summaryrefslogtreecommitdiff
path: root/partnerconfig
diff options
context:
space:
mode:
authorSetup Wizard Team <android-setup-team-eng@google.com>2019-03-14 10:00:10 +0800
committerpastychang <pastychang@google.com>2019-03-15 10:37:13 +0800
commit1ed3073417396ad4d3bec9d6a5722b490a49e47e (patch)
tree6be9a1c1b6f1d6bbba588ccc23cbd069bad56622 /partnerconfig
parentb5345f3d3b611fcf3513c613d1663f424414a12f (diff)
downloadsetupcompat-1ed3073417396ad4d3bec9d6a5722b490a49e47e.tar.gz
Import updated Android SetupCompat Library 238357591
Test: mm PiperOrigin-RevId: 238357591 Change-Id: Ifa32c7db8d5383f076582aeb7b44f42499a1217a
Diffstat (limited to 'partnerconfig')
-rw-r--r--partnerconfig/AndroidManifest.xml24
-rw-r--r--partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfig.java168
-rw-r--r--partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigHelper.java325
-rw-r--r--partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigKey.java165
-rw-r--r--partnerconfig/java/com/google/android/setupcompat/partnerconfig/ResourceEntry.java86
5 files changed, 768 insertions, 0 deletions
diff --git a/partnerconfig/AndroidManifest.xml b/partnerconfig/AndroidManifest.xml
new file mode 100644
index 0000000..c95a4dd
--- /dev/null
+++ b/partnerconfig/AndroidManifest.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.google.android.setupcompat.partnerconfig">
+
+ <uses-sdk
+ android:minSdkVersion="14"
+ android:targetSdkVersion="28" />
+</manifest>
diff --git a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfig.java b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfig.java
new file mode 100644
index 0000000..d2ae023
--- /dev/null
+++ b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfig.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright 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.google.android.setupcompat.partnerconfig;
+
+// TODO(b/121371322): optimize the enum
+/** Resources that can be customized by partner overlay APK. */
+public enum PartnerConfig {
+
+ // Status bar background color or illustration.
+ CONFIG_STATUS_BAR_BACKGROUND(PartnerConfigKey.KEY_STATUS_BAR_BACKGROUND, ResourceType.DRAWABLE),
+
+ // The same as "WindowLightStatusBar". If set true, the status bar icons will be drawn such
+ // that it is compatible with a light status bar background
+ CONFIG_LIGHT_STATUS_BAR(PartnerConfigKey.KEY_LIGHT_STATUS_BAR, ResourceType.BOOL),
+
+ // Navigation bar background color
+ CONFIG_NAVIGATION_BAR_BG_COLOR(PartnerConfigKey.KEY_NAVIGATION_BAR_BG_COLOR, ResourceType.COLOR),
+
+ // Background color of the footer bar.
+ CONFIG_FOOTER_BAR_BG_COLOR(PartnerConfigKey.KEY_FOOTER_BAR_BG_COLOR, ResourceType.COLOR),
+
+ // The same as "windowLightNavigationBar". If set true, the navigation bar icons will be drawn
+ // such that it is compatible with a light navigation bar background.
+ CONFIG_LIGHT_NAVIGATION_BAR(PartnerConfigKey.KEY_LIGHT_NAVIGATION_BAR, ResourceType.BOOL),
+
+ // The font face used in footer buttons. This must be a string reference to a font that is
+ // available in the system. Font references (@font or @xml) are not allowed.
+ CONFIG_FOOTER_BUTTON_FONT_FAMILY(
+ PartnerConfigKey.KEY_FOOTER_BUTTON_FONT_FAMILY, ResourceType.STRING),
+
+ // The icon for "add another" action. Can be "@null" for no icon.
+ CONFIG_FOOTER_BUTTON_ICON_ADD_ANOTHER(
+ PartnerConfigKey.KEY_FOOTER_BUTTON_ICON_ADD_ANOTHER, ResourceType.DRAWABLE),
+
+ // The icon for "cancel" action. Can be "@null" for no icon.
+ CONFIG_FOOTER_BUTTON_ICON_CANCEL(
+ PartnerConfigKey.KEY_FOOTER_BUTTON_ICON_CANCEL, ResourceType.DRAWABLE),
+
+ // The icon for "clear" action. Can be "@null" for no icon.
+ CONFIG_FOOTER_BUTTON_ICON_CLEAR(
+ PartnerConfigKey.KEY_FOOTER_BUTTON_ICON_CLEAR, ResourceType.DRAWABLE),
+
+ // The icon for "done" action. Can be "@null" for no icon.
+ CONFIG_FOOTER_BUTTON_ICON_DONE(
+ PartnerConfigKey.KEY_FOOTER_BUTTON_ICON_DONE, ResourceType.DRAWABLE),
+
+ // The icon for "next" action. Can be "@null" for no icon.
+ CONFIG_FOOTER_BUTTON_ICON_NEXT(
+ PartnerConfigKey.KEY_FOOTER_BUTTON_ICON_NEXT, ResourceType.DRAWABLE),
+
+ // The icon for "opt-in" action. Can be "@null" for no icon.
+ CONFIG_FOOTER_BUTTON_ICON_OPT_IN(
+ PartnerConfigKey.KEY_FOOTER_BUTTON_ICON_OPT_IN, ResourceType.DRAWABLE),
+
+ // The icon for "skip" action. Can be "@null" for no icon.
+ CONFIG_FOOTER_BUTTON_ICON_SKIP(
+ PartnerConfigKey.KEY_FOOTER_BUTTON_ICON_SKIP, ResourceType.DRAWABLE),
+
+ // The icon for "stop" action. Can be "@null" for no icon.
+ CONFIG_FOOTER_BUTTON_ICON_STOP(
+ PartnerConfigKey.KEY_FOOTER_BUTTON_ICON_STOP, ResourceType.DRAWABLE),
+
+ // Top padding of the footer buttons
+ CONFIG_FOOTER_BUTTON_PADDING_TOP(
+ PartnerConfigKey.KEY_FOOTER_BUTTON_PADDING_TOP, ResourceType.DIMENSION),
+
+ // Bottom padding of the footer buttons
+ CONFIG_FOOTER_BUTTON_PADDING_BOTTOM(
+ PartnerConfigKey.KEY_FOOTER_BUTTON_PADDING_BOTTOM, ResourceType.DIMENSION),
+
+ // Corner radius of the footer buttons
+ CONFIG_FOOTER_BUTTON_RADIUS(PartnerConfigKey.KEY_FOOTER_BUTTON_RADIUS, ResourceType.DIMENSION),
+
+ // Ripple color alpha the footer buttons
+ CONFIG_FOOTER_BUTTON_RIPPLE_COLOR_ALPHA(
+ PartnerConfigKey.KEY_FOOTER_BUTTON_RIPPLE_ALPHA, ResourceType.FRACTION),
+
+ // Text size of the primary footer button
+ CONFIG_FOOTER_BUTTON_TEXT_SIZE(
+ PartnerConfigKey.KEY_FOOTER_BUTTON_TEXT_SIZE, ResourceType.DIMENSION),
+
+ // Background color of the primary footer button
+ CONFIG_FOOTER_PRIMARY_BUTTON_BG_COLOR(
+ PartnerConfigKey.KEY_FOOTER_PRIMARY_BUTTON_BG_COLOR, ResourceType.COLOR),
+
+ // Text color of the primary footer button
+ CONFIG_FOOTER_PRIMARY_BUTTON_TEXT_COLOR(
+ PartnerConfigKey.KEY_FOOTER_PRIMARY_BUTTON_TEXT_COLOR, ResourceType.COLOR),
+
+ // Background color of the secondary footer button
+ CONFIG_FOOTER_SECONDARY_BUTTON_BG_COLOR(
+ PartnerConfigKey.KEY_FOOTER_SECONDARY_BUTTON_BG_COLOR, ResourceType.COLOR),
+
+ // Text color of the secondary footer button
+ CONFIG_FOOTER_SECONDARY_BUTTON_TEXT_COLOR(
+ PartnerConfigKey.KEY_FOOTER_SECONDARY_BUTTON_TEXT_COLOR, ResourceType.COLOR),
+
+ // Background color of layout
+ CONFIG_LAYOUT_BACKGROUND_COLOR(PartnerConfigKey.KEY_LAYOUT_BACKGROUND_COLOR, ResourceType.COLOR),
+
+ // Text color of the header
+ CONFIG_HEADER_TEXT_COLOR(PartnerConfigKey.KEY_HEADER_TEXT_COLOR, ResourceType.COLOR),
+
+ // Text size of the header
+ CONFIG_HEADER_TEXT_SIZE(PartnerConfigKey.KEY_HEADER_TEXT_SIZE, ResourceType.DIMENSION),
+
+ // Font family of the header
+ CONFIG_HEADER_FONT_FAMILY(PartnerConfigKey.KEY_HEADER_FONT_FAMILY, ResourceType.STRING),
+
+ // Gravity of the header, icon and description
+ CONFIG_LAYOUT_GRAVITY(PartnerConfigKey.KEY_LAYOUT_GRAVITY, ResourceType.STRING),
+
+ // Background color of the header area
+ CONFIG_HEADER_AREA_BACKGROUND_COLOR(
+ PartnerConfigKey.KEY_HEADER_AREA_BACKGROUND_COLOR, ResourceType.COLOR),
+
+ // Text size of the description
+ CONFIG_DESCRIPTION_TEXT_SIZE(PartnerConfigKey.KEY_DESCRIPTION_TEXT_SIZE, ResourceType.DIMENSION),
+
+ // Text color of the description
+ CONFIG_DESCRIPTION_TEXT_COLOR(PartnerConfigKey.KEY_DESCRIPTION_TEXT_COLOR, ResourceType.COLOR),
+
+ // Link text color of the description
+ CONFIG_DESCRIPTION_LINK_TEXT_COLOR(
+ PartnerConfigKey.KEY_DESCRIPTION_LINK_TEXT_COLOR, ResourceType.COLOR),
+
+ // Font family of the description
+ CONFIG_DESCRIPTION_FONT_FAMILY(PartnerConfigKey.KEY_DESCRIPTION_FONT_FAMILY, ResourceType.STRING);
+
+ public enum ResourceType {
+ BOOL,
+ COLOR,
+ DRAWABLE,
+ STRING,
+ DIMENSION,
+ FRACTION;
+ }
+
+ private final String resourceName;
+ private final ResourceType resourceType;
+
+ public ResourceType getResourceType() {
+ return resourceType;
+ }
+
+ public String getResourceName() {
+ return resourceName;
+ }
+
+ PartnerConfig(@PartnerConfigKey String resourceName, ResourceType type) {
+ this.resourceName = resourceName;
+ this.resourceType = type;
+ }
+}
diff --git a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigHelper.java b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigHelper.java
new file mode 100644
index 0000000..6fb391c
--- /dev/null
+++ b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigHelper.java
@@ -0,0 +1,325 @@
+/*
+ * Copyright 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.google.android.setupcompat.partnerconfig;
+
+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.Build;
+import android.os.Build.VERSION_CODES;
+import android.os.Bundle;
+import androidx.annotation.ColorInt;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import android.util.Log;
+import android.util.TypedValue;
+import com.google.android.setupcompat.partnerconfig.PartnerConfig.ResourceType;
+import java.util.EnumMap;
+
+/** The helper reads and caches the partner configurations from SUW. */
+public class PartnerConfigHelper {
+
+ private static final String TAG = PartnerConfigHelper.class.getSimpleName();
+
+ @VisibleForTesting
+ public static final String SUW_AUTHORITY = "com.google.android.setupwizard.partner";
+
+ @VisibleForTesting public static final String SUW_GET_PARTNER_CONFIG_METHOD = "getOverlayConfig";
+ private static PartnerConfigHelper instance = null;
+
+ @VisibleForTesting Bundle resultBundle = null;
+
+ @VisibleForTesting
+ final EnumMap<PartnerConfig, Object> partnerResourceCache = new EnumMap<>(PartnerConfig.class);
+
+ public static synchronized PartnerConfigHelper get(@NonNull Context context) {
+ if (instance == null) {
+ instance = new PartnerConfigHelper(context);
+ }
+ return instance;
+ }
+
+ private PartnerConfigHelper(Context context) {
+ getPartnerConfigBundle(context);
+ }
+
+ /**
+ * Returns the color of given {@code resourceConfig}, or 0 if the given {@code resourceConfig} is
+ * not found. If the {@code ResourceType} of the given {@code resourceConfig} is not color,
+ * IllegalArgumentException will be thrown.
+ *
+ * @param context The context of client activity
+ * @param resourceConfig The {@code PartnerConfig} of target resource
+ */
+ @ColorInt
+ public int getColor(@NonNull Context context, PartnerConfig resourceConfig) {
+ if (resourceConfig.getResourceType() != ResourceType.COLOR) {
+ throw new IllegalArgumentException("Not a color resource");
+ }
+
+ if (partnerResourceCache.containsKey(resourceConfig)) {
+ return (int) partnerResourceCache.get(resourceConfig);
+ }
+
+ int result = 0;
+ try {
+ String resourceName = resourceConfig.getResourceName();
+ ResourceEntry resourceEntry = getResourceEntryFromKey(resourceName);
+ Resources resource = getResourcesByPackageName(context, resourceEntry.getPackageName());
+ if (Build.VERSION.SDK_INT >= VERSION_CODES.M) {
+ result = resource.getColor(resourceEntry.getResourceId(), null);
+ } else {
+ result = resource.getColor(resourceEntry.getResourceId());
+ }
+ partnerResourceCache.put(resourceConfig, result);
+ } catch (PackageManager.NameNotFoundException | NullPointerException exception) {
+ // fall through
+ }
+ return result;
+ }
+
+ /**
+ * Returns the {@code Drawable} of given {@code resourceConfig}, or {@code null} if the given
+ * {@code resourceConfig} 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 resourceConfig The {@code PartnerConfig} of target resource
+ */
+ @Nullable
+ public Drawable getDrawable(@NonNull Context context, PartnerConfig resourceConfig) {
+ if (resourceConfig.getResourceType() != ResourceType.DRAWABLE) {
+ throw new IllegalArgumentException("Not a drawable resource");
+ }
+
+ if (partnerResourceCache.containsKey(resourceConfig)) {
+ return (Drawable) partnerResourceCache.get(resourceConfig);
+ }
+
+ Drawable result = null;
+ try {
+ ResourceEntry resourceEntry = getResourceEntryFromKey(resourceConfig.getResourceName());
+ 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;
+ }
+
+ if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
+ result = resource.getDrawable(resourceEntry.getResourceId(), null);
+ } else {
+ result = resource.getDrawable(resourceEntry.getResourceId());
+ }
+ partnerResourceCache.put(resourceConfig, result);
+ } catch (PackageManager.NameNotFoundException
+ | NullPointerException
+ | NotFoundException exception) {
+ // fall through
+ }
+ return result;
+ }
+
+ /**
+ * Returns the string of the given {@code resourceConfig}, or {@code null} if the given {@code
+ * resourceConfig} is not found. If the {@code ResourceType} of the given {@code resourceConfig}
+ * is not string, IllegalArgumentException will be thrown.
+ *
+ * @param context The context of client activity
+ * @param resourceConfig The {@code PartnerConfig} of target resource
+ */
+ @Nullable
+ public String getString(@NonNull Context context, PartnerConfig resourceConfig) {
+ if (resourceConfig.getResourceType() != ResourceType.STRING) {
+ throw new IllegalArgumentException("Not a string resource");
+ }
+
+ if (partnerResourceCache.containsKey(resourceConfig)) {
+ return (String) partnerResourceCache.get(resourceConfig);
+ }
+
+ String result = null;
+ try {
+ ResourceEntry resourceEntry = getResourceEntryFromKey(resourceConfig.getResourceName());
+ Resources resource = getResourcesByPackageName(context, resourceEntry.getPackageName());
+ result = resource.getString(resourceEntry.getResourceId());
+ partnerResourceCache.put(resourceConfig, result);
+ } catch (PackageManager.NameNotFoundException | NullPointerException exception) {
+ // fall through
+ }
+ return result;
+ }
+
+ /**
+ * Returns the boolean of given {@code resourceConfig}, or {@code defaultValue} if the given
+ * {@code resourceName} is not found. If the {@code ResourceType} of the given {@code
+ * resourceConfig} is not boolean, IllegalArgumentException will be thrown.
+ *
+ * @param context The context of client activity
+ * @param resourceConfig The {@code PartnerConfig} of target resource
+ * @param defaultValue The default value
+ */
+ public boolean getBoolean(
+ @NonNull Context context, PartnerConfig resourceConfig, boolean defaultValue) {
+ if (resourceConfig.getResourceType() != ResourceType.BOOL) {
+ throw new IllegalArgumentException("Not a bool resource");
+ }
+
+ if (partnerResourceCache.containsKey(resourceConfig)) {
+ return (boolean) partnerResourceCache.get(resourceConfig);
+ }
+
+ boolean result = defaultValue;
+ try {
+ ResourceEntry resourceEntry = getResourceEntryFromKey(resourceConfig.getResourceName());
+ Resources resource = getResourcesByPackageName(context, resourceEntry.getPackageName());
+ result = resource.getBoolean(resourceEntry.getResourceId());
+ partnerResourceCache.put(resourceConfig, result);
+ } catch (PackageManager.NameNotFoundException | NullPointerException exception) {
+ // fall through
+ }
+ return result;
+ }
+
+ /**
+ * Returns the dimension of given {@code resourceConfig}. 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 resourceConfig}. If the given {@code resourceConfig} 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 resourceConfig The {@code PartnerConfig} of target resource
+ * @param defaultValue The default value
+ */
+ public float getDimension(
+ @NonNull Context context, PartnerConfig resourceConfig, float defaultValue) {
+ if (resourceConfig.getResourceType() != ResourceType.DIMENSION) {
+ throw new IllegalArgumentException("Not a dimension resource");
+ }
+
+ if (partnerResourceCache.containsKey(resourceConfig)) {
+ return (float) partnerResourceCache.get(resourceConfig);
+ }
+
+ float result = defaultValue;
+ try {
+ ResourceEntry resourceEntry = getResourceEntryFromKey(resourceConfig.getResourceName());
+ Resources resource = getResourcesByPackageName(context, resourceEntry.getPackageName());
+ result = resource.getDimension(resourceEntry.getResourceId());
+ partnerResourceCache.put(resourceConfig, result);
+ } catch (PackageManager.NameNotFoundException | NullPointerException exception) {
+ // fall through
+ }
+ return result;
+ }
+
+ /**
+ * Returns the float of given {@code resourceConfig}. The default return value is 0.
+ *
+ * @param context The context of client activity
+ * @param resourceConfig The {@code PartnerConfig} of target resource
+ */
+ public float getFraction(@NonNull Context context, PartnerConfig resourceConfig) {
+ return getFraction(context, resourceConfig, 0.0f);
+ }
+
+ /**
+ * Returns the float of given {@code resourceConfig}. If the given {@code resourceConfig} not
+ * found, will return {@code defaultValue}. If the {@code ResourceType} of given {@code
+ * resourceConfig} is not fraction, will throw IllegalArgumentException.
+ *
+ * @param context The context of client activity
+ * @param resourceConfig The {@code PartnerConfig} of target resource
+ * @param defaultValue The default value
+ */
+ public float getFraction(
+ @NonNull Context context, PartnerConfig resourceConfig, float defaultValue) {
+ if (resourceConfig.getResourceType() != ResourceType.FRACTION) {
+ throw new IllegalArgumentException("Not a fraction resource");
+ }
+
+ if (partnerResourceCache.containsKey(resourceConfig)) {
+ return (float) partnerResourceCache.get(resourceConfig);
+ }
+
+ float result = defaultValue;
+ try {
+ ResourceEntry resourceEntry = getResourceEntryFromKey(resourceConfig.getResourceName());
+ Resources resource = getResourcesByPackageName(context, resourceEntry.getPackageName());
+ result = resource.getFraction(resourceEntry.getResourceId(), 1, 1);
+ partnerResourceCache.put(resourceConfig, result);
+ } catch (PackageManager.NameNotFoundException | NullPointerException exception) {
+ // fall through
+ }
+ return result;
+ }
+
+ private void getPartnerConfigBundle(Context context) {
+ if (resultBundle == null || resultBundle.isEmpty()) {
+ try {
+ Uri contentUri =
+ new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SUW_AUTHORITY)
+ .appendPath(SUW_GET_PARTNER_CONFIG_METHOD)
+ .build();
+ resultBundle =
+ context
+ .getContentResolver()
+ .call(
+ contentUri, SUW_GET_PARTNER_CONFIG_METHOD, /* arg= */ null, /* extras= */ null);
+ partnerResourceCache.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 (resultBundle == null) {
+ return null;
+ }
+ return ResourceEntry.fromBundle(resultBundle.getBundle(resourceName));
+ }
+
+ @VisibleForTesting
+ public static synchronized void resetForTesting() {
+ instance = null;
+ }
+}
diff --git a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigKey.java b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigKey.java
new file mode 100644
index 0000000..0c0c44f
--- /dev/null
+++ b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/PartnerConfigKey.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright 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.google.android.setupcompat.partnerconfig;
+
+import androidx.annotation.StringDef;
+import androidx.annotation.VisibleForTesting;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/** Resource names that can be customized by partner overlay APK. */
+@Retention(RetentionPolicy.SOURCE)
+@StringDef({
+ PartnerConfigKey.KEY_STATUS_BAR_BACKGROUND,
+ PartnerConfigKey.KEY_LIGHT_STATUS_BAR,
+ PartnerConfigKey.KEY_NAVIGATION_BAR_BG_COLOR,
+ PartnerConfigKey.KEY_LIGHT_NAVIGATION_BAR,
+ PartnerConfigKey.KEY_FOOTER_BAR_BG_COLOR,
+ PartnerConfigKey.KEY_FOOTER_BUTTON_FONT_FAMILY,
+ PartnerConfigKey.KEY_FOOTER_BUTTON_ICON_ADD_ANOTHER,
+ PartnerConfigKey.KEY_FOOTER_BUTTON_ICON_CANCEL,
+ PartnerConfigKey.KEY_FOOTER_BUTTON_ICON_CLEAR,
+ PartnerConfigKey.KEY_FOOTER_BUTTON_ICON_DONE,
+ PartnerConfigKey.KEY_FOOTER_BUTTON_ICON_NEXT,
+ PartnerConfigKey.KEY_FOOTER_BUTTON_ICON_OPT_IN,
+ PartnerConfigKey.KEY_FOOTER_BUTTON_ICON_SKIP,
+ PartnerConfigKey.KEY_FOOTER_BUTTON_ICON_STOP,
+ PartnerConfigKey.KEY_FOOTER_BUTTON_PADDING_TOP,
+ PartnerConfigKey.KEY_FOOTER_BUTTON_PADDING_BOTTOM,
+ PartnerConfigKey.KEY_FOOTER_BUTTON_RADIUS,
+ PartnerConfigKey.KEY_FOOTER_BUTTON_RIPPLE_ALPHA,
+ PartnerConfigKey.KEY_FOOTER_BUTTON_TEXT_SIZE,
+ PartnerConfigKey.KEY_FOOTER_PRIMARY_BUTTON_BG_COLOR,
+ PartnerConfigKey.KEY_FOOTER_PRIMARY_BUTTON_TEXT_COLOR,
+ PartnerConfigKey.KEY_FOOTER_SECONDARY_BUTTON_BG_COLOR,
+ PartnerConfigKey.KEY_FOOTER_SECONDARY_BUTTON_TEXT_COLOR,
+ PartnerConfigKey.KEY_LAYOUT_BACKGROUND_COLOR,
+ PartnerConfigKey.KEY_HEADER_TEXT_SIZE,
+ PartnerConfigKey.KEY_HEADER_TEXT_COLOR,
+ PartnerConfigKey.KEY_HEADER_FONT_FAMILY,
+ PartnerConfigKey.KEY_HEADER_AREA_BACKGROUND_COLOR,
+ PartnerConfigKey.KEY_LAYOUT_GRAVITY,
+ PartnerConfigKey.KEY_DESCRIPTION_TEXT_SIZE,
+ PartnerConfigKey.KEY_DESCRIPTION_TEXT_COLOR,
+ PartnerConfigKey.KEY_DESCRIPTION_LINK_TEXT_COLOR,
+ PartnerConfigKey.KEY_DESCRIPTION_FONT_FAMILY,
+})
+// TODO(b/121371322): can be removed and always reference PartnerConfig.getResourceName()?
+@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+public @interface PartnerConfigKey {
+ // Status bar background color or illustration.
+ String KEY_STATUS_BAR_BACKGROUND = "setup_compat_status_bar_background";
+
+ // The same as "WindowLightStatusBar". If set true, the status bar icons will be drawn such
+ // that it is compatible with a light status bar background
+ String KEY_LIGHT_STATUS_BAR = "setup_compat_light_status_bar";
+
+ // Navigation bar background color
+ String KEY_NAVIGATION_BAR_BG_COLOR = "setup_compat_navigation_bar_bg_color";
+
+ // The same as "windowLightNavigationBar". If set true, the navigation bar icons will be drawn
+ // such that it is compatible with a light navigation bar background.
+ String KEY_LIGHT_NAVIGATION_BAR = "setup_compat_light_navigation_bar";
+
+ // Background color of the footer bar.
+ String KEY_FOOTER_BAR_BG_COLOR = "setup_compat_footer_bar_bg_color";
+
+ // The font face used in footer buttons. This must be a string reference to a font that is
+ // available in the system. Font references (@font or @xml) are not allowed.
+ String KEY_FOOTER_BUTTON_FONT_FAMILY = "setup_compat_footer_button_font_family";
+
+ // The icon for "add another" action. Can be "@null" for no icon.
+ String KEY_FOOTER_BUTTON_ICON_ADD_ANOTHER = "setup_compat_footer_button_icon_add_another";
+
+ // The icon for "cancel" action. Can be "@null" for no icon.
+ String KEY_FOOTER_BUTTON_ICON_CANCEL = "setup_compat_footer_button_icon_cancel";
+
+ // The icon for "clear" action. Can be "@null" for no icon.
+ String KEY_FOOTER_BUTTON_ICON_CLEAR = "setup_compat_footer_button_icon_clear";
+
+ // The icon for "done" action. Can be "@null" for no icon.
+ String KEY_FOOTER_BUTTON_ICON_DONE = "setup_compat_footer_button_icon_done";
+
+ // The icon for "next" action. Can be "@null" for no icon.
+ String KEY_FOOTER_BUTTON_ICON_NEXT = "setup_compat_footer_button_icon_next";
+
+ // The icon for "opt-in" action. Can be "@null" for no icon.
+ String KEY_FOOTER_BUTTON_ICON_OPT_IN = "setup_compat_footer_button_icon_opt_in";
+
+ // The icon for "skip" action. Can be "@null" for no icon.
+ String KEY_FOOTER_BUTTON_ICON_SKIP = "setup_compat_footer_button_icon_skip";
+
+ // The icon for "stop" action. Can be "@null" for no icon.
+ String KEY_FOOTER_BUTTON_ICON_STOP = "setup_compat_footer_button_icon_stop";
+
+ // Top padding of the footer buttons
+ String KEY_FOOTER_BUTTON_PADDING_TOP = "setup_compat_footer_button_padding_top";
+
+ // Bottom padding of the footer buttons
+ String KEY_FOOTER_BUTTON_PADDING_BOTTOM = "setup_compat_footer_button_padding_bottom";
+
+ // Corner radius of the footer buttons
+ String KEY_FOOTER_BUTTON_RADIUS = "setup_compat_footer_button_radius";
+
+ // Ripple color alpha of the footer button
+ String KEY_FOOTER_BUTTON_RIPPLE_ALPHA = "setup_compat_footer_button_ripple_alpha";
+
+ // Text size of the footer button
+ String KEY_FOOTER_BUTTON_TEXT_SIZE = "setup_compat_footer_button_text_size";
+
+ // Background color of the primary footer button
+ String KEY_FOOTER_PRIMARY_BUTTON_BG_COLOR = "setup_compat_footer_primary_button_bg_color";
+
+ // Text color of the primary footer button
+ String KEY_FOOTER_PRIMARY_BUTTON_TEXT_COLOR = "setup_compat_footer_primary_button_text_color";
+
+ // Background color of the secondary footer button
+ String KEY_FOOTER_SECONDARY_BUTTON_BG_COLOR = "setup_compat_footer_secondary_button_bg_color";
+
+ // Text color of the secondary footer button
+ String KEY_FOOTER_SECONDARY_BUTTON_TEXT_COLOR = "setup_compat_footer_secondary_button_text_color";
+
+ // Background color of layout
+ String KEY_LAYOUT_BACKGROUND_COLOR = "setup_compat_layout_bg_color";
+
+ // Text size of the header
+ String KEY_HEADER_TEXT_SIZE = "setup_design_header_text_size";
+
+ // Text color of the header
+ String KEY_HEADER_TEXT_COLOR = "setup_design_header_text_color";
+
+ // Font family of the header
+ String KEY_HEADER_FONT_FAMILY = "setup_design_header_font_family";
+
+ // Gravity of the header, icon and description
+ String KEY_LAYOUT_GRAVITY = "setup_design_layout_gravity";
+
+ // Background color of the header area
+ String KEY_HEADER_AREA_BACKGROUND_COLOR = "setup_design_header_area_background_color";
+
+ // Text size of the description
+ String KEY_DESCRIPTION_TEXT_SIZE = "setup_design_description_text_size";
+
+ // Text color of the description
+ String KEY_DESCRIPTION_TEXT_COLOR = "setup_design_description_text_color";
+
+ // Link text color of the description
+ String KEY_DESCRIPTION_LINK_TEXT_COLOR = "setup_design_description_link_text_color";
+
+ // Font family of the description
+ String KEY_DESCRIPTION_FONT_FAMILY = "setup_design_description_font_family";
+}
diff --git a/partnerconfig/java/com/google/android/setupcompat/partnerconfig/ResourceEntry.java b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/ResourceEntry.java
new file mode 100644
index 0000000..2794f22
--- /dev/null
+++ b/partnerconfig/java/com/google/android/setupcompat/partnerconfig/ResourceEntry.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 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.google.android.setupcompat.partnerconfig;
+
+import android.os.Bundle;
+import androidx.annotation.VisibleForTesting;
+
+/**
+ * A potentially cross-package resource entry, which can then be retrieved using {@link
+ * PackageManager#getApplicationForResources}. 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 packageName;
+ private final String resourceName;
+ private final int resourceId;
+
+ /**
+ * 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(Bundle bundle) {
+ String packageName;
+ String resourceName;
+ int resourceId;
+ if (!bundle.containsKey(KEY_PACKAGE_NAME)
+ || !bundle.containsKey(KEY_RESOURCE_NAME)
+ || !bundle.containsKey(KEY_RESOURCE_ID)) {
+ return null;
+ }
+ packageName = bundle.getString(KEY_PACKAGE_NAME);
+ resourceName = bundle.getString(KEY_RESOURCE_NAME);
+ resourceId = bundle.getInt(KEY_RESOURCE_ID);
+ return new ResourceEntry(packageName, resourceName, resourceId);
+ }
+
+ public ResourceEntry(String packageName, String resourceName, int resourceId) {
+ this.packageName = packageName;
+ this.resourceName = resourceName;
+ this.resourceId = resourceId;
+ }
+
+ public String getPackageName() {
+ return this.packageName;
+ }
+
+ public String getResourceName() {
+ return this.resourceName;
+ }
+
+ public int getResourceId() {
+ return this.resourceId;
+ }
+
+ /**
+ * 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, packageName);
+ result.putString(KEY_RESOURCE_NAME, resourceName);
+ result.putInt(KEY_RESOURCE_ID, resourceId);
+ return result;
+ }
+}