PhoneAccounts include literal icon bitmap (3/4)

Change-Id: Ie3f02a5032b01e91d4620134bb7917cddd8b93e6
diff --git a/src/com/android/server/telecom/PhoneAccountRegistrar.java b/src/com/android/server/telecom/PhoneAccountRegistrar.java
index b5c078c..bb23123 100644
--- a/src/com/android/server/telecom/PhoneAccountRegistrar.java
+++ b/src/com/android/server/telecom/PhoneAccountRegistrar.java
@@ -21,13 +21,12 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.os.Environment;
-import android.os.UserHandle;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.provider.Settings;
 import android.telecom.ConnectionService;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
-import android.telecom.TelecomManager;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.SubscriptionManager;
 import android.content.ComponentName;
@@ -35,6 +34,7 @@
 import android.net.Uri;
 import android.text.TextUtils;
 import android.util.AtomicFile;
+import android.util.Base64;
 import android.util.Xml;
 
 // TODO: Needed for move to system service: import com.android.internal.R;
@@ -49,6 +49,7 @@
 
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
@@ -58,7 +59,6 @@
 import java.lang.SecurityException;
 import java.lang.String;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
@@ -84,7 +84,7 @@
 
     private static final String FILE_NAME = "phone-account-registrar-state.xml";
     @VisibleForTesting
-    public static final int EXPECTED_STATE_VERSION = 3;
+    public static final int EXPECTED_STATE_VERSION = 4;
 
     /** Keep in sync with the same in SipSettings.java */
     private static final String SIP_SHARED_PREFERENCES = "SIP_PREFERENCES";
@@ -675,7 +675,7 @@
         public abstract T readFromXml(XmlPullParser parser, int version, Context context)
                 throws IOException, XmlPullParserException;
 
-        protected void writeTextSafely(String tagName, Object value, XmlSerializer serializer)
+        protected void writeTextIfNonNull(String tagName, Object value, XmlSerializer serializer)
                 throws IOException {
             if (value != null) {
                 serializer.startTag(null, tagName);
@@ -710,7 +710,20 @@
                 serializer.attribute(null, LENGTH_ATTRIBUTE, "0");
             }
             serializer.endTag(null, tagName);
+        }
 
+        protected void writeBitmapIfNonNull(String tagName, Bitmap value, XmlSerializer serializer)
+                throws IOException {
+            if (value != null && value.getByteCount() > 0) {
+                ByteArrayOutputStream stream = new ByteArrayOutputStream();
+                value.compress(Bitmap.CompressFormat.PNG, 100, stream);
+                byte[] imageByteArray = stream.toByteArray();
+                String text = Base64.encodeToString(imageByteArray, 0, imageByteArray.length, 0);
+
+                serializer.startTag(null, tagName);
+                serializer.text(text);
+                serializer.endTag(null, tagName);
+            }
         }
 
         /**
@@ -743,6 +756,12 @@
 
             return arrayEntries;
         }
+
+        protected Bitmap readBitmap(XmlPullParser parser)
+                throws IOException, XmlPullParserException {
+            byte[] imageByteArray = Base64.decode(parser.getText(), 0);
+            return BitmapFactory.decodeByteArray(imageByteArray, 0, imageByteArray.length);
+        }
     }
 
     @VisibleForTesting
@@ -830,12 +849,12 @@
         private static final String SUBSCRIPTION_ADDRESS = "subscription_number";
         private static final String CAPABILITIES = "capabilities";
         private static final String ICON_RES_ID = "icon_res_id";
+        private static final String ICON_PACKAGE_NAME = "icon_package_name";
+        private static final String ICON_BITMAP = "icon_bitmap";
         private static final String COLOR = "color";
         private static final String LABEL = "label";
         private static final String SHORT_DESCRIPTION = "short_description";
         private static final String SUPPORTED_URI_SCHEMES = "supported_uri_schemes";
-        private static final String TRUE = "true";
-        private static final String FALSE = "false";
 
         @Override
         public void writeToXml(PhoneAccount o, XmlSerializer serializer)
@@ -849,13 +868,15 @@
                     serializer.endTag(null, ACCOUNT_HANDLE);
                 }
 
-                writeTextSafely(ADDRESS, o.getAddress(), serializer);
-                writeTextSafely(SUBSCRIPTION_ADDRESS, o.getSubscriptionAddress(), serializer);
-                writeTextSafely(CAPABILITIES, Integer.toString(o.getCapabilities()), serializer);
-                writeTextSafely(ICON_RES_ID, Integer.toString(o.getIconResId()), serializer);
-                writeTextSafely(COLOR, Integer.toString(o.getColor()), serializer);
-                writeTextSafely(LABEL, o.getLabel(), serializer);
-                writeTextSafely(SHORT_DESCRIPTION, o.getShortDescription(), serializer);
+                writeTextIfNonNull(ADDRESS, o.getAddress(), serializer);
+                writeTextIfNonNull(SUBSCRIPTION_ADDRESS, o.getSubscriptionAddress(), serializer);
+                writeTextIfNonNull(CAPABILITIES, Integer.toString(o.getCapabilities()), serializer);
+                writeTextIfNonNull(ICON_RES_ID, Integer.toString(o.getIconResId()), serializer);
+                writeTextIfNonNull(ICON_PACKAGE_NAME, o.getIconPackageName(), serializer);
+                writeBitmapIfNonNull(ICON_BITMAP, o.getIconBitmap(), serializer);
+                writeTextIfNonNull(COLOR, Integer.toString(o.getColor()), serializer);
+                writeTextIfNonNull(LABEL, o.getLabel(), serializer);
+                writeTextIfNonNull(SHORT_DESCRIPTION, o.getShortDescription(), serializer);
                 writeStringList(SUPPORTED_URI_SCHEMES, o.getSupportedUriSchemes(), serializer);
 
                 serializer.endTag(null, CLASS_PHONE_ACCOUNT);
@@ -871,6 +892,8 @@
                 Uri subscriptionAddress = null;
                 int capabilities = 0;
                 int iconResId = 0;
+                String iconPackageName = null;
+                Bitmap icon = null;
                 int color = 0;
                 String label = null;
                 String shortDescription = null;
@@ -894,6 +917,12 @@
                     } else if (parser.getName().equals(ICON_RES_ID)) {
                         parser.next();
                         iconResId = Integer.parseInt(parser.getText());
+                    } else if (parser.getName().equals(ICON_PACKAGE_NAME)) {
+                        parser.next();
+                        iconPackageName = parser.getText();
+                    } else if (parser.getName().equals(ICON_BITMAP)) {
+                        parser.next();
+                        icon = readBitmap(parser);
                     } else if (parser.getName().equals(COLOR)) {
                         parser.next();
                         color = Integer.parseInt(parser.getText());
@@ -934,6 +963,8 @@
                         .setSubscriptionAddress(subscriptionAddress)
                         .setCapabilities(capabilities)
                         .setIconResId(iconResId)
+                        .setIconPackageName(iconPackageName)
+                        .setIconBitmap(icon)
                         .setColor(color)
                         .setShortDescription(shortDescription)
                         .setSupportedUriSchemes(supportedUriSchemes)
@@ -970,11 +1001,11 @@
                 serializer.startTag(null, CLASS_PHONE_ACCOUNT_HANDLE);
 
                 if (o.getComponentName() != null) {
-                    writeTextSafely(
+                    writeTextIfNonNull(
                             COMPONENT_NAME, o.getComponentName().flattenToString(), serializer);
                 }
 
-                writeTextSafely(ID, o.getId(), serializer);
+                writeTextIfNonNull(ID, o.getId(), serializer);
 
                 serializer.endTag(null, CLASS_PHONE_ACCOUNT_HANDLE);
             }
diff --git a/tests/src/com/android/server/telecom/testapps/CallServiceNotifier.java b/tests/src/com/android/server/telecom/testapps/CallServiceNotifier.java
index b82f4af..a0959fa 100644
--- a/tests/src/com/android/server/telecom/testapps/CallServiceNotifier.java
+++ b/tests/src/com/android/server/telecom/testapps/CallServiceNotifier.java
@@ -24,6 +24,8 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.net.Uri;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
@@ -97,6 +99,10 @@
         TelecomManager telecomManager =
                 (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
 
+        Bitmap icon = BitmapFactory.decodeResource(
+                context.getResources(),
+                R.drawable.stat_sys_phone_call);
+
         telecomManager.clearAccounts();
 
         telecomManager.registerPhoneAccount(PhoneAccount.builder(
@@ -107,7 +113,7 @@
                 .setAddress(Uri.parse("tel:555-TEST"))
                 .setSubscriptionAddress(Uri.parse("tel:555-TEST"))
                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
-                .setIconResId(R.drawable.stat_sys_phone_call)
+                .setIconBitmap(icon)
                 .setShortDescription("a short description for the call provider")
                 .setSupportedUriSchemes(Arrays.asList("tel"))
                 .build());
@@ -121,7 +127,7 @@
                 .setSubscriptionAddress(Uri.parse("tel:555-TSIM"))
                 .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER |
                     PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
-                .setIconResId(R.drawable.stat_sys_phone_call)
+                .setIconBitmap(icon)
                 .setShortDescription("a short description for the sim subscription")
                 .build());
 
@@ -133,7 +139,7 @@
                 .setAddress(Uri.parse("tel:555-CMGR"))
                 .setSubscriptionAddress(Uri.parse("tel:555-CMGR"))
                 .setCapabilities(PhoneAccount.CAPABILITY_CONNECTION_MANAGER)
-                .setIconResId(R.drawable.stat_sys_phone_call)
+                .setIconBitmap(icon)
                 .setShortDescription("a short description for the connection manager")
                 .build());
     }
diff --git a/tests/src/com/android/server/telecom/tests/unit/PhoneAccountRegistrarTest.java b/tests/src/com/android/server/telecom/tests/unit/PhoneAccountRegistrarTest.java
index cd1bbd1..c2beb0b 100644
--- a/tests/src/com/android/server/telecom/tests/unit/PhoneAccountRegistrarTest.java
+++ b/tests/src/com/android/server/telecom/tests/unit/PhoneAccountRegistrarTest.java
@@ -19,12 +19,15 @@
 import com.android.internal.util.FastXmlSerializer;
 import com.android.server.telecom.Log;
 import com.android.server.telecom.PhoneAccountRegistrar;
+import com.android.server.telecom.tests.R;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlSerializer;
 
 import android.content.ComponentName;
 import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.net.Uri;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
@@ -187,15 +190,13 @@
                         "com.android.server.telecom.tests",
                         "com.android.server.telecom.tests.MockConnectionService"
                 ),
-                id
-        );
+                id);
     }
 
     private PhoneAccount.Builder makeQuickAccountBuilder(String id, int idx) {
         return new PhoneAccount.Builder(
                 makeQuickAccountHandle(id),
-                "label" + idx
-        );
+                "label" + idx);
     }
 
     private PhoneAccount makeQuickAccount(String id, int idx) {
@@ -203,7 +204,12 @@
                 .setAddress(Uri.parse("http://foo.com/" + idx))
                 .setSubscriptionAddress(Uri.parse("tel:555-000" + idx))
                 .setCapabilities(idx)
-                .setIconResId(idx)
+                .setIconResId(R.drawable.stat_sys_phone_call)
+                .setIconPackageName("com.android.server.telecom.tests")
+                .setIconBitmap(
+                        BitmapFactory.decodeResource(
+                                getContext().getResources(),
+                                R.drawable.stat_sys_phone_call))
                 .setShortDescription("desc" + idx)
                 .build();
     }
@@ -260,6 +266,8 @@
             assertEquals(a.getSubscriptionAddress(), b.getSubscriptionAddress());
             assertEquals(a.getCapabilities(), b.getCapabilities());
             assertEquals(a.getIconResId(), b.getIconResId());
+            assertEquals(a.getIconPackageName(), b.getIconPackageName());
+            assertBitmapEquals(a.getIconBitmap(), b.getIconBitmap());
             assertEquals(a.getColor(), b.getColor());
             assertEquals(a.getLabel(), b.getLabel());
             assertEquals(a.getShortDescription(), b.getShortDescription());
@@ -267,6 +275,16 @@
         }
     }
 
+    private static void assertBitmapEquals(Bitmap a, Bitmap b) {
+        assertEquals(a.getWidth(), b.getWidth());
+        assertEquals(a.getHeight(), b.getHeight());
+        for (int x = 0; x < a.getWidth(); x++) {
+            for (int y = 0; y < a.getHeight(); y++) {
+                assertEquals(a.getPixel(x, y), b.getPixel(x, y));
+            }
+        }
+    }
+
     private static void assertStateEquals(
             PhoneAccountRegistrar.State a, PhoneAccountRegistrar.State b) {
         assertPhoneAccountHandleEquals(a.defaultOutgoing, b.defaultOutgoing);