Add logic to parse previewImage from dreams.

Test: locally on device
Bug: 211662811
Change-Id: Icb782d87f7c83853ce5a746c94ee47621d56d207
diff --git a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
index c5e1c8d..6b9b750 100644
--- a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
@@ -17,6 +17,7 @@
 package com.android.settingslib.dream;
 
 import android.annotation.IntDef;
+import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -59,6 +60,7 @@
         public ComponentName componentName;
         public ComponentName settingsComponentName;
         public CharSequence description;
+        public Drawable previewImage;
 
         @Override
         public String toString() {
@@ -120,15 +122,22 @@
                 PackageManager.GET_META_DATA);
         List<DreamInfo> dreamInfos = new ArrayList<>(resolveInfos.size());
         for (ResolveInfo resolveInfo : resolveInfos) {
-            if (resolveInfo.serviceInfo == null)
+            if (resolveInfo.serviceInfo == null) {
                 continue;
+            }
             DreamInfo dreamInfo = new DreamInfo();
             dreamInfo.caption = resolveInfo.loadLabel(pm);
             dreamInfo.icon = resolveInfo.loadIcon(pm);
             dreamInfo.description = getDescription(resolveInfo, pm);
             dreamInfo.componentName = getDreamComponentName(resolveInfo);
             dreamInfo.isActive = dreamInfo.componentName.equals(activeDream);
-            dreamInfo.settingsComponentName = getSettingsComponentName(pm, resolveInfo);
+
+            final DreamMetadata dreamMetadata = getDreamMetadata(pm, resolveInfo);
+            if (dreamMetadata != null) {
+                dreamInfo.settingsComponentName = dreamMetadata.mSettingsActivity;
+                dreamInfo.previewImage = dreamMetadata.mPreviewImage;
+            }
+
             dreamInfos.add(dreamInfo);
         }
         Collections.sort(dreamInfos, mComparator);
@@ -325,57 +334,77 @@
     }
 
     private static ComponentName getDreamComponentName(ResolveInfo resolveInfo) {
-        if (resolveInfo == null || resolveInfo.serviceInfo == null)
+        if (resolveInfo == null || resolveInfo.serviceInfo == null) {
             return null;
+        }
         return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name);
     }
 
-    private static ComponentName getSettingsComponentName(PackageManager pm, ResolveInfo resolveInfo) {
-        if (resolveInfo == null
-                || resolveInfo.serviceInfo == null
-                || resolveInfo.serviceInfo.metaData == null)
+    private static final class DreamMetadata {
+        @Nullable
+        Drawable mPreviewImage;
+        @Nullable
+        ComponentName mSettingsActivity;
+    }
+
+    @Nullable
+    private static TypedArray readMetadata(PackageManager pm, ServiceInfo serviceInfo) {
+        if (serviceInfo == null || serviceInfo.metaData == null) {
             return null;
-        String cn = null;
-        XmlResourceParser parser = null;
-        Exception caughtException = null;
-        try {
-            parser = resolveInfo.serviceInfo.loadXmlMetaData(pm, DreamService.DREAM_META_DATA);
+        }
+        try (XmlResourceParser parser =
+                     serviceInfo.loadXmlMetaData(pm, DreamService.DREAM_META_DATA)) {
             if (parser == null) {
                 Log.w(TAG, "No " + DreamService.DREAM_META_DATA + " meta-data");
                 return null;
             }
-            Resources res = pm.getResourcesForApplication(resolveInfo.serviceInfo.applicationInfo);
+            Resources res = pm.getResourcesForApplication(serviceInfo.applicationInfo);
             AttributeSet attrs = Xml.asAttributeSet(parser);
-            int type;
-            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
-                    && type != XmlPullParser.START_TAG) {
+            while (true) {
+                final int type = parser.next();
+                if (type == XmlPullParser.END_DOCUMENT || type == XmlPullParser.START_TAG) {
+                    break;
+                }
             }
             String nodeName = parser.getName();
             if (!"dream".equals(nodeName)) {
                 Log.w(TAG, "Meta-data does not start with dream tag");
                 return null;
             }
-            TypedArray sa = res.obtainAttributes(attrs, com.android.internal.R.styleable.Dream);
-            cn = sa.getString(com.android.internal.R.styleable.Dream_settingsActivity);
-            sa.recycle();
-        } catch (PackageManager.NameNotFoundException|IOException|XmlPullParserException e) {
-            caughtException = e;
-        } finally {
-            if (parser != null) parser.close();
-        }
-        if (caughtException != null) {
-            Log.w(TAG, "Error parsing : " + resolveInfo.serviceInfo.packageName, caughtException);
+            return res.obtainAttributes(attrs, com.android.internal.R.styleable.Dream);
+        } catch (PackageManager.NameNotFoundException | IOException | XmlPullParserException e) {
+            Log.w(TAG, "Error parsing : " + serviceInfo.packageName, e);
             return null;
         }
-        if (cn != null && cn.indexOf('/') < 0) {
-            cn = resolveInfo.serviceInfo.packageName + "/" + cn;
+    }
+
+    private static ComponentName convertToComponentName(String flattenedString,
+            ServiceInfo serviceInfo) {
+        if (flattenedString == null) return null;
+
+        if (flattenedString.indexOf('/') < 0) {
+            flattenedString = serviceInfo.packageName + "/" + flattenedString;
         }
-        return cn == null ? null : ComponentName.unflattenFromString(cn);
+        return ComponentName.unflattenFromString(flattenedString);
+    }
+
+    private static DreamMetadata getDreamMetadata(PackageManager pm, ResolveInfo resolveInfo) {
+        DreamMetadata result = new DreamMetadata();
+        if (resolveInfo == null) return result;
+        TypedArray rawMetadata = readMetadata(pm, resolveInfo.serviceInfo);
+        if (rawMetadata == null) return result;
+        result.mSettingsActivity = convertToComponentName(rawMetadata.getString(
+                com.android.internal.R.styleable.Dream_settingsActivity), resolveInfo.serviceInfo);
+        result.mPreviewImage = rawMetadata.getDrawable(
+                com.android.internal.R.styleable.Dream_previewImage);
+        rawMetadata.recycle();
+        return result;
     }
 
     private static void logd(String msg, Object... args) {
-        if (DEBUG)
+        if (DEBUG) {
             Log.d(TAG, args == null || args.length == 0 ? msg : String.format(msg, args));
+        }
     }
 
     private static class DreamInfoComparator implements Comparator<DreamInfo> {