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/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;
+    }
+}