STK: Image/icon related fixes

1. Handle invalid images/icons
If the coding scheme of the image is not understood, then the
loading of the icon will fail.
Send a TR with ResultCode.PRFRMD_ICON_NOT_DISPLAYED back to
the card when this happens, but continue processing the command.

2. For Idle Mode Text the icon should be loaded even when text
is not present

BUG=22637125
Change-Id: Ie4199fe9ac00f14db2d6b12604fc2c9cf54208f5
diff --git a/src/java/com/android/internal/telephony/cat/CatCmdMessage.java b/src/java/com/android/internal/telephony/cat/CatCmdMessage.java
index fb470db..62d8869 100644
--- a/src/java/com/android/internal/telephony/cat/CatCmdMessage.java
+++ b/src/java/com/android/internal/telephony/cat/CatCmdMessage.java
@@ -34,7 +34,7 @@
     private ToneSettings mToneSettings = null;
     private CallSettings mCallSettings = null;
     private SetupEventListSettings mSetupEventListSettings = null;
-
+    private boolean mLoadIconFailed = false;
 
     /*
      * Container for Launch Browser command settings.
@@ -72,6 +72,7 @@
 
     CatCmdMessage(CommandParams cmdParams) {
         mCmdDet = cmdParams.mCmdDet;
+        mLoadIconFailed =  cmdParams.mLoadIconFailed;
         switch(getCmdType()) {
         case SET_UP_MENU:
         case SELECT_ITEM:
@@ -131,6 +132,7 @@
         mTextMsg = in.readParcelable(null);
         mMenu = in.readParcelable(null);
         mInput = in.readParcelable(null);
+        mLoadIconFailed = (in.readByte() == 1);
         switch (getCmdType()) {
         case LAUNCH_BROWSER:
             mBrowserSettings = new BrowserSettings();
@@ -164,6 +166,7 @@
         dest.writeParcelable(mTextMsg, 0);
         dest.writeParcelable(mMenu, 0);
         dest.writeParcelable(mInput, 0);
+        dest.writeByte((byte) (mLoadIconFailed ? 1 : 0));
         switch(getCmdType()) {
         case LAUNCH_BROWSER:
             dest.writeString(mBrowserSettings.url);
@@ -233,4 +236,12 @@
     public SetupEventListSettings getSetEventList() {
         return mSetupEventListSettings;
     }
+
+    /**
+     * API to be used by application to check if loading optional icon
+     * has failed
+     */
+    public boolean hasIconLoadFailed() {
+        return mLoadIconFailed;
+    }
 }
diff --git a/src/java/com/android/internal/telephony/cat/CatService.java b/src/java/com/android/internal/telephony/cat/CatService.java
old mode 100644
new mode 100755
index c4f1dfc..b5776a1
--- a/src/java/com/android/internal/telephony/cat/CatService.java
+++ b/src/java/com/android/internal/telephony/cat/CatService.java
@@ -371,6 +371,7 @@
         }
 
         CharSequence message;
+        ResultCode resultCode;
         CatCmdMessage cmdMsg = new CatCmdMessage(cmdParams);
         switch (cmdParams.getCommandType()) {
             case SET_UP_MENU:
@@ -379,7 +380,9 @@
                 } else {
                     mMenuCmd = cmdMsg;
                 }
-                sendTerminalResponse(cmdParams.mCmdDet, ResultCode.OK, false, 0, null);
+                resultCode = cmdParams.mLoadIconFailed ? ResultCode.PRFRMD_ICON_NOT_DISPLAYED
+                                                                            : ResultCode.OK;
+                sendTerminalResponse(cmdParams.mCmdDet, resultCode, false, 0, null);
                 break;
             case DISPLAY_TEXT:
                 break;
@@ -389,7 +392,9 @@
                 cmdParams.mCmdDet.typeOfCommand = CommandType.SET_UP_IDLE_MODE_TEXT.value();
                 break;
             case SET_UP_IDLE_MODE_TEXT:
-                sendTerminalResponse(cmdParams.mCmdDet, ResultCode.OK, false, 0, null);
+                resultCode = cmdParams.mLoadIconFailed ? ResultCode.PRFRMD_ICON_NOT_DISPLAYED
+                                                                            : ResultCode.OK;
+                sendTerminalResponse(cmdParams.mCmdDet,resultCode, false, 0, null);
                 break;
             case SET_UP_EVENT_LIST:
                 if (isSupportedSetupEventCommand(cmdMsg)) {
diff --git a/src/java/com/android/internal/telephony/cat/CommandParams.java b/src/java/com/android/internal/telephony/cat/CommandParams.java
index 93520f7..7dfedab 100644
--- a/src/java/com/android/internal/telephony/cat/CommandParams.java
+++ b/src/java/com/android/internal/telephony/cat/CommandParams.java
@@ -24,6 +24,8 @@
  */
 class CommandParams {
     CommandDetails mCmdDet;
+    // Variable to track if an optional icon load has failed.
+    boolean mLoadIconFailed = false;
 
     CommandParams(CommandDetails cmdDet) {
         mCmdDet = cmdDet;
diff --git a/src/java/com/android/internal/telephony/cat/CommandParamsFactory.java b/src/java/com/android/internal/telephony/cat/CommandParamsFactory.java
old mode 100644
new mode 100755
index ad84a82..2990da3
--- a/src/java/com/android/internal/telephony/cat/CommandParamsFactory.java
+++ b/src/java/com/android/internal/telephony/cat/CommandParamsFactory.java
@@ -46,6 +46,7 @@
     private CommandParams mCmdParams = null;
     private int mIconLoadState = LOAD_NO_ICON;
     private RilMessageDecoder mCaller = null;
+    private boolean mloadIcon = false;
 
     // constants
     static final int MSG_ID_LOAD_ICON_DONE = 1;
@@ -239,6 +240,15 @@
         int iconIndex = 0;
 
         if (data == null) {
+            CatLog.d(this, "Optional Icon data is NULL");
+            mCmdParams.mLoadIconFailed = true;
+            mloadIcon = false;
+            /** In case of icon load fail consider the
+            ** received proactive command as valid (sending RESULT OK) as
+            ** The result code, 'PRFRMD_ICON_NOT_DISPLAYED' will be added in the
+            ** terminal response by CatService/StkAppService if needed based on
+            ** the value of mLoadIconFailed.
+            */
             return ResultCode.OK;
         }
         switch(mIconLoadState) {
@@ -250,6 +260,10 @@
             // set each item icon.
             for (Bitmap icon : icons) {
                 mCmdParams.setIcon(icon);
+                if (icon == null && mloadIcon) {
+                    CatLog.d(this, "Optional Icon data is NULL while loading multi icons");
+                    mCmdParams.mLoadIconFailed = true;
+                }
             }
             break;
         }
@@ -352,6 +366,7 @@
         mCmdParams = new DisplayTextParams(cmdDet, textMsg);
 
         if (iconId != null) {
+            mloadIcon = true;
             mIconLoadState = LOAD_SINGLE_ICON;
             mIconLoader.loadIcon(iconId.recordNumber, this
                     .obtainMessage(MSG_ID_LOAD_ICON_DONE));
@@ -383,17 +398,25 @@
         if (ctlv != null) {
             textMsg.text = ValueParser.retrieveTextString(ctlv);
         }
-        // load icons only when text exist.
-        if (textMsg.text != null) {
-            ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
-            if (ctlv != null) {
-                iconId = ValueParser.retrieveIconId(ctlv);
-                textMsg.iconSelfExplanatory = iconId.selfExplanatory;
-            }
+
+        ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs);
+        if (ctlv != null) {
+            iconId = ValueParser.retrieveIconId(ctlv);
+            textMsg.iconSelfExplanatory = iconId.selfExplanatory;
+        }
+
+        /*
+         * If the tlv object doesn't contain text and the icon is not self
+         * explanatory then reply with command not understood.
+         */
+
+        if (textMsg.text == null && iconId != null && !textMsg.iconSelfExplanatory) {
+            throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD);
         }
         mCmdParams = new DisplayTextParams(cmdDet, textMsg);
 
         if (iconId != null) {
+            mloadIcon = true;
             mIconLoadState = LOAD_SINGLE_ICON;
             mIconLoader.loadIcon(iconId.recordNumber, this
                     .obtainMessage(MSG_ID_LOAD_ICON_DONE));
@@ -451,6 +474,7 @@
         mCmdParams = new GetInputParams(cmdDet, input);
 
         if (iconId != null) {
+            mloadIcon = true;
             mIconLoadState = LOAD_SINGLE_ICON;
             mIconLoader.loadIcon(iconId.recordNumber, this
                     .obtainMessage(MSG_ID_LOAD_ICON_DONE));
@@ -530,6 +554,7 @@
         mCmdParams = new GetInputParams(cmdDet, input);
 
         if (iconId != null) {
+            mloadIcon = true;
             mIconLoadState = LOAD_SINGLE_ICON;
             mIconLoader.loadIcon(iconId.recordNumber, this
                     .obtainMessage(MSG_ID_LOAD_ICON_DONE));
@@ -643,6 +668,7 @@
         case LOAD_NO_ICON:
             return false;
         case LOAD_SINGLE_ICON:
+            mloadIcon = true;
             mIconLoader.loadIcon(titleIconId.recordNumber, this
                     .obtainMessage(MSG_ID_LOAD_ICON_DONE));
             break;
@@ -655,6 +681,7 @@
                 System.arraycopy(itemsIconId.recordNumbers, 0, recordNumbers,
                         1, itemsIconId.recordNumbers.length);
             }
+            mloadIcon = true;
             mIconLoader.loadIcons(recordNumbers, this
                     .obtainMessage(MSG_ID_LOAD_ICON_DONE));
             break;
@@ -693,6 +720,7 @@
         mCmdParams = new DisplayTextParams(cmdDet, textMsg);
 
         if (iconId != null) {
+            mloadIcon = true;
             mIconLoadState = LOAD_SINGLE_ICON;
             mIconLoader.loadIcon(iconId.recordNumber, this
                     .obtainMessage(MSG_ID_LOAD_ICON_DONE));
diff --git a/src/java/com/android/internal/telephony/cat/ImageDescriptor.java b/src/java/com/android/internal/telephony/cat/ImageDescriptor.java
index 139a4e0..29e6c76 100644
--- a/src/java/com/android/internal/telephony/cat/ImageDescriptor.java
+++ b/src/java/com/android/internal/telephony/cat/ImageDescriptor.java
@@ -68,8 +68,11 @@
             d.mLowOffset = rawData[valueIndex++] & 0xff; // low byte offset
 
             d.mLength = ((rawData[valueIndex++] & 0xff) << 8 | (rawData[valueIndex++] & 0xff));
+            CatLog.d("ImageDescriptor", "parse; Descriptor : " + d.mWidth + ", " + d.mHeight +
+                    ", " + d.mCodingScheme + ", 0x" + Integer.toHexString(d.mImageId) + ", " +
+                    d.mHighOffset + ", " + d.mLowOffset + ", " + d.mLength);
         } catch (IndexOutOfBoundsException e) {
-            CatLog.d("ImageDescripter", "parse; failed parsing image descriptor");
+            CatLog.d("ImageDescriptor", "parse; failed parsing image descriptor");
             d = null;
         }
         return d;