Do not inform user when the alpha identifier is a null data.

This code change has below fixes related to play tone
proactive cmd.

1. Current code is not in accordance with the spec
3GPP TS 11.14, 6.4.5. Play Tone, as user is informed when the
alpha identifier is a null data.

With reference to the spec, if there is no alpha identifier,
show the text message to the user depending on the config setting.

If alpha identifier data is null, play only tone and do not
inform the user.

Move the code to handle play tone from ToneDialog to StkAppService
in cases where only tone needs to be played and no user inform needed.

Dismiss the tone dialog from StkAppService after play tone finish.

Send the intent to StkAppService from ToneDialog to finish
the play tone, when user presses back key.

Ref spec: 3GPP TS 11.14, 6.4.5. Play Tone.

2. Send the correct Message object for the Play Tone command.

When stopping the tone that is playing due to the Play Tone command,
a delayed Message is sent to StkAppService with its 'arg2' field
containing a flag that indicates if tone dialog activity needs to be
closed. But when handling the received messages, StkAppService expects
the Message object's 'arg2' field to contain the slot Id on which the
command is received. This causes unexpected behavior when executing
the Play Tone command.

Use a different field in the Message object to send the the value of
the flag which indicates if tone dialog activity needs to be closed.

3. set slotId in message for OP_STOP_TONE

- unable to send the response to the
correct sim card
- Set the slotId as arg2 in the message

Bug: 35615464
Test: manual
Merged-In: Ib25986efe1d7c26976015f666580a3deb28bb328
Change-Id: Ib25986efe1d7c26976015f666580a3deb28bb328
diff --git a/src/com/android/stk/StkAppService.java b/src/com/android/stk/StkAppService.java
index 91ae3d3..edd4306 100755
--- a/src/com/android/stk/StkAppService.java
+++ b/src/com/android/stk/StkAppService.java
@@ -32,6 +32,8 @@
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.net.Uri;
@@ -43,6 +45,7 @@
 import android.os.PersistableBundle;
 import android.os.PowerManager;
 import android.os.SystemProperties;
+import android.os.Vibrator;
 import android.provider.Settings;
 import android.telephony.CarrierConfigManager;
 import android.telephony.TelephonyManager;
@@ -73,6 +76,7 @@
 import com.android.internal.telephony.cat.CatLog;
 import com.android.internal.telephony.cat.CatResponseMessage;
 import com.android.internal.telephony.cat.TextMessage;
+import com.android.internal.telephony.cat.ToneSettings;
 import com.android.internal.telephony.uicc.IccRefreshResponse;
 import com.android.internal.telephony.uicc.IccCardStatus.CardState;
 import com.android.internal.telephony.PhoneConstants;
@@ -167,6 +171,8 @@
     private int mSimCount = 0;
     private PowerManager mPowerManager = null;
     private StkCmdReceiver mStkCmdReceiver = null;
+    private TonePlayer mTonePlayer = null;
+    private Vibrator mVibrator = null;
 
     // Used for setting FLAG_ACTIVITY_NO_USER_ACTION when
     // creating an intent.
@@ -190,6 +196,8 @@
     static final String STK_MENU_URI = "stk://com.android.stk/menu/";
     static final String STK_INPUT_URI = "stk://com.android.stk/input/";
     static final String STK_TONE_URI = "stk://com.android.stk/tone/";
+    static final String FINISH_TONE_ACTIVITY_ACTION =
+                                "android.intent.action.stk.finish_activity";
 
     // These below constants are used for SETUP_EVENT_LIST
     static final String SETUP_EVENT_TYPE = "event";
@@ -213,6 +221,15 @@
     //Invalid SetupEvent
     static final int INVALID_SETUP_EVENT = 0xFF;
 
+    // Message id to signal stop tone due to play tone timeout.
+    private static final int OP_STOP_TONE = 16;
+
+    // Message id to signal stop tone on user keyback.
+    static final int OP_STOP_TONE_USER = 17;
+
+    // Message id to remove stop tone message from queue.
+    private static final int STOP_TONE_WHAT = 100;
+
     // Response ids
     static final int RES_ID_MENU_SELECTION = 11;
     static final int RES_ID_INPUT = 12;
@@ -351,6 +368,10 @@
         case OP_END_SESSION:
         case OP_BOOT_COMPLETED:
             break;
+        case OP_STOP_TONE_USER:
+            msg.obj = args;
+            msg.what = STOP_TONE_WHAT;
+            break;
         default:
             return;
         }
@@ -598,6 +619,11 @@
                     }
                 }
                 break;
+            case OP_STOP_TONE_USER:
+            case OP_STOP_TONE:
+                CatLog.d(this, "Stop tone");
+                handleStopTone(msg, slotId);
+                break;
             }
         }
 
@@ -988,7 +1014,7 @@
             launchConfirmationDialog(mesg, slotId);
             break;
         case PLAY_TONE:
-            launchToneDialog(slotId);
+            handlePlayTone(slotId);
             break;
         case OPEN_CHANNEL:
             launchOpenChannelDialog(slotId);
@@ -1616,21 +1642,122 @@
         }
     }
 
-    private void launchToneDialog(int slotId) {
-        Intent newIntent = new Intent(this, ToneDialog.class);
-        String uriString = STK_TONE_URI + slotId;
-        Uri uriData = Uri.parse(uriString);
-        //Set unique URI to create a new instance of activity for different slotId.
-        CatLog.d(LOG_TAG, "launchToneDialog, slotId: " + slotId);
-        newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
-                | Intent.FLAG_ACTIVITY_NO_HISTORY
-                | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
-                | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
-        newIntent.putExtra("TEXT", mStkContext[slotId].mCurrentCmd.geTextMessage());
-        newIntent.putExtra("TONE", mStkContext[slotId].mCurrentCmd.getToneSettings());
-        newIntent.putExtra(SLOT_ID, slotId);
-        newIntent.setData(uriData);
-        startActivity(newIntent);
+    private void handlePlayTone(int slotId) {
+        TextMessage toneMsg = mStkContext[slotId].mCurrentCmd.geTextMessage();
+
+        boolean showUser = true;
+        boolean displayDialog = true;
+        Resources resource = Resources.getSystem();
+        try {
+            displayDialog = !resource.getBoolean(
+                    com.android.internal.R.bool.config_stkNoAlphaUsrCnf);
+        } catch (NotFoundException e) {
+            displayDialog = true;
+        }
+
+        // As per the spec 3GPP TS 11.14, 6.4.5. Play Tone.
+        // If there is no alpha identifier tlv present, UE may show the
+        // user information. 'config_stkNoAlphaUsrCnf' value will decide
+        // whether to show it or not.
+        // If alpha identifier tlv is present and its data is null, play only tone
+        // without showing user any information.
+        // Alpha Id is Present, but the text data is null.
+        if ((toneMsg.text != null ) && (toneMsg.text.equals(""))) {
+            CatLog.d(this, "Alpha identifier data is null, play only tone");
+            showUser = false;
+        }
+        // Alpha Id is not present AND we need to show info to the user.
+        if (toneMsg.text == null && displayDialog) {
+            CatLog.d(this, "toneMsg.text " + toneMsg.text
+                    + " Starting ToneDialog activity with default message.");
+            toneMsg.text = getResources().getString(R.string.default_tone_dialog_msg);
+            showUser = true;
+        }
+        // Dont show user info, if config setting is true.
+        if (toneMsg.text == null && !displayDialog) {
+            CatLog.d(this, "config value stkNoAlphaUsrCnf is true");
+            showUser = false;
+        }
+
+        CatLog.d(this, "toneMsg.text: " + toneMsg.text + "showUser: " +showUser +
+                "displayDialog: " +displayDialog);
+        playTone(showUser, slotId);
+    }
+
+    private void playTone(boolean showUserInfo, int slotId) {
+        // Start playing tone and vibration
+        ToneSettings settings = mStkContext[slotId].mCurrentCmd.getToneSettings();
+        if (null == settings) {
+            CatLog.d(this, "null settings, not playing tone.");
+            return;
+        }
+
+        mVibrator = (Vibrator)getSystemService(VIBRATOR_SERVICE);
+        mTonePlayer = new TonePlayer();
+        mTonePlayer.play(settings.tone);
+        int timeout = StkApp.calculateDurationInMilis(settings.duration);
+        if (timeout == 0) {
+            timeout = StkApp.TONE_DEFAULT_TIMEOUT;
+        }
+
+        Message msg = mServiceHandler.obtainMessage();
+        msg.arg1 = OP_STOP_TONE;
+        msg.arg2 = slotId;
+        msg.obj = (Integer)(showUserInfo ? 1 : 0);
+        msg.what = STOP_TONE_WHAT;
+        mServiceHandler.sendMessageDelayed(msg, timeout);
+        if (settings.vibrate) {
+            mVibrator.vibrate(timeout);
+        }
+
+        // Start Tone dialog Activity to show user the information.
+        if (showUserInfo) {
+            Intent newIntent = new Intent(sInstance, ToneDialog.class);
+            String uriString = STK_TONE_URI + slotId;
+            Uri uriData = Uri.parse(uriString);
+            newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                    | Intent.FLAG_ACTIVITY_NO_HISTORY
+                    | Intent.FLAG_ACTIVITY_SINGLE_TOP
+                    | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+                    | getFlagActivityNoUserAction(InitiatedByUserAction.unknown, slotId));
+            newIntent.putExtra("TEXT", mStkContext[slotId].mCurrentCmd.geTextMessage());
+            newIntent.putExtra(SLOT_ID, slotId);
+            newIntent.setData(uriData);
+            startActivity(newIntent);
+        }
+    }
+
+    private void finishToneDialogActivity() {
+        Intent finishIntent = new Intent(FINISH_TONE_ACTIVITY_ACTION);
+        sendBroadcast(finishIntent);
+    }
+
+    private void handleStopTone(Message msg, int slotId) {
+        int resId = 0;
+
+        // Stop the play tone in following cases:
+        // 1.OP_STOP_TONE: play tone timer expires.
+        // 2.STOP_TONE_USER: user pressed the back key.
+        if (msg.arg1 == OP_STOP_TONE) {
+            resId = RES_ID_DONE;
+            // Dismiss Tone dialog, after finishing off playing the tone.
+            int finishActivity = (Integer) msg.obj;
+            if (finishActivity == 1) finishToneDialogActivity();
+        } else if (msg.arg1 == OP_STOP_TONE_USER) {
+            resId = RES_ID_END_SESSION;
+        }
+
+        sendResponse(resId, slotId, true);
+        mServiceHandler.removeMessages(STOP_TONE_WHAT);
+        if (mTonePlayer != null)  {
+            mTonePlayer.stop();
+            mTonePlayer.release();
+            mTonePlayer = null;
+        }
+        if (mVibrator != null) {
+            mVibrator.cancel();
+            mVibrator = null;
+        }
     }
 
     private void launchOpenChannelDialog(final int slotId) {