Code drop from //branches/cupcake/...@124589
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 83f8ae7..b8472f5 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -19,24 +19,31 @@
 		package="com.android.stk" 
 		android:sharedUserId="android.uid.phone">
 
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+
 	<application android:icon="@drawable/ic_launcher_sim_toolkit"
 		android:label="@string/app_name"
 		android:clearTaskOnLaunch="true"
 		android:process="com.android.phone">
 
-		<activity android:name="StkActivity" android:label="@string/app_name"
+		<activity android:name="StkLauncherActivity" 
+			android:label="@string/app_name"
 			android:enabled="false"	>
 			<intent-filter>
 				<action android:name="android.intent.action.MAIN" />
 				<category android:name="android.intent.category.LAUNCHER" />
 			</intent-filter>
-			<intent-filter>
-                <action android:name="android.intent.action.VIEW" />
-                <action android:name="android.intent.action.PICK" />
-                <category android:name="android.intent.category.DEFAULT" />
-            </intent-filter>
 		</activity>
 
+		<activity android:name="StkMenuActivity" 
+             android:launchMode="singleTop">
+	         <intent-filter>
+	             <action android:name="android.intent.action.VIEW" />
+	             <action android:name="android.intent.action.PICK" />
+	             <category android:name="android.intent.category.DEFAULT" />
+	         </intent-filter>
+         </activity>
+
 		<activity android:name="StkInputActivity">
 			<intent-filter>
 		        <action android:name="android.intent.action.VIEW" />
@@ -45,14 +52,39 @@
 		    </intent-filter>
 		</activity>
 
-		<!-- SIM Toolkit settings activity -->
-        <activity android:name="StkSettings" android:label="@string/app_name">
-            <intent-filter>
-                <action android:name="android.intent.action.VIEW" />
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEVELOPMENT_PREFERENCE" />
-            </intent-filter>
+        <activity android:name="StkDialogActivity"
+            android:theme="@android:style/Theme.Dialog">
         </activity>
 
+        <activity android:name="ToneDialog"
+            android:theme="@android:style/Theme.Dialog">
+        </activity>
+
+		<!-- SIM Toolkit settings activity -->
+		<activity android:name="StkSettings"
+			android:label="@string/app_name">
+			<intent-filter>
+				<action android:name="android.intent.action.VIEW" />
+				<action android:name="android.intent.action.MAIN" />
+				<category
+					android:name="android.intent.category.DEVELOPMENT_PREFERENCE" />
+			</intent-filter>
+		</activity>
+		
+		<receiver android:name="com.android.stk.StkCmdReceiver">
+            <intent-filter>
+                <action android:name= "android.intent.action.stk.command" />
+                <action android:name= "android.intent.action.stk.session_end" />
+            </intent-filter>
+        </receiver>
+
+        <receiver android:name="com.android.stk.BootCompletedReceiver">
+            <intent-filter>
+                <action android:name="android.intent.action.BOOT_COMPLETED" />
+            </intent-filter>
+        </receiver>
+
+        <service android:name="StkAppService" />
+
 	</application>
 </manifest>
diff --git a/res/layout/stk_call_dialog.xml b/res/layout/stk_call_dialog.xml
deleted file mode 100644
index 533187d..0000000
--- a/res/layout/stk_call_dialog.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 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.
--->
-
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="240sp"
-    android:layout_height="wrap_content"
-    android:gravity="center"
-    android:orientation="vertical">
-    <TextView
-        android:id="@+id/prompt"
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        android:gravity="center"
-        android:textSize="16sp"
-        android:text="@string/launch_dialer"
-        android:layout_marginBottom="10dip" />
-    <LinearLayout
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal"
-        android:gravity="center">
-	    <Button
-	        android:id="@+id/button_call"
-	        android:layout_width="100sp"
-	        android:layout_height="wrap_content"
-	        android:textStyle="bold"
-	        android:textSize="20sp"
-	        android:text="@string/button_call" />
-	    <Button
-		    android:id="@+id/button_cancel"
-		    android:layout_width="100sp"
-		    android:layout_height="wrap_content"
-		    android:layout_marginLeft="10dip"
-		    android:textStyle="bold"
-		    android:textSize="20sp"
-	        android:text="@string/button_cancel" />
-    </LinearLayout>
-</LinearLayout>
diff --git a/res/layout/stk_event_msg.xml b/res/layout/stk_event_msg.xml
new file mode 100644
index 0000000..f6cc6d4
--- /dev/null
+++ b/res/layout/stk_event_msg.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* 
+**
+** Copyright 2006, Google Inc.
+**
+** 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.
+*/
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="horizontal"
+    android:background="@android:drawable/toast_frame">
+
+    <ImageView android:id="@android:id/icon"
+       android:layout_width="32dip"
+       android:layout_height="32dip"
+       android:scaleType="fitCenter" />
+
+    <TextView
+        android:id="@android:id/message"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:textAppearance="@android:style/TextAppearance.Small"
+        android:textColor="@color/bright_foreground_dark"
+        android:shadowColor="#BB000000"
+        android:shadowRadius="2.75"
+        />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/stk_menu_item.xml b/res/layout/stk_menu_item.xml
index 8ea5cc1..98d7828 100644
--- a/res/layout/stk_menu_item.xml
+++ b/res/layout/stk_menu_item.xml
@@ -38,7 +38,7 @@
         android:minHeight="?android:attr/listPreferredItemHeight"
 	    android:textAppearance="?android:attr/textAppearanceLarge"
 	    android:gravity="center_vertical"
-	    android:paddingLeft="25dip"
+	    android:layout_marginLeft="9dip"
 	/>
 
 </LinearLayout>
diff --git a/res/layout/stk_msg_dialog.xml b/res/layout/stk_msg_dialog.xml
index 7ef3a6c..c8ec5b0 100644
--- a/res/layout/stk_msg_dialog.xml
+++ b/res/layout/stk_msg_dialog.xml
@@ -16,40 +16,59 @@
 
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="200dip"
+    android:layout_width="fill_parent"
     android:layout_height="wrap_content"
-    android:layout_gravity="center_horizontal"
     android:orientation="vertical" >
 
-   <ImageView android:id="@+id/dialog_icon"
-       android:layout_width="16dip" 
-       android:layout_height="16dip"
-       android:layout_marginTop="5dip"
-       android:layout_marginLeft="5dip"
-       android:layout_alignParentLeft="true"
-       android:scaleType="fitCenter" />
-
-    <LinearLayout
+    <LinearLayout android:id="@+id/messagePanel"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
-        android:layout_gravity="center_horizontal"
-        android:padding="10dip"
-        android:orientation="vertical" >
-	    <TextView
-	        android:id="@+id/dialog_message"
+        android:layout_weight="1"
+        android:orientation="vertical">
+        <ScrollView android:id="@+id/scrollView"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="2dip"
+            android:paddingBottom="12dip"
+            android:paddingLeft="14dip"
+            android:paddingRight="10dip">
+            <TextView android:id="@+id/dialog_message"
+                style="?android:attr/textAppearanceMedium"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:padding="5dip" />
+        </ScrollView>
+    </LinearLayout>
+
+	<LinearLayout android:id="@+id/buttonPanel"
+	    android:layout_width="fill_parent"
+	    android:layout_height="wrap_content"
+	    android:minHeight="54dip"
+	    android:orientation="vertical" >     
+	    <LinearLayout 
 	        android:layout_width="fill_parent"
 	        android:layout_height="wrap_content"
-	        android:layout_gravity="center_horizontal"
-	        android:textSize="16sp"
-	        android:layout_marginBottom="5dip" />
-	    <Button
-	        android:id="@+id/button_ok"
-	        android:layout_width="120sp"
-	        android:layout_height="wrap_content"
-	        android:layout_gravity="center_horizontal"
-	        android:layout_marginTop="5dip"
-            android:textStyle="bold"
-            android:textSize="20sp"
-	        android:text="@string/button_ok" />
+	        android:orientation="horizontal"
+            android:background="@color/ltgrey"
+	        android:paddingTop="4dip"
+	        android:paddingLeft="2dip"
+	        android:paddingRight="2dip" >
+	        <Button 
+	            android:id="@+id/button_ok"
+	            android:layout_width="0dip"
+	            android:layout_height="wrap_content"
+	            android:layout_gravity="left"
+	            android:layout_weight="1"
+	            android:maxLines="2" 
+	            android:text="@string/button_ok" />
+	        <Button 
+	            android:id="@+id/button_cancel"
+	            android:layout_width="0dip"
+	            android:layout_height="wrap_content"
+	            android:layout_gravity="right"
+	            android:layout_weight="1"
+	            android:maxLines="2" 
+	            android:text="@string/button_cancel" />
+	       </LinearLayout>
     </LinearLayout>
 </LinearLayout>
diff --git a/res/layout/stk_title.xml b/res/layout/stk_title.xml
index 9e8125c..4d09368 100644
--- a/res/layout/stk_title.xml
+++ b/res/layout/stk_title.xml
@@ -24,26 +24,48 @@
 		android:layout_width="fill_parent"
 		android:layout_height="wrap_content"
 		android:orientation="horizontal"
+		android:layout_centerVertical="true"
 		style="?android:attr/windowTitleBackgroundStyle" >
 
-		<ImageView android:id="@+id/title_icon"
-			android:layout_width="16dip" 
-			android:layout_height="16dip"
-			android:layout_marginLeft="2dip"
-	        android:layout_alignParentLeft="true"
-            android:layout_gravity="center_vertical"
-			android:scaleType="fitCenter" />
+        <LinearLayout android:id="@+id/left_container"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:layout_weight="1"
+            android:layout_centerVertical="true">
+			<ImageView android:id="@+id/title_icon"
+				android:layout_width="16dip" 
+				android:layout_height="16dip"
+				android:layout_marginLeft="2dip"
+				android:layout_marginRight="9dip"
+	            android:layout_gravity="center_vertical"
+	            android:layout_alignParentLeft="true"
+				android:scaleType="fitCenter" />
 
-		<TextView android:id="@+id/title_text"
-			android:gravity="center_vertical" 
-			android:layout_width="fill_parent"
-			android:layout_height="wrap_content"
-			android:paddingLeft="5dip"
-			android:shadowColor="#BB000000"
-			android:shadowRadius="2.75"
-			style="@android:style/TextAppearance.WindowTitle" />
+			<TextView android:id="@+id/title_text"
+				android:gravity="center_vertical" 
+				android:layout_width="fill_parent"
+				android:layout_height="wrap_content"
+				style="@android:style/TextAppearance.WindowTitle" />
+        </LinearLayout>
 
+        <LinearLayout android:id="@+id/right_container"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentRight="true"
+            android:layout_centerVertical="true">
+
+	        <ProgressBar android:id="@+id/progress_bar"
+	                style="?android:attr/progressBarStyleSmallTitle"
+	                android:layout_width="wrap_content"
+	                android:layout_height="wrap_content"
+	                android:layout_marginLeft="5dip"
+	                android:layout_centerVertical="true"
+	                android:visibility="gone"
+	                android:max="10000" />
+        </LinearLayout>
 	</LinearLayout>
+
 	<FrameLayout android:id="@android:id/content"
 		android:layout_width="fill_parent" 
 		android:layout_height="0dip"
diff --git a/res/layout/stk_tone_dialog.xml b/res/layout/stk_tone_dialog.xml
new file mode 100644
index 0000000..6c10110
--- /dev/null
+++ b/res/layout/stk_tone_dialog.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2007 Google Inc.
+ *
+ * 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.
+ */
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:orientation="vertical"
+    android:padding="14dip">
+
+    <ImageView
+        android:id="@+id/icon"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content" 
+        android:scaleType="fitCenter"
+        android:gravity="center" />
+
+    <TextView
+        android:id="@+id/message"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="14dip"
+        android:gravity="center"
+        android:textAppearance="?android:attr/textAppearanceMedium" />
+
+</LinearLayout>
+
+
diff --git a/res/values-de-rDE/strings.xml b/res/values-de-rDE/strings.xml
deleted file mode 100644
index 9041f0f..0000000
--- a/res/values-de-rDE/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string name="alphabet">Alphabet</string>
-  <string name="app_name">SIM-Toolkit</string>
-  <string name="button_call">Anrufen</string>
-  <string name="button_cancel">Abbrechen</string>
-  <string name="button_no">Nein</string>
-  <string name="button_ok">OK</string>
-  <string name="button_yes">Ja</string>
-  <string name="default_call_setup_msg">Aktiver Anruf\u2026</string>
-  <string name="digits">Ziffern ( 0-9, *, #,+)</string>
-  <string name="disable_app">Deaktiviert</string>
-  <string name="enable_app">Aktiviert</string>
-  <string name="help">Hilfe</string>
-  <string name="launch_browser">Browser starten?</string>
-  <string name="launch_dialer">Wähltastatur starten?</string>
-  <string name="no_content">Kein SIM-Karten-Inhalt verfügbar!</string>
-  <string name="play_tone">Ton wiedergeben</string>
-  <string name="service_name">Dienstname</string>
-  <string name="sim_main_menu">Hauptmenü</string>
-  <string name="stk_app_state">Anwendungsstatus</string>
-  <string name="stk_no_service">Kein Dienst verfügbar</string>
-</resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
new file mode 100644
index 0000000..ed15c44
--- /dev/null
+++ b/res/values-de/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name">"SIM-Toolkit"</string>
+    <string name="menu_end_session">"Sitzung beenden"</string>
+    <string name="help">"Hilfe"</string>
+    <string name="menu_back">"Zurück"</string>
+    <string name="service_name">"Name des Dienstes"</string>
+    <string name="stk_no_service">"Kein Dienst verfügbar"</string>
+    <string name="button_ok">"OK"</string>
+    <string name="button_cancel">"Abbrechen"</string>
+    <string name="button_yes">"Ja"</string>
+    <string name="button_no">"Nein"</string>
+    <string name="alphabet">"Buchstaben"</string>
+    <string name="digits">"Ziffern (0-9, *, #, +)"</string>
+    <string name="default_call_setup_msg">"Verbindungsaufbau..."</string>
+    <!-- no translation found for stk_app_state (18582277302584082) -->
+    <skip />
+    <!-- no translation found for enable_app (3701224550936728203) -->
+    <skip />
+    <!-- no translation found for disable_app (6725081975611415214) -->
+    <skip />
+</resources>
diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml
index b91eccc..3a06669 100644
--- a/res/values-en-rGB/strings.xml
+++ b/res/values-en-rGB/strings.xml
@@ -1,24 +1,22 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string name="alphabet">Alphabets</string>
-  <string name="app_name">SIM Toolkit</string>
-  <string name="button_call">Call</string>
-  <string name="button_cancel">Cancel</string>
-  <string name="button_no">No</string>
-  <string name="button_ok">OK</string>
-  <string name="button_yes">Yes</string>
-  <string name="default_call_setup_msg">Call in progress\u2026</string>
-  <string name="digits">Digits (0-9, *, #, +)</string>
-  <string name="disable_app">Disabled</string>
-  <string name="enable_app">Enabled</string>
-  <string name="help">Help</string>
-  <string name="launch_browser">Launch Browser?</string>
-  <string name="launch_dialer">Launch Dialer?</string>
-  <string name="no_content">No SIM content available!</string>
-  <string name="play_tone">Play tone</string>
-  <string name="service_name">Service name</string>
-  <string name="sim_main_menu">Main menu</string>
-  <string name="stk_app_state">Application state</string>
-  <string name="stk_no_service">No service available</string>
+    <string name="app_name">"SIM Toolkit"</string>
+    <!-- no translation found for menu_end_session (3801465311834787807) -->
+    <skip />
+    <string name="help">"Help"</string>
+    <!-- no translation found for menu_back (9160708252396089257) -->
+    <skip />
+    <string name="service_name">"Service name"</string>
+    <string name="stk_no_service">"No service available"</string>
+    <string name="button_ok">"OK"</string>
+    <string name="button_cancel">"Cancel"</string>
+    <string name="button_yes">"Yes"</string>
+    <string name="button_no">"No"</string>
+    <string name="alphabet">"Alphabets"</string>
+    <string name="digits">"Digits (0-9, *, #, +)"</string>
+    <string name="default_call_setup_msg">"Call in progress…"</string>
+    <string name="stk_app_state">"Application state"</string>
+    <string name="enable_app">"Enabled"</string>
+    <string name="disable_app">"Disabled"</string>
 </resources>
diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml
deleted file mode 100644
index 4fe5db0..0000000
--- a/res/values-es-rUS/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string name="alphabet">Alfabetos</string>
-  <string name="app_name">Herramientas SIM</string>
-  <string name="button_call">Llamar</string>
-  <string name="button_cancel">Cancelar</string>
-  <string name="button_no">No</string>
-  <string name="button_ok">Aceptar</string>
-  <string name="button_yes">Sí</string>
-  <string name="default_call_setup_msg">Llamada en curso\u2026</string>
-  <string name="digits">Dígitos (0-9, *, #, +)</string>
-  <string name="disable_app">Deshabilitado</string>
-  <string name="enable_app">Habilitado</string>
-  <string name="help">Ayuda</string>
-  <string name="launch_browser">¿Iniciar explorador?</string>
-  <string name="launch_dialer">¿Iniciar marcador?</string>
-  <string name="no_content">¡Sin contenido SIM disponible!</string>
-  <string name="play_tone">Reproducir tono</string>
-  <string name="service_name">Nombre del servicio</string>
-  <string name="sim_main_menu">Menú principal</string>
-  <string name="stk_app_state">Estado de la aplicación</string>
-  <string name="stk_no_service">Sin servicio disponible</string>
-</resources>
diff --git a/res/values-fr-rFR/strings.xml b/res/values-fr-rFR/strings.xml
deleted file mode 100644
index 44fecde..0000000
--- a/res/values-fr-rFR/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string name="alphabet">Alphabets</string>
-  <string name="app_name">Outils SIM</string>
-  <string name="button_call">Appeler</string>
-  <string name="button_cancel">Annuler</string>
-  <string name="button_no">Non</string>
-  <string name="button_ok">OK</string>
-  <string name="button_yes">Oui</string>
-  <string name="default_call_setup_msg">Appel en cours\u2026</string>
-  <string name="digits">Chiffres (0-9, *, #, +)</string>
-  <string name="disable_app">Désactivé</string>
-  <string name="enable_app">Activé</string>
-  <string name="help">Aide</string>
-  <string name="launch_browser">Lancer le navigateur ?</string>
-  <string name="launch_dialer">Lancer le numéroteur ?</string>
-  <string name="no_content">Aucun contenu SIM disponible !</string>
-  <string name="play_tone">Émettre la tonalité</string>
-  <string name="service_name">Nom de service</string>
-  <string name="sim_main_menu">Menu principal</string>
-  <string name="stk_app_state">État d\'application</string>
-  <string name="stk_no_service">Pas de service disponible</string>
-</resources>
diff --git a/res/values-it-rIT/strings.xml b/res/values-it-rIT/strings.xml
deleted file mode 100644
index a349699..0000000
--- a/res/values-it-rIT/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string name="alphabet">Alfabeti</string>
-  <string name="app_name">Kit di strumenti SIM</string>
-  <string name="button_call">Chiama</string>
-  <string name="button_cancel">Annulla</string>
-  <string name="button_no">No</string>
-  <string name="button_ok">OK</string>
-  <string name="button_yes">Sì</string>
-  <string name="default_call_setup_msg">Chiamata in corso\u2026</string>
-  <string name="digits">Numeri (0-9, *, #, +)</string>
-  <string name="disable_app">Disabilitato</string>
-  <string name="enable_app">Abilitato</string>
-  <string name="help">Guida</string>
-  <string name="launch_browser">Avviare il browser?</string>
-  <string name="launch_dialer">Avviare il dialer?</string>
-  <string name="no_content">Nessun contenuto SIM disponibile.</string>
-  <string name="play_tone">Riproduci tono</string>
-  <string name="service_name">Nome servizio</string>
-  <string name="sim_main_menu">Menu principale</string>
-  <string name="stk_app_state">Stato applicazione</string>
-  <string name="stk_no_service">Nessun servizio disponibile</string>
-</resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
new file mode 100644
index 0000000..1c6139f
--- /dev/null
+++ b/res/values-ja/strings.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name">"SIM Toolkit"</string>
+    <string name="menu_end_session">"セッションを終了"</string>
+    <string name="help">"ヘルプ"</string>
+    <string name="menu_back">"戻る"</string>
+    <string name="service_name">"サービス名"</string>
+    <string name="stk_no_service">"利用できるサービスがありません"</string>
+    <string name="button_ok">"OK"</string>
+    <string name="button_cancel">"キャンセル"</string>
+    <string name="button_yes">"はい"</string>
+    <string name="button_no">"いいえ"</string>
+    <string name="alphabet">"英字"</string>
+    <string name="digits">"数字 (0-9、*、#、+)"</string>
+    <string name="default_call_setup_msg">"通話中..."</string>
+    <!-- no translation found for stk_app_state (18582277302584082) -->
+    <skip />
+    <!-- no translation found for enable_app (3701224550936728203) -->
+    <skip />
+    <!-- no translation found for disable_app (6725081975611415214) -->
+    <skip />
+</resources>
diff --git a/res/values-mcc234-mnc030/strings.xml b/res/values-mcc234-mnc030/strings.xml
deleted file mode 100644
index c3d4de5..0000000
--- a/res/values-mcc234-mnc030/strings.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 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.
--->
-
- 
-<resources>
-    <string name="app_name">Interactive</string>
-</resources>
- 
diff --git a/res/values-mcc234-mnc033/strings.xml b/res/values-mcc234-mnc033/strings.xml
deleted file mode 100644
index 226065b..0000000
--- a/res/values-mcc234-mnc033/strings.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 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.
--->
-
-<resources>
-    <string name="app_name">Orange Plus</string>
-</resources>
diff --git a/res/values-mcc234-mnc034/strings.xml b/res/values-mcc234-mnc034/strings.xml
deleted file mode 100644
index 226065b..0000000
--- a/res/values-mcc234-mnc034/strings.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 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.
--->
-
-<resources>
-    <string name="app_name">Orange Plus</string>
-</resources>
diff --git a/res/values-mcc262-mnc001/strings.xml b/res/values-mcc262-mnc001/strings.xml
deleted file mode 100644
index e56258c..0000000
--- a/res/values-mcc262-mnc001/strings.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2007 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.
--->
-
-<resources>
-    <string name="app_name">SIM Tool Kit</string>
-</resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
deleted file mode 100644
index 68c337f..0000000
--- a/res/values-zh-rTW/strings.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-  <string name="alphabet">字母</string>
-  <string name="app_name">SIM Toolkit</string>
-  <string name="button_call">撥號</string>
-  <string name="button_cancel">取消</string>
-  <string name="button_no">否</string>
-  <string name="button_ok">確定</string>
-  <string name="button_yes">是</string>
-  <string name="default_call_setup_msg">通話中\u2026</string>
-  <string name="digits">數字 (0-9、*、#、+)</string>
-  <string name="disable_app">停用</string>
-  <string name="enable_app">啟用</string>
-  <string name="help">說明</string>
-  <string name="launch_browser">啟動瀏覽器?</string>
-  <string name="launch_dialer">啟動撥號員?</string>
-  <string name="no_content">無可用的 SIM 卡內容!</string>
-  <string name="play_tone">播放音調</string>
-  <string name="service_name">服務名稱</string>
-  <string name="sim_main_menu">主功能表</string>
-  <string name="stk_app_state">應用程式狀態</string>
-  <string name="stk_no_service">無可用的服務</string>
-</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 1a4d54d..9435d30 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -16,4 +16,5 @@
 
 <resources>
     <color name="ltgrey">#ffe0e0e0</color>
+    <color name="bright_foreground_dark">#ffffffff</color>
 </resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 792801e..1252912 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -15,24 +15,34 @@
 -->
 
 <resources>
+    <!-- Default Application label used on home screen with an icon -->
     <string name="app_name">SIM Toolkit</string>
-    <string name="no_content">No SIM content available!</string>
-    <string name="sim_main_menu">Main menu</string>
+    <!-- Menu button option for ending current SIM session -->
+    <string name="menu_end_session">End session</string>
+    <!-- Menu button option for requesting additional help information -->
+    <string name="help">Help</string>
+    <!-- Menu button option to navigate back to the previous screen -->
+    <string name="menu_back">Back</string>
+    <!-- Settings entry which describes the current SIM Toolkit service on the device -->
     <string name="service_name">Service name</string>
-    <string name="stk_app_state">Application state</string>
+    <!-- Default description for service_name when no STK service is available -->
     <string name="stk_no_service">No service available</string>
+    <!-- OK button used to confirm a message dialog -->
+    <string name="button_ok">OK</string>
+    <!-- Cancel button used to dismiss a message dialog and terminate the current SIM session-->
+    <string name="button_cancel">Cancel</string>
+    <!-- Yes button, used on a Yes/No confirmation screen -->
+    <string name="button_yes">Yes</string>
+    <!-- No button, used on a Yes/No confirmation screen -->
+    <string name="button_no">No</string>
+    <!-- Description for the type of text allowed in a form: alphanumeric or digits only -->
+    <string name="alphabet">Alphabets</string>
+    <!-- Type of alphabet text allowed in a form: 0-9, *, #, + characters only -->
+    <string name="digits">Digits (0-9, *, #, +)</string>
+    <!-- Default transition message when launching a call -->
+    <string name="default_call_setup_msg">Call in progress\u2026</string>
+
+    <string name="stk_app_state">Application state</string>
     <string name="enable_app">Enabled</string>
     <string name="disable_app">Disabled</string>
-    <string name="button_ok">OK</string>
-    <string name="button_call">Call</string>
-    <string name="button_cancel">Cancel</string>
-    <string name="button_yes">Yes</string>
-    <string name="button_no">No</string>
-    <string name="alphabet">Alphabets</string>
-    <string name="digits">Digits (0-9, *, #, +)</string>
-    <string name="launch_dialer">Launch Dialer?</string>
-    <string name="default_call_setup_msg">Call in progress\u2026</string>
-    <string name="launch_browser">Launch Browser?</string>
-    <string name="play_tone">Play tone</string>
-    <string name="help">Help</string>
 </resources>
diff --git a/src/com/android/stk/BootCompletedReceiver.java b/src/com/android/stk/BootCompletedReceiver.java
new file mode 100644
index 0000000..12cb32e
--- /dev/null
+++ b/src/com/android/stk/BootCompletedReceiver.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2007 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.stk;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+
+/**
+ * Boot completed receiver. used to reset the app install state every time the
+ * device boots.
+ *
+ */
+public class BootCompletedReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        String action = intent.getAction();
+
+        // make sure the app icon is removed every time the device boots.
+        if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
+            Bundle args = new Bundle();
+            args.putInt(StkAppService.OPCODE, StkAppService.OP_BOOT_COMPLETED);
+            context.startService(new Intent(context, StkAppService.class)
+                    .putExtras(args));
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/stk/StkActivity.java b/src/com/android/stk/StkActivity.java
deleted file mode 100644
index b442545..0000000
--- a/src/com/android/stk/StkActivity.java
+++ /dev/null
@@ -1,1317 +0,0 @@
-/*
- * Copyright (C) 2007 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.stk;
-
-import android.app.Dialog;
-import android.app.ListActivity;
-import android.app.ProgressDialog;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.graphics.Bitmap;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-
-import com.android.internal.telephony.gsm.stk.*;
-import android.util.Log;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.Window;
-import android.widget.Button;
-import android.widget.ImageView;
-import android.widget.ListView;
-import android.widget.TextView;
-
-import java.util.BitSet;
-import java.util.List;
-
-/**
- * Display main menu and items menu of the SIM application. Launch sub
- * activities and dialogs to interact with user.
- */
-public class StkActivity extends ListActivity implements View.OnClickListener {
-
-    // Members
-    private AppInterface mStkService = null;
-    private String mSelectedItem = null;
-    private Handler mHandler = null;
-    private BitSet mStkEvents = null;
-    private DialogEvent mActiveMsgDialogEvent = null;
-    private DialogEvent mActiveBrowserDialogEvent = null;
-    private MsgDialogParams mMsgDialogParams = new MsgDialogParams();
-    private MsgDialogParams mNextMsgDialogParams = new MsgDialogParams();
-    private BrowserDialogParams mBrowserDialogParams = new BrowserDialogParams();
-    private CallDialogParams mCallDialogParams = new CallDialogParams();
-
-    private TonePlayer mTonePlayer = null;
-    private WatchDog mTimeoutWatchDog = null;
-    private Object mMsgDialogSync = null;
-    private int mUiState = UI_STATE_IDLE;
-    private boolean mLaunchNextDialog = false;
-    private TextView mTitleText;
-    private ImageView mTitleIcon;
-    private com.android.internal.telephony.gsm.stk.Menu mCurrentMenu = null;
-
-    // Constants
-    private static final String TAG = "STK ACTIVITY";
-
-    private static final String UI_STATE = "Stk.ui.state";
-    private static final String STK_MENU = "Stk.ui.stkMenu";
-
-    // Internal Activity id
-    public static final int ACTIVITY_MAIN = 1;
-    public static final int ACTIVITY_GET_INPUT = 2;
-    public static final int ACTIVITY_GET_INKEY = 3;
-    public static final int ACTIVITY_GET_INKEY_YESNO = 4;
-    public static final int ACTIVITY_BROWSER = 5;
-    public static final int ACTIVITY_CALL = 6;
-
-    // Internal Dialog id
-    private static final int NO_DIALOG_ID = 0;
-    private static final int CALL_CONFIRM_DIALOG_ID = 1;
-    private static final int CALL_SETUP_DIALOG_ID = 2;
-    private static final int MSG_DIALOG_ID = 3;
-    private static final int BROWSER_DIALOG_ID = 4;
-
-    // Internal state id
-    private static final int UI_STATE_IDLE = 0;
-    private static final int UI_STATE_MAIN = 1;
-    private static final int UI_STATE_SELECT = 2;
-    private static final int UI_STATE_IN_MSG_DIALOG = 3;
-    private static final int UI_STATE_IN_BROWSER_DIALOG = 4;
-    private static final int UI_STATE_IN_CALL_CONFIRM_DIALOG = 5;
-    private static final int UI_STATE_IN_CALL_SETUP_DIALOG = 6;
-    private static final int UI_STATE_PLAY_TONE = 7;
-
-    // Message id to signal tone duration timeout.
-    private static final int STOP_TONE_MSG = 0xde;
-
-    // Inner class, implements WatchDog.Event. track the active state of a dialog
-    // Event should be set when dialog becomes inactive.
-    private class DialogEvent implements Event {
-        private boolean mActiveMsgDialog = true;
-
-        public void set() {
-            mActiveMsgDialog = true;
-        }
-
-        public void unSet() {
-            mActiveMsgDialog = false;
-        }
-
-        public boolean isSet() {
-            return mActiveMsgDialog;
-        }
-    }
-
-    // Container to store dialog parameters.
-    private class DialogParams {
-        // Constants
-        private static final String DIALOG_TEXT = "Dialog.text";
-        private static final String DIALOG_TITLE = "Dialog.title";
-        private static final String DIALOG_ATTR = "Dialog.attr";
-
-        String text;
-        TextAttribute attr;
-        String title;
-        Bitmap icon;
-        // timer
-        WatchDog timeoutWatchDog;
-
-        DialogParams() {
-            title = "";
-            attr = null;
-            text = "";
-            icon = null;
-            timeoutWatchDog = null;
-        }
-
-        void setTimer() {
-            dismissTimer();
-            timeoutWatchDog = new WatchDog(null, mHandler, null,
-                    StkApp.UI_TIMEOUT);
-        }
-
-        void dismissTimer() {
-            if (timeoutWatchDog != null) {
-                timeoutWatchDog.cancel();
-            }
-        }
-
-        DialogParams(String text, TextAttribute attr, String title, Bitmap icon) {
-            this.text = text;
-            this.attr = attr;
-            this.title = title;
-            this.icon = icon;
-        }
-
-        void packParams(Bundle bundle) {
-            bundle.putString(DIALOG_TEXT, this.text);
-            bundle.putString(DIALOG_TITLE, this.title);
-            bundle.putBundle(DIALOG_ATTR, Util.packTextAttr(this.attr));
-        }
-
-        void unPackParams(Bundle bundle) {
-            if (bundle == null) {
-                return;
-            }
-            this.text = bundle.getString(DIALOG_TEXT);
-            this.title = bundle.getString(DIALOG_TITLE);
-            this.attr = Util.unPackTextAttr(bundle.getBundle(DIALOG_ATTR));
-        }
-    }
-
-    // Container to store message dialog parameters.
-    private class MsgDialogParams extends DialogParams {
-        // Constants
-        private static final String MSG_DIALOG_RES = "MsgDialog.response";
-        private static final String MSG_DIALOG_CONIF = "MsgDialog.confirmed";
-
-        // Message dialog specific parameters.
-        boolean responseNeeded;
-        Object terminationLock;
-
-        MsgDialogParams() {
-            super();
-            responseNeeded = false;
-            terminationLock = new Object();
-        }
-
-        void setTimer() {
-            dismissTimer();
-            timeoutWatchDog = new WatchDog(null, mHandler,
-                    new RunTerminateMsgDialog(), StkApp.UI_TIMEOUT);
-        }
-
-        void packParams(Bundle bundle) {
-            if (bundle == null) {
-                return;
-            }
-            super.packParams(bundle);
-            bundle.putBoolean(MSG_DIALOG_RES, this.responseNeeded);
-        }
-
-        void unPackParams(Bundle bundle) {
-            if (bundle == null) {
-                return;
-            }
-            super.unPackParams(bundle);
-            this.responseNeeded = bundle.getBoolean(MSG_DIALOG_RES);
-        }
-    }
-
-    // Container to store browser dialog parameters.
-    private class BrowserDialogParams extends DialogParams {
-        // Constants
-        private static final String BROWSER_DIALOG_URI = "BrowserDialog.uri";
-        private static final String BROWSER_DIALOG_MODE = "BrowserDialog.mode";
-
-        // Browser dialog specific parameters.
-        Uri uri;
-        LaunchBrowserMode mode;
-
-        BrowserDialogParams() {
-            super();
-            // Set default uri.
-            uri = Uri.parse("file:///android_asset/html/home.html");
-            mode = LaunchBrowserMode.LAUNCH_NEW_BROWSER;
-        }
-
-        void setTimer() {
-            dismissTimer();
-            timeoutWatchDog = new WatchDog(null, mHandler,
-                    new RunTerminateBrowserDialog(), StkApp.UI_TIMEOUT);
-        }
-
-        void packParams(Bundle bundle) {
-            if (bundle == null) {
-                return;
-            }
-            super.packParams(bundle);
-            if (this.uri != null) {
-                bundle.putString(BROWSER_DIALOG_URI, this.uri.toString());
-            }
-            if (this.mode != null) {
-                bundle.putInt(BROWSER_DIALOG_MODE, this.mode.ordinal());
-            }
-        }
-
-        void unPackParams(Bundle bundle) {
-            if (bundle == null) {
-                return;
-            }
-            super.unPackParams(bundle);
-            String uriValue = bundle.getString(BROWSER_DIALOG_URI);
-            if (uriValue != null) {
-                this.uri = Uri.parse(uriValue);
-            }
-            int modeValue = bundle.getInt(BROWSER_DIALOG_MODE);
-            if (modeValue != 0) {
-                this.mode = LaunchBrowserMode.values() [modeValue];
-            }
-        }
-    }
-
-    private class CallDialogParams extends DialogParams {
-        // Constants
-        private static final String CALL_DIALOG_MSG = "CallDialog.message";
-
-        String callMsg;
-
-        CallDialogParams() {
-            super();
-        }
-
-        CallDialogParams(String text, TextAttribute attr, String title,
-                String callMsg) {
-            super(text, attr, title, null);
-            this.callMsg = callMsg;
-        }
-
-        void packParams(Bundle bundle) {
-            if (bundle == null) {
-                return;
-            }
-            bundle.putString(CALL_DIALOG_MSG, callMsg);
-        }
-
-        void unPackParams(Bundle bundle) {
-            if (bundle == null) {
-                return;
-            }
-            callMsg = bundle.getString(CALL_DIALOG_MSG);
-        }
-    }
-
-    // Runnable to be executed when message dialog are timed out.
-    private class RunTerminateMsgDialog implements Runnable {
-        public void run() {
-            terminateMsgDialog(ResultCode.NO_RESPONSE_FROM_USER);
-        }
-    }
-
-    // Runnable to be terminate browser confirmation dialog.
-    private class RunTerminateBrowserDialog implements Runnable {
-        public void run() {
-            terminateBrowserDialog(false, true);
-        }
-    }
-
-    // Runnable to be notify STK service user didn't respond to display text 
-    // command.
-    private class OnNoResponse implements Runnable {
-        public void run() {
-            mStkService.notifyNoResponse();
-            mUiState = UI_STATE_IDLE;
-        }
-    }
-
-    // Runnable to trigger refresh view on session end.
-    private class RunRefeshViewOnSessionEnd implements Runnable {
-        public void run() {
-            refreshViewOnSessionEnd();
-        }
-    }
-
-    /**
-     * Handler used to stop tones from playing when the duration ends.
-     */
-    Handler mToneStopper = new Handler() {
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-            case STOP_TONE_MSG:
-                terminateTone();
-                break;
-            }
-        }
-    };
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        int dialogId = NO_DIALOG_ID;
-        super.onCreate(icicle);
-
-        // Remove the default title, customized one is used.
-        requestWindowFeature(Window.FEATURE_NO_TITLE);
-        // Set the layout for this activity.
-        setContentView(R.layout.stk_menu_list);
-
-        mTitleText = (TextView) findViewById(R.id.title_text);
-        mTitleIcon = (ImageView) findViewById(R.id.title_icon);
-
-        // Initialize members
-        mStkService = Service.getInstance();
-        if (mStkService == null) {
-            Log.d(TAG, "Unable to get application handle ==> Activity stoped");
-            finish();
-        }
-
-        // Instantiate members
-        mHandler = new Handler();
-        mMsgDialogSync = new Object();
-        mActiveMsgDialogEvent = new DialogEvent();
-        mActiveBrowserDialogEvent = new DialogEvent();
-
-        // Synchronize application state with the service, only if it's on main 
-        // state. This is usually true when the application is launched for the 
-        // first time. Otherwise the application state will be preserved using 
-        // onSaveInstanceState(...) & onRestoreInstaceState(...).
-        if (mStkService.getState() == AppInterface.State.MAIN_MENU) {
-            mUiState = UI_STATE_MAIN;
-            mCurrentMenu = mStkService.getCurrentMenu();
-        }
-    }
-
-    public void onClick(View v) {
-        switch(v.getId()) {
-        case R.id.button_ok:
-            // used on message dialog.
-            terminateMsgDialog(ResultCode.OK);
-            break;
-        case R.id.button_no:
-            // used on launch browser dialog.
-            terminateBrowserDialog(false, true);
-            break;
-        case R.id.button_yes:
-            // used on launch browser dialog.
-            terminateBrowserDialog(true, true);
-            break;
-        case R.id.button_call:
-            // used on set up call dialog.
-            terminateCallConfirmDialog(true, true);
-            break;
-            // used on set up call dialog.
-        case R.id.button_cancel:
-            terminateCallConfirmDialog(false, true);
-            break;
-        }
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-
-        // Setting stk service command listener to null will stop the service
-        // from trying to send messages when the app is paused.
-        mStkService.setCommandListener(null);
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        
-        // Set stk service command listener to receive proactive commands.
-        mStkService.setCommandListener(this.new StkCmdListener());
-
-        // If application is resumed from call setup go back to the menu state.
-        if (mUiState == UI_STATE_IN_CALL_SETUP_DIALOG) {
-            switch (mStkService.getState()) {
-            case SELECT_ITEM:
-                mUiState = UI_STATE_SELECT;
-                break;
-            case MAIN_MENU:
-                mUiState = UI_STATE_MAIN;
-                mCurrentMenu = mStkService.getCurrentMenu();
-                break;
-            default:
-                mStkService.terminateSession();
-                return;
-            }
-        }
-
-        // Render application view.
-        refreshView();
-    }
-
-    @Override
-    public void onDestroy() {
-        super.onDestroy();
-        if (mTimeoutWatchDog != null) {
-            mTimeoutWatchDog.cancel();
-        }
-
-        // If Toneplayer was used, release it's resources.
-        if (mTonePlayer != null) {
-            mTonePlayer.release();
-        }
-    }
-
-    @Override
-    protected void onListItemClick(ListView l, View v, int position, long id) {
-        super.onListItemClick(l, v, position, id);
-
-        AppInterface.State state = mStkService.getState();
-        Item item = getSelectedItem(position);
-        if (item == null) {
-            return;
-        }
-        switch (state) {
-        case MAIN_MENU:
-            // Notify the SIM about the menu selection id.
-            mStkService.notifyMenuSelection(item.id, false);
-            break;
-        case SELECT_ITEM:
-            // Terminate timeout watchdog for SELECT_ITEM.
-            if (mTimeoutWatchDog != null) {
-                mTimeoutWatchDog.cancel();
-            }
-            // Save item string for display purposes.
-            mSelectedItem = mCurrentMenu.items.get(position).toString();
-            // Notify the SIM about the item selection id.
-            mStkService.notifySelectedItem(item.id, false);
-            break;
-        default:
-            // If application and service are not synchronized, terminate 
-            // the current session.
-            mStkService.terminateSession();
-        }
-    }
-
-    @Override
-    public boolean onKeyDown(int keyCode, KeyEvent event) {
-
-        switch (keyCode) {
-        case KeyEvent.KEYCODE_BACK:
-            switch (mUiState) {
-            case UI_STATE_SELECT:
-                cancelTimeOut();
-                // Signal stk service to go back, if failed go to the main menu.
-                if (!mStkService.backwardMove()) {
-                    mStkService.terminateSession();
-                }
-                mUiState = UI_STATE_IDLE;
-                return true;
-            case UI_STATE_MAIN:
-                mUiState = UI_STATE_IDLE;
-                break;
-            }
-            break;
-        }
-
-        return super.onKeyDown(keyCode, event);
-    }
-
-    @Override
-    public boolean onTrackballEvent(MotionEvent event) {
-        resetTimeOut();
-        return super.onTrackballEvent(event);
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        resetTimeOut();
-        return super.onTouchEvent(event);
-    }
-
-    @Override
-    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-        super.onActivityResult(requestCode, resultCode, data);
-        Bundle extras = null;
-        boolean helpRequired = false;
-        boolean yesNoResponse = false;
-        String inputResponse = null;
-        char inKeyResponse = 'F';
-        
-        if (data != null) {
-            extras = data.getExtras();
-        }
-
-        switch (resultCode) {
-        case StkApp.RESULT_HELP:
-            helpRequired = true;
-        case StkApp.RESULT_OK:
-            switch (requestCode) {
-            case ACTIVITY_GET_INPUT:
-                if (extras != null) {
-                    inputResponse = extras.getString(Util.INPUT_TYPE_TEXT);
-                }
-                mStkService.notifyInput(inputResponse, helpRequired);
-                break;
-            case ACTIVITY_GET_INKEY:
-                if (extras != null) {
-                    inKeyResponse = extras.getChar(Util.INPUT_TYPE_KEY);
-                }
-                mStkService.notifyInkey(inKeyResponse, helpRequired);
-                break;
-            case ACTIVITY_GET_INKEY_YESNO:
-                if (extras != null) {
-                    yesNoResponse = extras.getBoolean(Util.INPUT_TYPE_KEY);
-                }
-                mStkService.notifyInkey(yesNoResponse, helpRequired);
-                break;
-            case ACTIVITY_BROWSER:
-                // Handle browser termination event
-                if (getEventStatus(Service.UICC_EVENT_BROWSER_TERMINATION)) {
-                    setEventStatus(Service.UICC_EVENT_BROWSER_TERMINATION,
-                            false);
-                    mStkService.notifyBrowserTermination(false);
-                    break;
-                }
-            case ACTIVITY_CALL:
-                break;
-            }
-            break;
-        case StkApp.RESULT_TIMEDOUT:
-            mStkService.notifyNoResponse();
-            break;
-        case StkApp.RESULT_BACKWARD:
-            mStkService.backwardMove();
-            break;
-        case StkApp.RESULT_END_SESSION:
-            mStkService.terminateSession();
-            break;
-        }
-    }
-
-    @Override
-    public boolean onCreateOptionsMenu(android.view.Menu menu) {
-        super.onCreateOptionsMenu(menu);
-        menu.add(0, StkApp.MENU_ID_MAIN, 1, R.string.sim_main_menu);
-        menu.add(0, StkApp.MENU_ID_HELP, 2, R.string.help);
-        return true;
-    }
-
-    @Override
-    public boolean onPrepareOptionsMenu(android.view.Menu menu) {
-        super.onPrepareOptionsMenu(menu);
-        boolean helpVisible = false;
-        boolean mainVisible = false;
-
-        if (mUiState == UI_STATE_SELECT) {
-            mainVisible = true;
-        }
-        if (mCurrentMenu != null) {
-            helpVisible = mCurrentMenu.helpAvailable;
-        }
-        
-        menu.findItem(StkApp.MENU_ID_MAIN).setVisible(mainVisible);
-        menu.findItem(StkApp.MENU_ID_HELP).setVisible(helpVisible);
-
-        return true;
-    }
-
-    @Override
-    public boolean onOptionsItemSelected(MenuItem item) {
-        switch (item.getItemId()) {
-        case StkApp.MENU_ID_MAIN:
-            // Cancel timeout thread.
-            cancelTimeOut();
-            // Terminate SIM session
-            mStkService.terminateSession();
-            // Set ui state to idle.
-            mUiState = UI_STATE_IDLE;
-            return true;
-        case StkApp.MENU_ID_HELP:
-            int position = getSelectedItemPosition();
-            Item stkItem = getSelectedItem(position);
-            if (item == null) {
-                break;
-            }
-            switch(mUiState) {
-            case UI_STATE_MAIN:
-                mStkService.notifyMenuSelection(stkItem.id, true);
-                break;
-            case UI_STATE_SELECT:
-                mStkService.notifySelectedItem(stkItem.id, true);
-                break;
-            }
-            return true;
-        }
-        return super.onOptionsItemSelected(item);
-    }
-
-    @Override
-    protected void onSaveInstanceState(Bundle outState) {
-        if (StkApp.DBG) Log.d(TAG, "onSaveInstanceState");
-
-        super.onSaveInstanceState(outState);
-
-        // Setting stk service command listener to null will stop the service
-        // from trying to send messages while the state is being saved. 
-        // This function is also called in onPause for cases where state is not 
-        // preserved. 
-        mStkService.setCommandListener(null);
-
-        outState.putInt(UI_STATE, mUiState);
-        outState.putParcelable(STK_MENU, mCurrentMenu);
-
-        // Preserve dialog parameters
-        switch (mUiState) {
-        case UI_STATE_IN_MSG_DIALOG:
-            mMsgDialogParams.packParams(outState);
-            mMsgDialogParams.responseNeeded = false;
-            terminateMsgDialog();
-            removeDialog(MSG_DIALOG_ID);
-            break;
-        case UI_STATE_IN_BROWSER_DIALOG:
-            mBrowserDialogParams.packParams(outState);
-            terminateBrowserDialog(false, false);
-            removeDialog(BROWSER_DIALOG_ID);
-            break;
-        case UI_STATE_IN_CALL_CONFIRM_DIALOG:
-            mCallDialogParams.packParams(outState);
-            terminateCallConfirmDialog(false, false);
-            removeDialog(CALL_CONFIRM_DIALOG_ID);
-            break;
-        case UI_STATE_IN_CALL_SETUP_DIALOG:
-            dismissDialog(CALL_SETUP_DIALOG_ID);
-            removeDialog(CALL_SETUP_DIALOG_ID);
-            break;
-        case UI_STATE_PLAY_TONE:
-            mToneStopper.removeMessages(STOP_TONE_MSG);
-            terminateTone();
-            // Once playing the tone is done the session is ended so the application 
-            // should go back to main state.
-            outState.putInt(UI_STATE, UI_STATE_MAIN);
-            break;
-        }
-    }
-
-    @Override
-    protected void onRestoreInstanceState(Bundle savedInstanceState) {
-        if (StkApp.DBG) Log.d(TAG, "onRestoreInstanceState");
-
-        super.onRestoreInstanceState(savedInstanceState);
-
-        mUiState = savedInstanceState.getInt(UI_STATE);
-        mCurrentMenu = savedInstanceState.getParcelable(STK_MENU);
-
-        switch (mUiState) {
-        case UI_STATE_IN_MSG_DIALOG:
-            MsgDialogParams m = new MsgDialogParams();
-            m.unPackParams(savedInstanceState);
-            prepareMsgDialog(m.text, m.attr, m.title, m.responseNeeded, m.icon);
-            break;
-        case UI_STATE_IN_BROWSER_DIALOG:
-            mBrowserDialogParams.unPackParams(savedInstanceState);
-            break;
-        case UI_STATE_IN_CALL_CONFIRM_DIALOG:
-            mCallDialogParams.unPackParams(savedInstanceState);
-            break;
-        }
-    }
-
-    private Item getSelectedItem(int position) {
-        Item item = null;
-        if (mCurrentMenu != null) {
-            try {
-                item = mCurrentMenu.items.get(position);
-            } catch (IndexOutOfBoundsException e) {
-                if (StkApp.DBG) {
-                    Log.d(TAG, "Invalid menu");
-                }
-            } catch (NullPointerException e) {
-                if (StkApp.DBG) {
-                    Log.d(TAG, "Invalid menu");
-                }
-            }
-        }
-        return item;
-    }
-
-    // Bind list adapter to the items list.
-    private void displayMenu() {
-
-        if (mCurrentMenu != null) {
-            // create an array adapter for the menu list
-            StkMenuAdapter adapter = new StkMenuAdapter(this,
-                    mCurrentMenu.items, mCurrentMenu.itemsIconSelfExplanatory);
-            // Bind menu list to the new adapter.
-            setListAdapter(adapter);
-
-            // Display title & title icon
-            if (mCurrentMenu.titleIcon != null) {
-                mTitleIcon.setImageBitmap(mCurrentMenu.titleIcon);
-            } else {
-                mTitleIcon.setVisibility(View.GONE);
-            }
-            if (!mCurrentMenu.titleIconSelfExplanatory) {
-                if (mCurrentMenu.title == null) {
-                    mTitleText.setText(R.string.app_name);
-                } else {
-                    mTitleText.setText(mCurrentMenu.title);
-                }
-            }
-            // Set default item
-            setSelection(mCurrentMenu.defaultItem);
-        }
-    }
-
-    private void refreshView() {
-        displayMenu();
-
-        // In case a dialog needs to be refreshed.
-        switch (mUiState) {
-        case UI_STATE_IN_MSG_DIALOG:
-            launchMsgDialog();
-            break;
-        case UI_STATE_IN_BROWSER_DIALOG:
-            launchBrowserDialog();
-            break;
-        case UI_STATE_IN_CALL_CONFIRM_DIALOG:
-            launchCallConfirmDialog();
-            break;
-        default:
-            return;
-        }
-    }
-
-    private void refreshViewOnSessionEnd() {
-        cancelTimeOut();
-        switch (mStkService.getState()) {
-        case MAIN_MENU:
-            mUiState = UI_STATE_MAIN;
-            mCurrentMenu = mStkService.getCurrentMenu();
-            refreshView();
-            break;
-        case IDLE:
-            finish();
-            break;
-        }
-    }
-
-    private void resetTimeOut() {
-        if (mTimeoutWatchDog != null) {
-            // Reset timeout.
-            mTimeoutWatchDog.reset();
-        }
-    }
-
-    private void cancelTimeOut() {
-        if (mTimeoutWatchDog != null) {
-            // Reset timeout.
-            mTimeoutWatchDog.cancel();
-        }
-    }
-
-    private void pauseTimeOut() {
-        if (mTimeoutWatchDog != null) {
-            // Reset timeout.
-            mTimeoutWatchDog.pause();
-        }
-    }
-
-    private void resumeTimeOut() {
-        if (mTimeoutWatchDog != null) {
-            // Reset timeout.
-            mTimeoutWatchDog.unpause();
-        }
-    }
-
-    private void prepareDialog(DialogParams params, String text,
-            TextAttribute attr, String title, Bitmap icon) {
-        if (params == null) return;
-
-        params.text = text;
-        params.attr = attr;
-        params.title = title;
-        params.icon = icon;
-    }
-
-    // Set text dialog parameters into a member.
-    private void prepareMsgDialog(String text, TextAttribute attrs,
-            String title, boolean responseNeeded, Bitmap icon) {
-        synchronized (mMsgDialogSync) {
-            prepareDialog(mNextMsgDialogParams, text, attrs, title, icon);
-            mNextMsgDialogParams.responseNeeded = responseNeeded;
-        }
-    }
-
-    // Set text dialog parameters into a member.
-    private void prepareBrowserDialog(String text, TextAttribute attrs,
-            String title, Uri uri, LaunchBrowserMode mode) {
-
-        prepareDialog(mBrowserDialogParams, text, attrs, title, null);
-        mBrowserDialogParams.uri = uri;
-        mBrowserDialogParams.mode = mode;
-    }
-
-    private void prepareCallDialog(String text, TextAttribute attrs,
-            String title, String callMsg) {
-        prepareDialog(mCallDialogParams, text, attrs, title, null);
-        mCallDialogParams.callMsg = callMsg;
-    }
-
-    // Opens display text dialog. MUST be preceded by prepareMsgDialog(...)
-    private void launchMsgDialog() {
-        // Pause timeout thread for Select Item.
-        pauseTimeOut();
-        mUiState = UI_STATE_IN_MSG_DIALOG;
-        mActiveMsgDialogEvent.unSet();
-        synchronized (mMsgDialogSync) {
-            mMsgDialogParams = mNextMsgDialogParams;
-        }
-        mMsgDialogParams.setTimer();
-        showDialog(MSG_DIALOG_ID);
-    }
-
-    // Opens display browser confirmation dialog. MUST be preceded by
-    // prepareBrowserDialog(...)
-    private void launchBrowserDialog() {
-        mUiState = UI_STATE_IN_BROWSER_DIALOG;
-        mActiveBrowserDialogEvent.unSet();
-        mBrowserDialogParams.setTimer();
-        showDialog(BROWSER_DIALOG_ID);
-    }
-
-    // Opens call/cancel confirmation dialog
-    private void launchCallConfirmDialog() {
-        mUiState = UI_STATE_IN_CALL_CONFIRM_DIALOG;
-        showDialog(CALL_CONFIRM_DIALOG_ID);
-    }
-
-    // Opens setup call dialog
-    private void launchCallSetupDialog() {
-        mUiState = UI_STATE_IN_CALL_SETUP_DIALOG;
-        showDialog(CALL_SETUP_DIALOG_ID);
-    }
-
-    // Same as terminateMsgDialog(), with additional ResultCode send to the STK 
-    // Service.
-    private void terminateMsgDialog(ResultCode terminationCode) {
-        terminateMsgDialog();
-        if (mMsgDialogParams.responseNeeded) {
-            mStkService.notifyDisplayTextEnded(terminationCode);
-        }
-    }
-
-    private void terminateMsgDialog() {
-        synchronized (mMsgDialogParams.terminationLock) {
-            dismissDialog(MSG_DIALOG_ID);
-            mMsgDialogParams.dismissTimer();
-            // Resume timeout thread for Select Item.
-            resumeTimeOut();
-            if (mLaunchNextDialog == true) {
-                synchronized (this) {
-                    mLaunchNextDialog = false;
-                }
-                launchMsgDialog();
-            } else {
-                mUiState = UI_STATE_IDLE;
-                // signal message dialog event.
-                mActiveMsgDialogEvent.set();
-            }
-        }
-    }
-
-    private void terminateBrowserDialog(boolean userConfirmed,
-            boolean notifyService) {
-        dismissDialog(BROWSER_DIALOG_ID);
-        mBrowserDialogParams.dismissTimer();
-        if (userConfirmed) {
-            launchBrowser(mBrowserDialogParams.uri, mBrowserDialogParams.mode);
-        }
-        if (notifyService) {
-            mStkService.notifyLaunchBrowser(userConfirmed);
-        }
-        mUiState = UI_STATE_IDLE;
-        // signal browser dialog event.
-        mActiveBrowserDialogEvent.set();
-    }
-
-    private void terminateCallConfirmDialog(boolean call, boolean notifyService) {
-        dismissDialog(CALL_CONFIRM_DIALOG_ID);
-        if (call) {
-            if (mCallDialogParams.callMsg == null) {
-                mCallDialogParams.callMsg = getString(R.string.default_call_setup_msg);
-            }
-            launchCallSetupDialog(); 
-        } else {
-            mUiState = UI_STATE_IDLE;
-        }
-        if (notifyService) {
-            mStkService.acceptOrRejectCall(call);
-        }
-    }
-
-    private void terminateTone() {
-        if (mTonePlayer != null) {
-            mTonePlayer.stop();
-            mStkService.notifyToneEnded();
-        }
-        mUiState = UI_STATE_IDLE;
-    }
-
-    @Override
-    protected Dialog onCreateDialog(int id) {
-        Dialog dialog = null;
-        if (id == CALL_SETUP_DIALOG_ID) {
-            dialog = new ProgressDialog(this);
-            dialog.setCancelable(false);
-            ((ProgressDialog) dialog).setMessage(mCallDialogParams.callMsg);
-            ((ProgressDialog) dialog).setIndeterminate(true);
-        } else {
-            dialog = new Dialog(this);
-
-            switch (id) {
-            case MSG_DIALOG_ID:
-                dialog.setContentView(R.layout.stk_msg_dialog);
-                break;
-            case BROWSER_DIALOG_ID:
-                dialog.setContentView(R.layout.stk_input);
-
-                View yesNoLayout = dialog.findViewById(R.id.yes_no_layout);
-                View normalLayout = dialog.findViewById(R.id.normal_layout);
-
-                yesNoLayout.setVisibility(View.VISIBLE);
-                normalLayout.setVisibility(View.GONE);
-                break;
-            case CALL_CONFIRM_DIALOG_ID:
-                dialog.setContentView(R.layout.stk_call_dialog);
-                break;
-            }
-        }
-        return dialog;
-    }
-
-    @Override
-    protected void onPrepareDialog(int id, Dialog dialog) {
-        DialogParams currentDialogParams = null;
-        TextView promptView = null;
-        ImageView imageView = null;
-
-        switch (id) {
-        case MSG_DIALOG_ID:
-            currentDialogParams = mMsgDialogParams;
-            promptView = (TextView) dialog.findViewById(R.id.dialog_message);
-            imageView = (ImageView) dialog.findViewById(R.id.dialog_icon);
-            Button b = (Button) dialog.findViewById(R.id.button_ok);
-            b.setOnClickListener(this);
-            dialog.setCanceledOnTouchOutside(false);
-            dialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
-                public boolean onKey(DialogInterface dialog, int keyCode,
-                        KeyEvent event) {
-                    switch (keyCode) {
-                    case KeyEvent.KEYCODE_BACK:
-                        terminateMsgDialog(ResultCode.BACKWARD_MOVE_BY_USER);
-                        break;
-                    }
-                    return false;
-                }
-            });
-            break;
-        case CALL_CONFIRM_DIALOG_ID:
-            currentDialogParams = mCallDialogParams;
-            promptView = (TextView) dialog.findViewById(R.id.prompt);
-            Button call = (Button) dialog.findViewById(R.id.button_call);
-            Button cancel = (Button) dialog.findViewById(R.id.button_cancel);
-            call.setOnClickListener(this);
-            cancel.setOnClickListener(this);
-            dialog.setCancelable(false);
-            break;
-        case BROWSER_DIALOG_ID:
-            currentDialogParams = mBrowserDialogParams;
-            promptView = (TextView) dialog.findViewById(R.id.prompt);
-            Button y = (Button) dialog.findViewById(R.id.button_yes);
-            Button n = (Button) dialog.findViewById(R.id.button_no);
-            y.setOnClickListener(this);
-            n.setOnClickListener(this);
-            dialog.setCancelable(false);
-            break;
-        default:
-            return;
-        }
-        // Set prompt and title.
-        promptView.setText(currentDialogParams.text);
-        // Set title if present... if not remove it from the layout.
-        if (currentDialogParams.title != null) {
-            dialog.setTitle(currentDialogParams.title);
-        } else {
-            View t = dialog.findViewById(android.R.id.title);
-            t.setVisibility(View.GONE);
-        }
-        if(currentDialogParams.icon != null) {
-            imageView.setImageBitmap(currentDialogParams.icon);
-        } else if (imageView != null) {
-            imageView.setVisibility(View.GONE);
-        }
-    }
-
-    // Opens the browser
-    private void launchBrowser(Uri uri, LaunchBrowserMode mode) {
-        // Set browser launch mode
-        Intent intent = new Intent(Intent.ACTION_VIEW);
-        intent.setClassName("com.android.browser",
-                "com.android.browser.BrowserActivity");
-        intent.setData(uri);
-        intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
-        intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
-        switch (mode) {
-        case USE_EXISTING_BROWSER:
-            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-            break;
-        case LAUNCH_NEW_BROWSER:
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            break;
-        case LAUNCH_IF_NOT_ALREADY_LAUNCHED:
-            intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
-            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            break;
-        }
-        // start browser activity
-        startActivity(intent);
-    }
-
-    private void updateEventsSet(BitSet events) {
-        mStkEvents.or(events);
-    }
-
-    private void setEventStatus(int event, boolean state) {
-        if (mStkEvents == null) return;
-
-        mStkEvents.set(event, state);
-    }
-
-    private boolean getEventStatus(int event) {
-        if (mStkEvents == null) return false;
-
-        return mStkEvents.get(event);
-    }
-
-    // Private inner class, implements CommandListener I/F to get callback calls
-    // from the STK service.
-    private class StkCmdListener implements CommandListener {
-
-        public void onCallSetup(String confirmMsg, List<TextAttribute> textAttrs,
-                String callMsg) {
-            if (StkApp.DBG) Log.d(TAG, "onCallSetup");
-
-            TextAttribute attr = null;
-            String title = getString(R.string.launch_dialer);
-            
-            if (textAttrs != null && textAttrs.size() > 0) {
-                attr = textAttrs.get(0);
-            }
-            // Launch call confirmation dialog.
-            prepareCallDialog(confirmMsg, attr, title, callMsg);
-            launchCallConfirmDialog();
-        }
-
-       public void onDisplayText(String text, List<TextAttribute> textAttrs,
-                boolean isHighPriority, boolean userClear,
-                boolean responseNeeded, Bitmap icon) {
-
-            if (StkApp.DBG) Log.d(TAG, "onDisplayText: " + text);
-
-            // Store dialog parameters to be used just before dialog creation.
-            TextAttribute attr = null;
-            if (textAttrs != null && textAttrs.size() > 0) {
-                attr = textAttrs.get(0);
-            }
-            prepareMsgDialog(text, attr, null, responseNeeded, icon);
-
-            // If there is an active message dialog, signal to launch a new dialog 
-            // when the current one is done.
-            if (mUiState == UI_STATE_IN_MSG_DIALOG) {
-                synchronized (StkActivity.this) {
-                    mLaunchNextDialog = true;
-                }
-                if (isHighPriority) {
-                    terminateMsgDialog(ResultCode.OK);
-                }
-            } else {
-                launchMsgDialog();
-            }
-        }
-
-        public void onSetUpMenu(com.android.internal.telephony.gsm.stk.Menu menu) {
-            if (StkApp.DBG) Log.d(TAG, "onSetUpMenu");
-
-            mUiState = UI_STATE_MAIN; 
-            mCurrentMenu = menu; 
-            displayMenu();
-        }
-
-        public void onGetInkey(String text, List<TextAttribute> textAttrs,
-                boolean yesNo, boolean digitOnly, boolean ucs2,
-                boolean immediateResponse, boolean helpAvailable) {
-
-            if (StkApp.DBG) Log.d(TAG, "onGetInkey" + text);
-
-            Intent intent = new Intent(StkActivity.this, StkInputActivity.class);
-            int subActivityId = yesNo ? ACTIVITY_GET_INKEY_YESNO
-                    : ACTIVITY_GET_INKEY;
-
-            // put command data inside the intent.
-            intent.putExtra(Util.INPUT_TYPE, Util.INPUT_TYPE_KEY);
-            intent.putExtra(Util.INPUT_PROMPT, text);
-
-            if (textAttrs != null && textAttrs.size() > 0) {
-                TextAttribute attr = textAttrs.get(0);
-                Bundle texttAttrBundle;
-                if (attr != null) {
-                    texttAttrBundle = Util.packTextAttr(attr);
-                    intent.putExtra(Util.INPUT_TEXT_ATTRS, texttAttrBundle);
-                }
-            }
-            // Pack the global input attributes into the intent.
-            Bundle glblAttrBundle = new Bundle();
-            glblAttrBundle.putBoolean(Util.INPUT_ATTR_YES_NO, yesNo);
-            glblAttrBundle.putBoolean(Util.INPUT_ATTR_DIGITS, digitOnly);
-            glblAttrBundle.putBoolean(Util.INPUT_ATTR_UCS2, ucs2);
-            glblAttrBundle.putBoolean(Util.INPUT_ATTR_IMD_RESPONSE,
-                    immediateResponse);
-            glblAttrBundle.putBoolean(Util.INPUT_ATTR_HELP, helpAvailable);
-            intent.putExtra(Util.INPUT_GLBL_ATTRS, glblAttrBundle);
-
-            // Start the input sub activity
-            startActivityForResult(intent, subActivityId);
-        }
-
-        public void onGetInput(String text, String defaultText, int minLen,
-                int maxLen, boolean noMaxLimit, List<TextAttribute> textAttrs,
-                boolean digitOnly, boolean ucs2, boolean echo,
-                boolean helpAvailable) {
-
-            if (StkApp.DBG) Log.d(TAG, "onGetInput: " + text);
-
-            Intent intent = new Intent(StkActivity.this, StkInputActivity.class);
-            // put command data inside the intent.
-            intent.putExtra(Util.INPUT_TYPE, Util.INPUT_TYPE_TEXT);
-            intent.putExtra(Util.INPUT_PROMPT, text);
-            if (defaultText != null) {
-                intent.putExtra(Util.INPUT_DEFAULT, defaultText);
-            }
-
-            // Pack text attributes into the intent.
-            if (textAttrs != null && textAttrs.size() > 0) {
-                TextAttribute attr = textAttrs.get(0);
-                if (attr != null) {
-                    Bundle texttAttrBundle = Util.packTextAttr(attr);
-                    intent.putExtra(Util.INPUT_TEXT_ATTRS, texttAttrBundle);
-                }
-            }
-            // Pack the global input attributes into the intent.
-            Bundle glblAttrBundle = new Bundle();
-            glblAttrBundle.putInt(Util.INPUT_ATTR_MINLEN, minLen);
-            glblAttrBundle.putInt(Util.INPUT_ATTR_MAXLEN, maxLen);
-            glblAttrBundle.putBoolean(Util.INPUT_ATTR_NOMAAXLIM, noMaxLimit);
-            glblAttrBundle.putBoolean(Util.INPUT_ATTR_DIGITS, digitOnly);
-            glblAttrBundle.putBoolean(Util.INPUT_ATTR_UCS2, ucs2);
-            glblAttrBundle.putBoolean(Util.INPUT_ATTR_ECHO, echo);
-            glblAttrBundle.putBoolean(Util.INPUT_ATTR_HELP, helpAvailable);
-            intent.putExtra(Util.INPUT_GLBL_ATTRS, glblAttrBundle);
-
-            // Start the input sub activity
-            startActivityForResult(intent, ACTIVITY_GET_INPUT);
-        }
-
-        public void onSelectItem(com.android.internal.telephony.gsm.stk.Menu menu, 
-                PresentationType presentationType) {
-
-            if (StkApp.DBG) Log.d(TAG, "onSelectItem: " + menu.title);
-
-            mCurrentMenu = menu;
-
-            // If activity is already inside a message dialog, launch the next 
-            // item list when that message is dismissed. 
-            if (mUiState != UI_STATE_IN_MSG_DIALOG) {
-                mUiState = UI_STATE_SELECT;
-                displayMenu();
-                // launch timeout watchdog to signal no response from user.
-                mTimeoutWatchDog = new WatchDog(null, mHandler,
-                        new OnNoResponse(), StkApp.UI_TIMEOUT);
-            } else {
-                new WatchDog(mActiveMsgDialogEvent, mHandler, new Runnable() {
-                    public void run() {
-                        mUiState = UI_STATE_SELECT;
-                        displayMenu();
-                        // launch timeout wathdog to signal no response from
-                        // user.
-                        mTimeoutWatchDog = new WatchDog(null, mHandler,
-                                new OnNoResponse(), StkApp.UI_TIMEOUT);
-                    }
-                }, WatchDog.TIMEOUT_WAIT_FOREVER);
-            } 
-        }
-
-        public void onSetUpEventList(BitSet events) throws ResultException {
-            if (StkApp.DBG) Log.d(TAG, "onSetUpEventList");
-
-            if (events == null || events.isEmpty()) {
-                throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING);
-            }
-
-            updateEventsSet(events);
-        }
-
-        public void onLaunchBrowser(String url, String confirmMsg,
-                List<TextAttribute> confirmMsgAttrs,
-                final LaunchBrowserMode mode) {
-            if (StkApp.DBG) Log.d(TAG, "onLaunchBrowser: " + url);
-
-            TextAttribute attrs = null;
-            String title = getString(R.string.launch_browser);
-            Uri uri = url == null ? null : Uri.parse(url);
-
-            // Launch browser confirmation dialog.
-            if (confirmMsg != null) {
-                if (confirmMsgAttrs != null && confirmMsgAttrs.size() > 0) {
-                    attrs = confirmMsgAttrs == null ? null : confirmMsgAttrs
-                            .get(0);
-                }
-                prepareBrowserDialog(confirmMsg, attrs, title, uri, mode);
-                launchBrowserDialog();
-            } else {
-                mStkService.notifyLaunchBrowser(true);
-                launchBrowser(uri, mode);
-            }
-        }
-
-        public void onPlayTone(Tone tone, String text,
-                List<TextAttribute> textAttrs, Duration duration)
-                throws ResultException {
-            if (StkApp.DBG) Log.d(TAG, "onPlayTone:" + tone + " Message:" + text);
-
-            if (text != null) {
-                String title = getString(R.string.play_tone);
-                TextAttribute attrs = textAttrs == null ? null : textAttrs
-                        .get(0);
-                prepareMsgDialog(text, attrs, title, false, null);
-                launchMsgDialog();
-            }
-            if (mTonePlayer == null) {
-                mTonePlayer = new TonePlayer();
-            }
-            mTonePlayer.play(tone);
-            int timeout = StkApp.calculateToneDuration(duration);
-            mToneStopper.sendEmptyMessageDelayed(STOP_TONE_MSG, timeout);
-            mUiState = UI_STATE_PLAY_TONE;
-        }
-
-        public void onSessionEnd() {
-            if (StkApp.DBG) Log.d(TAG, "onSessionEnd");
-
-            // If any message dialog is active wait until it is finish before
-            // the refreshing the view.
-            synchronized (mMsgDialogParams.terminationLock) {
-                if (mUiState == UI_STATE_IN_MSG_DIALOG) {
-                    new WatchDog(mActiveMsgDialogEvent,
-                            StkActivity.this.mHandler,
-                            new RunRefeshViewOnSessionEnd(),
-                            WatchDog.TIMEOUT_WAIT_FOREVER);
-                } else {
-                    refreshViewOnSessionEnd();
-                }
-            }
-        }
-    }
-}
diff --git a/src/com/android/stk/StkApp.java b/src/com/android/stk/StkApp.java
index cabbb19..ebd52b1 100644
--- a/src/com/android/stk/StkApp.java
+++ b/src/com/android/stk/StkApp.java
@@ -16,39 +16,36 @@
 
 package com.android.stk;
 
-import android.app.Activity;
 import android.app.Application;
+
 import com.android.internal.telephony.gsm.stk.Duration;
 
 /**
- * Top-level Application class for the Phone app.
+ * Top-level Application class for STK app.
  */
-public class StkApp extends Application {
+abstract class StkApp extends Application {
     // Application constants
     public static final boolean DBG = true;
 
-    // Result values for sub activities started by the main StkActivity.
-    static final int RESULT_OK = Activity.RESULT_OK;
-    static final int RESULT_TIMEDOUT = RESULT_OK + 10;
-    static final int RESULT_BACKWARD = RESULT_OK + 11;
-    static final int RESULT_HELP = RESULT_OK + 12;
-    static final int RESULT_END_SESSION = RESULT_OK + 20;
-
     // Identifiers for option menu items
-    static final int MENU_ID_MAIN = android.view.Menu.FIRST;
-    static final int MENU_ID_HELP = android.view.Menu.FIRST + 1;
+    static final int MENU_ID_END_SESSION = android.view.Menu.FIRST;
+    static final int MENU_ID_BACK = android.view.Menu.FIRST + 1;
+    static final int MENU_ID_HELP = android.view.Menu.FIRST + 2;
 
     // UI timeout, 30 seconds - used for display dialog and activities.
-    static final int UI_TIMEOUT = (20 * 1000);
+    static final int UI_TIMEOUT = (40 * 1000);
 
     // Tone default timeout - 2 seconds
     static final int TONE_DFEAULT_TIMEOUT = (2 * 1000);
 
+    public static final String TAG = "STK App";
+
     /**
-     * This function calculate the time in MS a tone should be played.
+     * This function calculate the time in MS from a duration instance.
+     * returns zero when duration is null.
      */
-    public static int calculateToneDuration(Duration duration) {
-        int timeout = TONE_DFEAULT_TIMEOUT;
+    public static int calculateDurationInMilis(Duration duration) {
+        int timeout = 0;
         if (duration != null) {
             switch (duration.timeUnit) {
             case MINUTE:
diff --git a/src/com/android/stk/StkAppInstaller.java b/src/com/android/stk/StkAppInstaller.java
new file mode 100644
index 0000000..7c04a43
--- /dev/null
+++ b/src/com/android/stk/StkAppInstaller.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2007 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.stk;
+
+import com.android.internal.telephony.gsm.stk.StkLog;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+/**
+ * Application installer for SIM Toolkit.
+ * 
+ */
+abstract class StkAppInstaller {
+    private StkAppInstaller() {}
+
+    static void install(Context context) {
+        setAppState(context, true);
+    }
+
+    static void unInstall(Context context) {
+        setAppState(context, false);
+    }
+
+    private static void setAppState(Context context, boolean install) {
+        if (context == null) {
+            return;
+        }
+        PackageManager pm = context.getPackageManager();
+        if (pm == null) {
+            return;
+        }
+        // check that STK app package is known to the PackageManager
+        ComponentName cName = new ComponentName("com.android.stk",
+                "com.android.stk.StkLauncherActivity");
+        int state = install ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+                : PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
+
+        try {
+            pm.setComponentEnabledSetting(cName, state,
+                    PackageManager.DONT_KILL_APP);
+        } catch (Exception e) {
+            StkLog.d("StkAppInstaller", "Could not change STK app state");
+        }
+    }
+}
diff --git a/src/com/android/stk/StkAppService.java b/src/com/android/stk/StkAppService.java
new file mode 100644
index 0000000..cd6da78
--- /dev/null
+++ b/src/com/android/stk/StkAppService.java
@@ -0,0 +1,711 @@
+/*
+ * Copyright (C) 2007 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.stk;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.RemoteViews;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.android.internal.telephony.gsm.stk.AppInterface;
+import com.android.internal.telephony.gsm.stk.Menu;
+import com.android.internal.telephony.gsm.stk.Item;
+import com.android.internal.telephony.gsm.stk.ResultCode;
+import com.android.internal.telephony.gsm.stk.StkCmdMessage;
+import com.android.internal.telephony.gsm.stk.StkCmdMessage.BrowserSettings;
+import com.android.internal.telephony.gsm.stk.StkLog;
+import com.android.internal.telephony.gsm.stk.StkResponseMessage;
+import com.android.internal.telephony.gsm.stk.TextMessage;
+
+import java.util.LinkedList;
+
+/**
+ * SIM toolkit application level service. Interacts with Telephopny messages,
+ * application's launch and user input from STK UI elements.
+ * 
+ */
+public class StkAppService extends Service implements Runnable {
+
+    // members
+    private volatile Looper mServiceLooper;
+    private volatile ServiceHandler mServiceHandler;
+    private AppInterface mStkService;
+    private Context mContext = null;
+    private StkCmdMessage mMainCmd = null;
+    private StkCmdMessage mCurrentCmd = null;
+    private Menu mCurrentMenu = null;
+    private String lastSelectedItem = null;
+    private boolean mMenuIsVisibile = false;
+    private boolean responseNeeded = true;
+    private boolean mCmdInProgress = false;
+    private NotificationManager mNotificationManager = null;
+    private LinkedList<DelayedCmd> mCmdsQ = null;
+    private boolean launchBrowser = false;
+    private BrowserSettings mBrowserSettings = null;
+    static StkAppService sInstance = null;
+
+    // constants
+    static final String OPCODE = "op";
+    static final String CMD_MSG = "cmd message";
+    static final String RES_ID = "response id";
+    static final String MENU_SELECTION = "menu selection";
+    static final String INPUT = "input";
+    static final String HELP = "help";
+    static final String CONFIRMATION = "confirm";
+
+    // operations ids for different service functionality.
+    static final int OP_CMD = 1;
+    static final int OP_RESPONSE = 2;
+    static final int OP_LAUNCH_APP = 3;
+    static final int OP_END_SESSION = 4;
+    static final int OP_BOOT_COMPLETED = 5;
+    private static final int OP_DELAYED_MSG = 6;
+
+    // Response ids
+    static final int RES_ID_MENU_SELECTION = 11;
+    static final int RES_ID_INPUT = 12;
+    static final int RES_ID_CONFIRM = 13;
+    static final int RES_ID_DONE = 14;
+
+    static final int RES_ID_TIMEOUT = 20;
+    static final int RES_ID_BACKWARD = 21;
+    static final int RES_ID_END_SESSION = 22;
+    static final int RES_ID_EXIT = 23;
+
+    private static final String TAG = "StkAppService";
+
+    private static final String PACKAGE_NAME = "com.android.stk";
+    private static final String MENU_ACTIVITY_NAME = 
+                                        PACKAGE_NAME + ".StkMenuActivity";
+    private static final String INPUT_ACTIVITY_NAME = 
+                                        PACKAGE_NAME + ".StkInputActivity";
+    
+    // Notification id used to display Idle Mode text in NotificationManager.
+    private static final int STK_NOTIFICATION_ID = 333;
+    
+    // Inner class used for queuing telephony messages (proactive commands, 
+    // session end) while the service is busy processing a previous message.
+    private class DelayedCmd {
+        // members
+        int id;
+        StkCmdMessage msg;
+
+        DelayedCmd(int id, StkCmdMessage msg) {
+            this.id = id;
+            this.msg = msg;
+        }
+    }
+
+    @Override
+    public void onCreate() {
+        // Initialize members
+        mStkService = com.android.internal.telephony.gsm.stk.Service
+                .getInstance();
+        if (mStkService == null) {
+            StkLog.d(this, " Unable to get Service handle");
+            return;
+        }
+
+        mCmdsQ = new LinkedList<DelayedCmd>();
+        Thread serviceThread = new Thread(null, this, "Stk App Service");
+        serviceThread.start();
+        mContext = getBaseContext();
+        mNotificationManager = (NotificationManager) mContext
+                .getSystemService(Context.NOTIFICATION_SERVICE);
+        sInstance = this;
+    }
+
+    @Override
+    public void onStart(Intent intent, int startId) {
+        waitForLooper();
+
+        Bundle args = intent.getExtras();
+        if (args == null) {
+            return;
+        }
+
+        Message msg = mServiceHandler.obtainMessage();
+        msg.arg1 = args.getInt(OPCODE);
+        switch(msg.arg1) {
+        case OP_CMD:
+            msg.obj = args.getParcelable(CMD_MSG);
+            break;
+        case OP_RESPONSE:
+            msg.obj = args;
+            /* falls through */
+        case OP_LAUNCH_APP:
+        case OP_END_SESSION:
+        case OP_BOOT_COMPLETED:
+            break;
+        default:
+            return;
+        }
+        mServiceHandler.sendMessage(msg);
+    }
+
+    @Override
+    public void onDestroy() {
+        waitForLooper();
+        mServiceLooper.quit();
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    public void run() {
+        Looper.prepare();
+
+        mServiceLooper = Looper.myLooper();
+        mServiceHandler = new ServiceHandler();
+
+        Looper.loop();
+    }
+
+    /*
+     * Package api used by StkMenuActivity to indicate if its on the foreground.
+     */
+    void indicateMenuVisibility(boolean visibilty) {
+        mMenuIsVisibile = visibilty;
+    }
+
+    /*
+     * Package api used by StkMenuActivity to get its Menu parameter.
+     */
+    Menu getMenu() {
+        return mCurrentMenu;
+    }
+
+    /*
+     * Package api used by UI Activities and Dialogs to communicate directly
+     * with the service to deliver state information and parameters.
+     */
+    static StkAppService getInstance() {
+        return sInstance;
+    }
+
+    private void waitForLooper() {
+        while (mServiceHandler == null) {
+            synchronized (this) {
+                try {
+                    wait(100);
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+    }
+
+    private final class ServiceHandler extends Handler {
+        @Override
+        public void handleMessage(Message msg) {
+            int opcode = msg.arg1;
+
+            switch (opcode) {
+            case OP_LAUNCH_APP:
+                if (mMainCmd == null) {
+                    // nothing todo when no SET UP MENU command didn't arrive.
+                    return;
+                }
+                launchMenuActivity(null);
+                break;
+            case OP_CMD:
+                StkCmdMessage cmdMsg = (StkCmdMessage) msg.obj;
+                // There are two types of commands:
+                // 1. Interactive - user's response is required.
+                // 2. Informative - display a message, no interaction with the user.
+                //
+                // Informative commands can be handled immediately without any delay. 
+                // Interactive commands can't override each other. So if a command
+                // is already in progress, we need to queue the next command until
+                // the user has responded or a timeout expired.
+                if (!isCmdInteractive(cmdMsg)) {
+                    handleCmd(cmdMsg);
+                } else {
+                    if (!mCmdInProgress) {
+                        mCmdInProgress = true;
+                        handleCmd((StkCmdMessage) msg.obj);
+                    } else {
+                        mCmdsQ.addLast(new DelayedCmd(OP_CMD,
+                                (StkCmdMessage) msg.obj));
+                    }
+                }
+                break;
+            case OP_RESPONSE:
+                if (responseNeeded) {
+                    handleCmdResponse((Bundle) msg.obj);
+                }
+                // call delayed commands if needed.
+                if (mCmdsQ.size() != 0) {
+                    callDelayedMsg();
+                } else {
+                    mCmdInProgress = false;
+                }
+                // reset response needed state var to its original value.
+                responseNeeded = true;
+                break;
+            case OP_END_SESSION:
+                if (!mCmdInProgress) {
+                    mCmdInProgress = true;
+                    handleSessionEnd();
+                } else {
+                    mCmdsQ.addLast(new DelayedCmd(OP_END_SESSION, null));
+                }
+                break;
+            case OP_BOOT_COMPLETED:
+                StkLog.d(this, "OP_BOOT_COMPLETED");
+                if (mMainCmd == null) {
+                    StkAppInstaller.unInstall(mContext);
+                }
+                break;
+            case OP_DELAYED_MSG:
+                handleDelayedCmd();
+                break;
+            }
+        }
+    }
+
+    private boolean isCmdInteractive(StkCmdMessage cmd) {
+        switch (cmd.getCmdType()) {
+        case SEND_DTMF:
+        case SEND_SMS:
+        case SEND_SS:
+        case SEND_USSD:
+        case SET_UP_IDLE_MODE_TEXT:
+        case SET_UP_MENU:
+            return false;
+        }
+
+        return true;
+    }
+
+    private void handleDelayedCmd() {
+        if (mCmdsQ.size() != 0) {
+            DelayedCmd cmd = mCmdsQ.poll();
+            switch (cmd.id) {
+            case OP_CMD:
+                handleCmd(cmd.msg);
+                break;
+            case OP_END_SESSION:
+                handleSessionEnd();
+                break;
+            }
+        }
+    }
+
+    private void callDelayedMsg() {
+        Message msg = mServiceHandler.obtainMessage();
+        msg.arg1 = OP_DELAYED_MSG;
+        mServiceHandler.sendMessage(msg);
+    }
+
+    private void handleSessionEnd() {
+        mCurrentCmd = mMainCmd;
+        lastSelectedItem = null;
+        // In case of SET UP MENU command which removed the app, don't 
+        // update the current menu member.
+        if (mCurrentMenu != null && mMainCmd != null) {
+            mCurrentMenu = mMainCmd.getMenu();
+        }
+        if (mMenuIsVisibile) {
+            launchMenuActivity(null);
+        }
+        if (mCmdsQ.size() != 0) {
+            callDelayedMsg();
+        } else {
+            mCmdInProgress = false;
+        }
+        // In case a launch browser command was just confirmed, launch that url.
+        if (launchBrowser) {
+            launchBrowser = false;
+            launchBrowser(mBrowserSettings);
+        }
+    }
+
+    private void handleCmd(StkCmdMessage cmdMsg) {
+        if (cmdMsg == null) {
+            return;
+        }
+        // save local reference for state tracking.
+        mCurrentCmd = cmdMsg;
+        boolean waitForUsersResponse = true;
+
+        StkLog.d(this, cmdMsg.getCmdType().name());
+        switch (cmdMsg.getCmdType()) {
+        case DISPLAY_TEXT:
+            TextMessage msg = cmdMsg.geTextMessage();
+            responseNeeded = msg.responseNeeded;
+            if (lastSelectedItem != null) {
+                msg.title = lastSelectedItem;
+            } else if (mMainCmd != null){
+                msg.title = mMainCmd.getMenu().title;
+            } else {
+                // TODO: get the carrier name from the SIM
+                msg.title = "";
+            }
+            launchTextDialog();
+            break;
+        case SELECT_ITEM:
+            mCurrentMenu = cmdMsg.getMenu();
+            launchMenuActivity(cmdMsg.getMenu());
+            break;
+        case SET_UP_MENU:
+            mMainCmd = mCurrentCmd;
+            mCurrentMenu = cmdMsg.getMenu();
+            if (removeMenu()) {
+                StkLog.d(this, "Uninstall App");
+                mCurrentMenu = null;
+                StkAppInstaller.unInstall(mContext);
+            } else {
+                StkLog.d(this, "Install App");
+                StkAppInstaller.install(mContext);
+            }
+            if (mMenuIsVisibile) {
+                launchMenuActivity(null);
+            }
+            break;
+        case GET_INPUT:
+        case GET_INKEY:
+            launchInputActivity();
+            break;
+        case SET_UP_IDLE_MODE_TEXT:
+            waitForUsersResponse = false;
+            launchIdleText();
+            break;
+        case SEND_DTMF:
+        case SEND_SMS:
+        case SEND_SS:
+        case SEND_USSD:
+            waitForUsersResponse = false;
+            launchEventMessage();
+            break;
+        case LAUNCH_BROWSER:
+            launchConfirmationDialog(mCurrentCmd.geTextMessage());
+            break;
+        case SET_UP_CALL:
+            launchConfirmationDialog(mCurrentCmd.getCallSettings().confirmMsg);
+            break;
+        case PLAY_TONE:
+            launchToneDialog();
+            break;
+        }
+
+        if (!waitForUsersResponse) {
+            if (mCmdsQ.size() != 0) {
+                callDelayedMsg();
+            } else {
+                mCmdInProgress = false;
+            }
+        }
+    }
+
+    private void handleCmdResponse(Bundle args) {
+        if (mCurrentCmd == null) {
+            return;
+        }
+        StkResponseMessage resMsg = new StkResponseMessage(mCurrentCmd);
+
+        // set result code
+        boolean helpRequired = args.getBoolean(HELP, false);
+
+        switch(args.getInt(RES_ID)) {
+        case RES_ID_MENU_SELECTION:
+            StkLog.d(this, "RES_ID_MENU_SELECTION");
+            int menuSelection = args.getInt(MENU_SELECTION);
+            switch(mCurrentCmd.getCmdType()) {
+            case SET_UP_MENU:
+            case SELECT_ITEM:
+                lastSelectedItem = getItemName(menuSelection);
+                if (helpRequired) {
+                    resMsg.setResultCode(ResultCode.HELP_INFO_REQUIRED);
+                } else {
+                    resMsg.setResultCode(ResultCode.OK);
+                }
+                resMsg.setMenuSelection(menuSelection);
+                break;
+            }
+            break;
+        case RES_ID_INPUT:
+            StkLog.d(this, "RES_ID_INPUT");
+            String input = args.getString(INPUT);
+            if (mCurrentCmd.geInput().yesNo) {
+                boolean yesNoSelection = input
+                        .equals(StkInputActivity.YES_STR_RESPONSE);
+                resMsg.setYesNo(yesNoSelection);
+            } else {
+                if (helpRequired) {
+                    resMsg.setResultCode(ResultCode.HELP_INFO_REQUIRED);
+                } else {
+                    resMsg.setResultCode(ResultCode.OK);
+                    resMsg.setInput(input);
+                }
+            }
+            break;
+        case RES_ID_CONFIRM:
+            StkLog.d(this, "RES_ID_CONFIRM");
+            boolean confirmed = args.getBoolean(CONFIRMATION);
+            switch (mCurrentCmd.getCmdType()) {
+            case DISPLAY_TEXT:
+                resMsg.setResultCode(confirmed ? ResultCode.OK
+                        : ResultCode.UICC_SESSION_TERM_BY_USER);
+                break;
+            case LAUNCH_BROWSER:
+                resMsg.setResultCode(confirmed ? ResultCode.OK
+                        : ResultCode.UICC_SESSION_TERM_BY_USER);
+                if (confirmed) {
+                    launchBrowser = true;
+                    mBrowserSettings = mCurrentCmd.getBrowserSettings();
+                }
+                break;
+            case SET_UP_CALL:
+                resMsg.setResultCode(ResultCode.OK);
+                resMsg.setConfirmation(confirmed);
+                if (confirmed) {
+                    launchCallMsg();
+                }
+                break;
+            }
+            break;
+        case RES_ID_DONE:
+            resMsg.setResultCode(ResultCode.OK);
+            break;
+        case RES_ID_BACKWARD:
+            StkLog.d(this, "RES_ID_BACKWARD");
+            resMsg.setResultCode(ResultCode.BACKWARD_MOVE_BY_USER);
+            break;
+        case RES_ID_END_SESSION:
+            StkLog.d(this, "RES_ID_END_SESSION");
+            resMsg.setResultCode(ResultCode.UICC_SESSION_TERM_BY_USER);
+            break;
+        case RES_ID_TIMEOUT:
+            StkLog.d(this, "RES_ID_TIMEOUT");
+            resMsg.setResultCode(ResultCode.NO_RESPONSE_FROM_USER);
+            break;
+        default:
+            StkLog.d(this, "Unknown result id");
+            return;
+        }
+        mStkService.onCmdResponse(resMsg);
+    }
+
+    private void launchMenuActivity(Menu menu) {
+        Intent newIntent = new Intent(Intent.ACTION_VIEW);
+        newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        newIntent.setClassName(PACKAGE_NAME, MENU_ACTIVITY_NAME);
+        if (menu == null) {
+            newIntent.putExtra("STATE", StkMenuActivity.STATE_MAIN);
+        } else {
+            newIntent.putExtra("STATE", StkMenuActivity.STATE_SECONDARY);
+        }
+        mContext.startActivity(newIntent);
+    }
+
+    private void launchInputActivity() {
+        Intent newIntent = new Intent(Intent.ACTION_VIEW);
+        newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        newIntent.setClassName(PACKAGE_NAME, INPUT_ACTIVITY_NAME);
+        newIntent.putExtra("INPUT", mCurrentCmd.geInput());
+        mContext.startActivity(newIntent);
+    }
+
+    private void launchTextDialog() {
+        Intent newIntent = new Intent(this, StkDialogActivity.class);
+        newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_MULTIPLE_TASK
+                | Intent.FLAG_ACTIVITY_NO_HISTORY
+                | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+        newIntent.putExtra("TEXT", mCurrentCmd.geTextMessage());
+        startActivity(newIntent);
+    }
+
+    private void launchEventMessage() {
+        TextMessage msg = mCurrentCmd.geTextMessage();
+        if (msg == null) {
+            return;
+        }
+        Toast toast = new Toast(mContext.getApplicationContext());
+        LayoutInflater inflate = (LayoutInflater) mContext
+                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        View v = inflate.inflate(R.layout.stk_event_msg, null);
+        TextView tv = (TextView) v
+                .findViewById(com.android.internal.R.id.message);
+        ImageView iv = (ImageView) v
+                .findViewById(com.android.internal.R.id.icon);
+        if (msg.icon != null) {
+            iv.setImageBitmap(msg.icon);
+        } else {
+            iv.setVisibility(View.GONE);
+        }
+        if (!msg.iconSelfExplanatory) {
+            tv.setText(msg.text);
+        }
+
+        toast.setView(v);
+        toast.setDuration(Toast.LENGTH_LONG);
+        toast.setGravity(Gravity.BOTTOM, 0, 0);
+        toast.show();
+    }
+
+    private void launchConfirmationDialog(TextMessage msg) {
+        msg.title = lastSelectedItem;
+        Intent newIntent = new Intent(this, StkDialogActivity.class);
+        newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_NO_HISTORY
+                | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+        newIntent.putExtra("TEXT", msg);
+        startActivity(newIntent);
+    }
+
+    private void launchBrowser(BrowserSettings settings) {
+        if (settings == null) {
+            return;
+        }
+        // Set browser launch mode
+        Intent intent = new Intent();
+        intent.setClassName("com.android.browser",
+                "com.android.browser.BrowserActivity");
+
+        // to launch home page, make sure that data Uri is null. 
+        Uri data = null;
+        if (settings.url != null) {
+            data = Uri.parse(settings.url);
+        }
+        intent.setData(data);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        switch (settings.mode) {
+        case USE_EXISTING_BROWSER:
+            intent.setAction(Intent.ACTION_VIEW);
+            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+            break;
+        case LAUNCH_NEW_BROWSER:
+            intent.setAction(Intent.ACTION_VIEW);
+            intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+            break;
+        case LAUNCH_IF_NOT_ALREADY_LAUNCHED:
+            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+            break;
+        }
+        // start browser activity
+        startActivity(intent);
+        // a small delay, let the browser start, before processing the next command.
+        // this is good for scenarios where a related DISPLAY TEXT command is 
+        // followed immediately.
+        try {
+            Thread.sleep(10000);
+        } catch (InterruptedException e) {}
+    }
+
+    private void launchCallMsg() {
+        TextMessage msg = mCurrentCmd.getCallSettings().callMsg;
+        if (msg.text == null || msg.text.length() == 0) {
+            return;
+        }
+        msg.title = lastSelectedItem;
+
+        Toast toast = Toast.makeText(mContext.getApplicationContext(), msg.text,
+                Toast.LENGTH_LONG);
+        toast.setGravity(Gravity.BOTTOM, 0, 0);
+        toast.show();
+    }
+
+    private void launchIdleText() {
+        TextMessage msg = mCurrentCmd.geTextMessage();
+        if (msg.text == null) {
+            mNotificationManager.cancel(STK_NOTIFICATION_ID);
+        } else {
+            Notification notification = new Notification();
+            RemoteViews contentView = new RemoteViews(
+                    PACKAGE_NAME,
+                    com.android.internal.R.layout.status_bar_latest_event_content);
+
+            notification.flags |= Notification.FLAG_NO_CLEAR;
+            notification.icon = com.android.internal.R.drawable.stat_notify_sim_toolkit;
+            // Set text and icon for the status bar and notification body.
+            if (!msg.iconSelfExplanatory) {
+                notification.tickerText = msg.text;
+                contentView.setTextViewText(com.android.internal.R.id.text,
+                        msg.text);
+            }
+            if (msg.icon != null) {
+                contentView.setImageViewBitmap(com.android.internal.R.id.icon,
+                        msg.icon);
+            } else {
+                contentView
+                        .setImageViewResource(
+                                com.android.internal.R.id.icon,
+                                com.android.internal.R.drawable.stat_notify_sim_toolkit);
+            }
+            notification.contentView = contentView;
+            notification.contentIntent = PendingIntent.getService(mContext, 0,
+                    new Intent(mContext, StkAppService.class), 0);
+
+            mNotificationManager.notify(STK_NOTIFICATION_ID, notification);
+        }
+    }
+
+    private void launchToneDialog() {
+        Intent newIntent = new Intent(this, ToneDialog.class);
+        newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+                | Intent.FLAG_ACTIVITY_NO_HISTORY
+                | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+        newIntent.putExtra("TEXT", mCurrentCmd.geTextMessage());
+        newIntent.putExtra("TONE", mCurrentCmd.getToneSettings());
+        startActivity(newIntent);
+    }
+
+    private String getItemName(int itemId) {
+        Menu menu = mCurrentCmd.getMenu();
+        if (menu == null) {
+            return null;
+        }
+        for (Item item : menu.items) {
+            if (item.id == itemId) {
+                return item.text;
+            }
+        }
+        return null;
+    }
+
+    private boolean removeMenu() {
+        try {
+            if (mCurrentMenu.items.size() == 1 && 
+                mCurrentMenu.items.get(0) == null) {
+                return true;
+            }
+        } catch (NullPointerException e) {
+            StkLog.d(this, "Unable to get Menu's items size");
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/src/com/android/stk/StkCmdReceiver.java b/src/com/android/stk/StkCmdReceiver.java
new file mode 100644
index 0000000..6f05de6
--- /dev/null
+++ b/src/com/android/stk/StkCmdReceiver.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2007 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.stk;
+
+import com.android.internal.telephony.gsm.stk.AppInterface;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+
+/**
+ * Receiver class to get STK intents, broadcasted by telephony layer.
+ * 
+ */
+public class StkCmdReceiver extends BroadcastReceiver {
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        String action = intent.getAction();
+
+        if (action.equals(AppInterface.STK_CMD_ACTION)) {
+            handleCommandMessage(context, intent);
+        } else if (action.equals(AppInterface.STK_SESSION_END_ACTION)) {
+            handleSessionEnd(context, intent);
+        }
+    }
+
+    private void handleCommandMessage(Context context, Intent intent) {
+        Bundle args = new Bundle();
+        args.putInt(StkAppService.OPCODE, StkAppService.OP_CMD);
+        args.putParcelable(StkAppService.CMD_MSG, intent
+                .getParcelableExtra("STK CMD"));
+        context.startService(new Intent(context, StkAppService.class)
+                .putExtras(args));
+    }
+
+    private void handleSessionEnd(Context context, Intent intent) {
+        Bundle args = new Bundle();
+        args.putInt(StkAppService.OPCODE, StkAppService.OP_END_SESSION);
+        context.startService(new Intent(context, StkAppService.class)
+                .putExtras(args));
+    }
+}
diff --git a/src/com/android/stk/StkDialogActivity.java b/src/com/android/stk/StkDialogActivity.java
new file mode 100644
index 0000000..f20b41d
--- /dev/null
+++ b/src/com/android/stk/StkDialogActivity.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (C) 2007 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.stk;
+
+import com.android.internal.telephony.gsm.stk.TextMessage;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.graphics.drawable.BitmapDrawable;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.TextView;
+
+/**
+ * AlretDialog used for DISPLAY TEXT commands.
+ * 
+ */
+public class StkDialogActivity extends Activity implements View.OnClickListener {
+    // members
+    TextMessage mTextMsg;
+
+    Handler mTimeoutHandler = new Handler() {
+        public void handleMessage(Message msg) {
+            switch(msg.what) {
+            case MSG_ID_TIMEOUT:
+                sendResponse(StkAppService.RES_ID_TIMEOUT);
+                finish();
+                break;
+            }
+        }
+    };
+
+    // constants
+    static final String TAG = "STK Dialog";
+
+    //keys) for saving the state of the dialog in the icicle
+    private static final String TEXT = "text";
+
+    // message id for time out 
+    private static final int MSG_ID_TIMEOUT = 1;
+
+    // buttons id
+    public static final int OK_BUTTON = R.id.button_ok;
+    public static final int CANCEL_BUTTON = R.id.button_cancel;
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        initFromIntent(getIntent());
+        if (mTextMsg == null) {
+            finish();
+            return;
+        }
+
+        requestWindowFeature(Window.FEATURE_LEFT_ICON);
+        Window window = getWindow();
+
+        setContentView(R.layout.stk_msg_dialog);
+        TextView mMessageView = (TextView) window
+                .findViewById(R.id.dialog_message);
+
+        Button okButton = (Button) findViewById(R.id.button_ok);
+        Button cancelButton = (Button) findViewById(R.id.button_cancel);
+
+        okButton.setOnClickListener(this);
+        cancelButton.setOnClickListener(this);
+
+        setTitle(mTextMsg.title);
+        if (!(mTextMsg.iconSelfExplanatory && mTextMsg.icon != null)) {
+            mMessageView.setText(mTextMsg.text); 
+        }
+
+        if (mTextMsg.icon == null) {
+            window.setFeatureDrawableResource(Window.FEATURE_LEFT_ICON,
+                    com.android.internal.R.drawable.stat_notify_sim_toolkit);
+        } else {
+            window.setFeatureDrawable(Window.FEATURE_LEFT_ICON,
+                    new BitmapDrawable(mTextMsg.icon));
+        }
+    }
+
+    public void onClick(View v) {
+        String input = null;
+
+        switch (v.getId()) {
+        case OK_BUTTON:
+            sendResponse(StkAppService.RES_ID_CONFIRM, true);
+            finish();
+            break;
+        case CANCEL_BUTTON:
+            sendResponse(StkAppService.RES_ID_CONFIRM, false);
+            finish();
+            break;
+        }
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        switch (keyCode) {
+        case KeyEvent.KEYCODE_BACK:
+            sendResponse(StkAppService.RES_ID_BACKWARD);
+            finish();
+            break;
+        }
+        return false;
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        startTimeOut();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+
+        cancelTimeOut();
+    }
+
+    @Override
+    public void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+
+        outState.putParcelable(TEXT, mTextMsg);
+    }
+
+    @Override
+    public void onRestoreInstanceState(Bundle savedInstanceState) {
+        super.onRestoreInstanceState(savedInstanceState);
+        
+        mTextMsg = savedInstanceState.getParcelable(TEXT);
+    }
+
+    private void sendResponse(int resId, boolean confirmed) {
+        Bundle args = new Bundle();
+        args.putInt(StkAppService.OPCODE, StkAppService.OP_RESPONSE);
+        args.putInt(StkAppService.RES_ID, resId);
+        args.putBoolean(StkAppService.CONFIRMATION, confirmed);
+        startService(new Intent(this, StkAppService.class).putExtras(args));
+    }
+
+    private void sendResponse(int resId) {
+        sendResponse(resId, true);
+    }
+
+    private void initFromIntent(Intent intent) {
+
+        if (intent != null) {
+            mTextMsg = intent.getParcelableExtra("TEXT");
+        } else {
+            finish();
+        }
+    }
+
+    private void cancelTimeOut() {
+        mTimeoutHandler.removeMessages(MSG_ID_TIMEOUT);
+    }
+
+    private void startTimeOut() {
+        // Reset timeout.
+        cancelTimeOut();
+        int dialogDuration = StkApp.calculateDurationInMilis(mTextMsg.duration);
+        if (dialogDuration == 0) {
+            dialogDuration = StkApp.UI_TIMEOUT;
+        }
+        mTimeoutHandler.sendMessageDelayed(mTimeoutHandler
+                .obtainMessage(MSG_ID_TIMEOUT), dialogDuration);
+    }
+}
diff --git a/src/com/android/stk/StkDigitsKeyListener.java b/src/com/android/stk/StkDigitsKeyListener.java
index 475b932..eb3d53a 100644
--- a/src/com/android/stk/StkDigitsKeyListener.java
+++ b/src/com/android/stk/StkDigitsKeyListener.java
@@ -18,6 +18,7 @@
 
 import android.text.method.NumberKeyListener;
 import android.view.KeyEvent;
+import android.view.inputmethod.EditorInfo;
 
 /**
  * For entering dates in a text field.
@@ -28,6 +29,10 @@
         return CHARACTERS;
     }
 
+    public int getInputType() {
+        return EditorInfo.TYPE_CLASS_PHONE;
+    }
+    
     public static StkDigitsKeyListener getInstance() {
         if (sInstance != null) {
             return sInstance;
diff --git a/src/com/android/stk/StkInputActivity.java b/src/com/android/stk/StkInputActivity.java
index d629ef3..8a91563 100644
--- a/src/com/android/stk/StkInputActivity.java
+++ b/src/com/android/stk/StkInputActivity.java
@@ -1,12 +1,12 @@
 /*
  * Copyright (C) 2007 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
- *
+ * 
+ * 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.
@@ -17,26 +17,29 @@
 package com.android.stk;
 
 import android.app.Activity;
+import android.content.Context;
 import android.content.Intent;
+import android.graphics.drawable.BitmapDrawable;
 import android.os.Bundle;
 import android.os.Handler;
-import com.android.internal.telephony.gsm.stk.AppInterface;
-import com.android.internal.telephony.gsm.stk.FontSize;
-import com.android.internal.telephony.gsm.stk.Service;
-import com.android.internal.telephony.gsm.stk.TextAttribute;
-import android.view.KeyEvent;
-import android.view.Menu;
-import android.view.MenuItem;
-import android.view.MotionEvent;
-import android.view.View;
-import android.widget.Button;
-import android.widget.TextView;
-import android.widget.EditText;
+import android.os.Message;
 import android.text.Editable;
 import android.text.InputFilter;
 import android.text.TextWatcher;
-import android.graphics.Typeface;
 import android.text.method.PasswordTransformationMethod;
+import android.view.KeyEvent;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.EditText;
+import android.widget.TextView.BufferType;
+
+import com.android.internal.telephony.gsm.stk.AppInterface;
+import com.android.internal.telephony.gsm.stk.FontSize;
+import com.android.internal.telephony.gsm.stk.Input;
+import com.android.internal.telephony.gsm.stk.Service;
 
 /**
  * Display a request for a text input a long with a text edit form.
@@ -46,40 +49,45 @@
 
     // Members
     private int mState;
-    private int mMinTextLength = NO_MIN_LIMIT;
+    private Context mContext;
     private EditText mTextIn = null;
     private TextView mPromptView = null;
     private View mYesNoLayout = null;
     private View mNormalLayout = null;
-    private WatchDog mTimeoutWatchDog = null;
-    private boolean mHelpAvailable = false;
+    private Input mStkInput = null;
 
     // Constants
-    private static final String TAG = "STK INPUT ACTIVITY";
+    private static final String TAG = "STK Input";
 
-    private static final int IN_STATE_TEXT = 1;
-    private static final int IN_STATE_KEY = 2;
+    private static final int STATE_TEXT = 1;
+    private static final int STATE_YES_NO = 2;
 
-    private static final int NO_MIN_LIMIT = 0;
-    private static final int INKEY_MAX_LIMIT = 1;
+    static final String YES_STR_RESPONSE = "YES";
+    static final String NO_STR_RESPONSE = "NO";
 
-    private static final String INKEY_MAX_LIMIT_STR = "1";
-
-    // Font size factor values. 
+    // Font size factor values.
     static final float NORMAL_FONT_FACTOR = 1;
     static final float LARGE_FONT_FACTOR = 2;
     static final float SMALL_FONT_FACTOR = (1 / 2);
 
-    private class Terminate implements Runnable {
-        public void run() {
-            setResult(StkApp.RESULT_TIMEDOUT);
-            finish();
+    // message id for time out 
+    private static final int MSG_ID_TIMEOUT = 1;
+
+    Handler mTimeoutHandler = new Handler() {
+        public void handleMessage(Message msg) {
+            switch(msg.what) {
+            case MSG_ID_TIMEOUT:
+                //mAcceptUsersInput = false;
+                sendResponse(StkAppService.RES_ID_TIMEOUT);
+                finish();
+                break;
+            }
         }
-    }
+    };
 
     // Click listener to handle buttons press..
     public void onClick(View v) {
-        Intent data = new Intent();
+        String input = null;
 
         switch (v.getId()) {
         case R.id.button_ok:
@@ -87,30 +95,18 @@
             if (!verfiyTypedText()) {
                 return;
             }
-            switch (mState) {
-            case IN_STATE_TEXT:
-                // return input text to the calling activity
-                String input = mTextIn.getText().toString();
-                data.putExtra(Util.INPUT_TYPE_TEXT, input);
-                break;
-            case IN_STATE_KEY:
-                // return input key to the calling activity
-                Character key = new Character(mTextIn.getText().toString()
-                        .charAt(0));
-                data.putExtra(Util.INPUT_TYPE_KEY, key.charValue());
-                break;
-            }
+            input = mTextIn.getText().toString();
             break;
         // Yes/No layout buttons.
         case R.id.button_yes:
-            onYesNoButtonClick(true);
+            input = YES_STR_RESPONSE;
             break;
         case R.id.button_no:
-            onYesNoButtonClick(true);
+            input = NO_STR_RESPONSE;
             break;
         }
 
-        setResult(RESULT_OK, data);
+        sendResponse(StkAppService.RES_ID_INPUT, input, false);
         finish();
     }
 
@@ -119,6 +115,7 @@
         super.onCreate(icicle);
 
         // Set the layout for this activity.
+        requestWindowFeature(Window.FEATURE_LEFT_ICON);
         setContentView(R.layout.stk_input);
 
         // Initialize members
@@ -139,18 +136,19 @@
 
         // Get the calling intent type: text/key, and setup the 
         // display parameters.
-        Bundle extras = getIntent().getExtras();
-        if (extras != null) {
-            // set input state
-            String str = extras.getString(Util.INPUT_TYPE);
-            mState = (str.equals(Util.INPUT_TYPE_TEXT)) ? IN_STATE_TEXT
-                    : IN_STATE_KEY;
-            configInputDisplay(extras);
+        Intent intent = getIntent();
+        if (intent != null) {
+            mStkInput = intent.getParcelableExtra("INPUT");
+            if (mStkInput == null) {
+                finish();
+            } else {
+                mState = mStkInput.yesNo ? STATE_YES_NO : STATE_TEXT;
+                configInputDisplay();
+            }
+        } else {
+            finish();
         }
-        // Create a watch dog to terminate the activity if no input is received
-        // after one minute.
-        mTimeoutWatchDog = new WatchDog(null, new Handler(), new Terminate(),
-                StkApp.UI_TIMEOUT);
+        mContext = getBaseContext();
     }
 
     @Override
@@ -161,49 +159,51 @@
     }
 
     @Override
-    public void onDestroy() {
-        super.onDestroy();
-        mTimeoutWatchDog.cancel();
+    public void onResume() {
+        super.onResume();
+
+        startTimeOut();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+
+        cancelTimeOut();
     }
 
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
-        AppInterface stkService = Service.getInstance();
-
-        // Reset timeout.
-        mTimeoutWatchDog.reset();
-
         switch (keyCode) {
         case KeyEvent.KEYCODE_BACK:
-            setResult(StkApp.RESULT_BACKWARD);
-            finish();
-            break;
-        case KeyEvent.KEYCODE_HOME:
-            setResult(StkApp.RESULT_END_SESSION);
+            sendResponse(StkAppService.RES_ID_BACKWARD, null, false);
             finish();
             break;
         }
         return super.onKeyDown(keyCode, event);
     }
 
-    @Override
-    public boolean onTrackballEvent(MotionEvent event) {
-        // Reset timeout.
-        mTimeoutWatchDog.reset();
-        return super.onTrackballEvent(event);
+    private void sendResponse(int resId) {
+        sendResponse(resId, null, false);
     }
 
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        // Reset timeout.
-        mTimeoutWatchDog.reset();
-        return super.onTouchEvent(event);
+    private void sendResponse(int resId, String input, boolean help) {
+        Bundle args = new Bundle();
+        args.putInt(StkAppService.OPCODE, StkAppService.OP_RESPONSE);
+        args.putInt(StkAppService.RES_ID, resId);
+        if (input != null) {
+            args.putString(StkAppService.INPUT, input);
+        }
+        args.putBoolean(StkAppService.HELP, help);
+        mContext.startService(new Intent(mContext, StkAppService.class)
+                .putExtras(args));
     }
 
     @Override
     public boolean onCreateOptionsMenu(android.view.Menu menu) {
         super.onCreateOptionsMenu(menu);
-        menu.add(0, StkApp.MENU_ID_MAIN, 1, R.string.sim_main_menu);
+        menu.add(android.view.Menu.NONE, StkApp.MENU_ID_END_SESSION, 1,
+                R.string.menu_end_session);
         menu.add(0, StkApp.MENU_ID_HELP, 2, R.string.help);
 
         return true;
@@ -212,8 +212,8 @@
     @Override
     public boolean onPrepareOptionsMenu(android.view.Menu menu) {
         super.onPrepareOptionsMenu(menu);
-        menu.findItem(StkApp.MENU_ID_MAIN).setVisible(true);
-        menu.findItem(StkApp.MENU_ID_HELP).setVisible(mHelpAvailable);
+        menu.findItem(StkApp.MENU_ID_END_SESSION).setVisible(true);
+        menu.findItem(StkApp.MENU_ID_HELP).setVisible(mStkInput.helpAvailable);
 
         return true;
     }
@@ -223,12 +223,12 @@
         AppInterface stkService = Service.getInstance();
 
         switch (item.getItemId()) {
-        case StkApp.MENU_ID_MAIN:
-            setResult(StkApp.RESULT_END_SESSION);
+        case StkApp.MENU_ID_END_SESSION:
+            sendResponse(StkAppService.RES_ID_END_SESSION);
             finish();
             return true;
         case StkApp.MENU_ID_HELP:
-            setResult(StkApp.RESULT_HELP);
+            sendResponse(StkAppService.RES_ID_INPUT, "", true);
             finish();
             return true;
         }
@@ -241,118 +241,84 @@
 
     public void onTextChanged(CharSequence s, int start, int before, int count) {
         // Reset timeout.
-        mTimeoutWatchDog.reset();
+        startTimeOut();
     }
 
     public void afterTextChanged(Editable s) {
     }
 
-    private void onYesNoButtonClick(boolean yesNo) {
-        Intent data = new Intent();
-        data.putExtra(Util.INPUT_TYPE_KEY, yesNo);
-
-        // End the activity.
-        setResult(StkApp.RESULT_OK, data);
-        finish();
-    }
-
     private boolean verfiyTypedText() {
         // If not enough input was typed in stay on the edit screen.
-        if (mTextIn.getText().length() < mMinTextLength) return false;
+        if (mTextIn.getText().length() < mStkInput.minLen) {
+            return false;
+        }
 
         return true;
     }
 
-    private void configInputDisplay(Bundle extras) {
+    private void cancelTimeOut() {
+        mTimeoutHandler.removeMessages(MSG_ID_TIMEOUT);
+    }
+
+    private void startTimeOut() {
+        cancelTimeOut();
+        mTimeoutHandler.sendMessageDelayed(mTimeoutHandler
+                .obtainMessage(MSG_ID_TIMEOUT), StkApp.UI_TIMEOUT);
+    }
+
+    private void configInputDisplay() {
         TextView numOfCharsView = (TextView) findViewById(R.id.num_of_chars);
         TextView inTypeView = (TextView) findViewById(R.id.input_type);
-        Bundle bundle = extras.getBundle(Util.INPUT_TEXT_ATTRS);
-        Bundle glblAttrs = extras.getBundle(Util.INPUT_GLBL_ATTRS);
-        TextAttribute textAttrs = null;
+
         int inTypeId = R.string.alphabet;
 
         // set the prompt.
-        String prompt = extras.getString(Util.INPUT_PROMPT);
-        if (prompt != null) {
-            mPromptView.setText(prompt);
-        }
-
-        // Unpack text attributes from the bundle.
-        if (bundle != null) textAttrs = Util.unPackTextAttr(bundle);
+        mPromptView.setText(mStkInput.text);
 
         // Set input type (alphabet/digit) info close to the InText form. 
-        if (glblAttrs.getBoolean(Util.INPUT_ATTR_DIGITS)) {
+        if (mStkInput.digitOnly) {
             mTextIn.setKeyListener(StkDigitsKeyListener.getInstance());
             inTypeId = R.string.digits;
-        } 
+        }
         inTypeView.setText(inTypeId);
 
-        if (glblAttrs.getBoolean(Util.INPUT_ATTR_HELP)) {
-            mHelpAvailable = true;
+        if (mStkInput.icon != null) {
+            setFeatureDrawable(Window.FEATURE_LEFT_ICON, new BitmapDrawable(
+                    mStkInput.icon));
         }
 
         // Handle specific global and text attributes.
         switch (mState) {
-        case IN_STATE_TEXT:
-            // Handle text attributes setup for get input.
-            if (textAttrs != null) {
-                // Set font size.
-                float size = mPromptView.getTextSize() * 
-                                getFontSizeFactor(textAttrs.size);
-
-                mPromptView.setTextSize(size);
-
-                // Set prompt to bold.
-                if (textAttrs.bold) {
-                    mPromptView.setTypeface(Typeface.DEFAULT_BOLD);
-                }
-                // Set prompt to italic.
-                if (textAttrs.italic) {
-                    mPromptView.setTypeface(Typeface.create(Typeface.DEFAULT,
-                            Typeface.ITALIC));
-                }
-                // Set text color.
-                mPromptView.setTextColor(textAttrs.color.ordinal());
-            }
-            // Handle global attributes setup.
-            mMinTextLength = glblAttrs.getInt(Util.INPUT_ATTR_MINLEN);
-
-            // Set the maximum number of characters according to the maximum 
-            // input size.
-            int maxTextLength = glblAttrs.getInt(Util.INPUT_ATTR_MAXLEN);
+        case STATE_TEXT:        
+            int maxLen = mStkInput.maxLen;
+            int minLen = mStkInput.minLen;
             mTextIn.setFilters(new InputFilter[] {new InputFilter.LengthFilter(
-                    maxTextLength)});
+                    maxLen)});
  
             // Set number of chars info.
-            String lengthLimit = String.valueOf(mMinTextLength);
-            if (maxTextLength != mMinTextLength) {
-                lengthLimit = mMinTextLength + " - " + maxTextLength;
+            String lengthLimit = String.valueOf(minLen);
+            if (maxLen != minLen) {
+                lengthLimit = minLen + " - " + maxLen;
             }
             numOfCharsView.setText(lengthLimit);
 
-            if (!glblAttrs.getBoolean(Util.INPUT_ATTR_ECHO)) {
+            if (!mStkInput.echo) {
                 mTextIn.setTransformationMethod(PasswordTransformationMethod
                         .getInstance());
             }
             // Set default text if present.
-            String defaultText = extras.getString(Util.INPUT_DEFAULT);
-            if (defaultText != null) {
-                mTextIn.setText(defaultText);
+            if (mStkInput.defaultText != null) {
+                mTextIn.setText(mStkInput.defaultText);
+            } else {
+                // make sure the text is cleared
+                mTextIn.setText("", BufferType.EDITABLE);
             }
 
             break;
-        case IN_STATE_KEY:
+        case STATE_YES_NO:
             // Set display mode - normal / yes-no layout
-            if (glblAttrs.getBoolean(Util.INPUT_ATTR_YES_NO)) {
-                mYesNoLayout.setVisibility(View.VISIBLE);
-                mNormalLayout.setVisibility(View.GONE);
-                break;
-            }
-            // In case of a input key, limit the text in to a single char.
-            mTextIn.setFilters(new InputFilter[] {new InputFilter.LengthFilter(
-                    INKEY_MAX_LIMIT)});
-            mMinTextLength = INKEY_MAX_LIMIT;
-            numOfCharsView.setText(INKEY_MAX_LIMIT_STR);
+            mYesNoLayout.setVisibility(View.VISIBLE);
+            mNormalLayout.setVisibility(View.GONE);
             break;
         }
     }
diff --git a/src/com/android/stk/StkLauncherActivity.java b/src/com/android/stk/StkLauncherActivity.java
new file mode 100644
index 0000000..df9fa24
--- /dev/null
+++ b/src/com/android/stk/StkLauncherActivity.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2007 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.stk;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+/**
+ * Launcher class. Serve as the app's MAIN activity, send an intent to the 
+ * StkAppService and finish.
+ * 
+ */
+public class StkLauncherActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        Bundle args = new Bundle();
+        args.putInt(StkAppService.OPCODE, StkAppService.OP_LAUNCH_APP);
+        startService(new Intent(this, StkAppService.class).putExtras(args));
+
+        finish();
+    }
+}
diff --git a/src/com/android/stk/StkMenuActivity.java b/src/com/android/stk/StkMenuActivity.java
new file mode 100644
index 0000000..16c8fe4
--- /dev/null
+++ b/src/com/android/stk/StkMenuActivity.java
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2007 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.stk;
+
+import android.app.ListActivity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.Window;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import com.android.internal.telephony.gsm.stk.Item;
+import com.android.internal.telephony.gsm.stk.Menu;
+
+/**
+ * ListActivity used for displaying STK menus. These can be SET UP MENU and 
+ * SELECT ITEM menus. This activity is started multiple times with different 
+ * menu content.
+ *
+ */
+public class StkMenuActivity extends ListActivity {
+    private Context mContext;
+    private Menu mStkMenu = null;
+    private int mState = STATE_MAIN;
+    private boolean mAcceptUsersInput = true;
+
+    private TextView mTitleTextView = null;
+    private ImageView mTitleIconView = null;
+    private ProgressBar mProgressView = null;
+
+    StkAppService appService = StkAppService.getInstance();
+
+    // Constants
+    private static final String TAG = "STK Menu";
+
+    // Internal state values
+    static final int STATE_MAIN = 1;
+    static final int STATE_SECONDARY = 2;
+
+    // message id for time out 
+    private static final int MSG_ID_TIMEOUT = 1;
+
+    Handler mTimeoutHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch(msg.what) {
+            case MSG_ID_TIMEOUT:
+                mAcceptUsersInput = false;
+                sendResponse(StkAppService.RES_ID_TIMEOUT);
+                break;
+            }
+        }
+    };
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        Log.d(TAG, "onCreate");
+        // Remove the default title, customized one is used.
+        requestWindowFeature(Window.FEATURE_NO_TITLE);  
+        // Set the layout for this activity.
+        setContentView(R.layout.stk_menu_list);
+
+        mTitleTextView = (TextView) findViewById(R.id.title_text);
+        mTitleIconView = (ImageView) findViewById(R.id.title_icon);
+        mProgressView = (ProgressBar) findViewById(R.id.progress_bar);
+        mContext = getBaseContext();
+
+        initFromIntent(getIntent());
+        mAcceptUsersInput = true;
+    }
+
+    @Override
+    protected void onNewIntent(Intent intent) {
+        super.onNewIntent(intent);
+
+        Log.d(TAG, "onNewIntent");
+        initFromIntent(intent);
+        mAcceptUsersInput = true;
+    }
+
+    @Override
+    protected void onListItemClick(ListView l, View v, int position, long id) {
+        super.onListItemClick(l, v, position, id);
+ 
+        if (!mAcceptUsersInput) {
+            return;
+        }
+
+        Item item = getSelectedItem(position);
+        if (item == null) {
+            return;
+        }
+        sendResponse(StkAppService.RES_ID_MENU_SELECTION, item.id, false);
+        mAcceptUsersInput = false;
+        mProgressView.setVisibility(View.VISIBLE);
+        mProgressView.setIndeterminate(true);
+    }
+
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+
+        if (!mAcceptUsersInput) {
+            return true;
+        }
+
+        switch (keyCode) {
+        case KeyEvent.KEYCODE_BACK:
+            switch (mState) {
+            case STATE_SECONDARY:
+                cancelTimeOut();
+                mAcceptUsersInput = false;
+                sendResponse(StkAppService.RES_ID_BACKWARD);
+                return true;
+            case STATE_MAIN:
+                break;
+            }
+            break;
+        }
+        return super.onKeyDown(keyCode, event);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        appService.indicateMenuVisibility(true);
+        mStkMenu = appService.getMenu();
+        if (mStkMenu == null) {
+            finish();
+            return;
+        }
+        displayMenu();
+        startTimeOut();
+        // whenever this activity is resumed after a sub activity was invoked
+        // (Browser, In call screen) switch back to main state and enable  
+        // user's input;
+        if (!mAcceptUsersInput) {
+            mState = STATE_MAIN;
+            mAcceptUsersInput = true;
+        }
+        // make sure the progress bar is not shown.
+        mProgressView.setIndeterminate(false);
+        mProgressView.setVisibility(View.GONE);
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+
+        appService.indicateMenuVisibility(false);
+        cancelTimeOut();
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+
+        Log.d(TAG, "onDestroy");
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(android.view.Menu menu) {
+        super.onCreateOptionsMenu(menu);
+        menu.add(0, StkApp.MENU_ID_END_SESSION, 1, R.string.menu_end_session);
+        menu.add(0, StkApp.MENU_ID_HELP, 2, R.string.help);
+        return true;
+    }
+
+    @Override
+    public boolean onPrepareOptionsMenu(android.view.Menu menu) {
+        super.onPrepareOptionsMenu(menu);
+        boolean helpVisible = false;
+        boolean mainVisible = false;
+
+        if (mState == STATE_SECONDARY) {
+            mainVisible = true;
+        }
+        if (mStkMenu != null) {
+            helpVisible = mStkMenu.helpAvailable;
+        }
+
+        menu.findItem(StkApp.MENU_ID_END_SESSION).setVisible(mainVisible);
+        menu.findItem(StkApp.MENU_ID_HELP).setVisible(helpVisible);
+
+        return true;
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        if (!mAcceptUsersInput) {
+            return true;
+        }
+        switch (item.getItemId()) {
+        case StkApp.MENU_ID_END_SESSION:
+            cancelTimeOut();
+            mAcceptUsersInput = false;
+            // send session end response.
+            sendResponse(StkAppService.RES_ID_END_SESSION);
+            return true;
+        case StkApp.MENU_ID_HELP:
+            cancelTimeOut();
+            mAcceptUsersInput = false;
+            int position = getSelectedItemPosition();
+            Item stkItem = getSelectedItem(position);
+            if (stkItem == null) {
+                break;
+            }
+            // send help needed response.
+            sendResponse(StkAppService.RES_ID_MENU_SELECTION, stkItem.id, true);
+            return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        outState.putInt("STATE", mState);
+        outState.putParcelable("MENU", mStkMenu);
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Bundle savedInstanceState) {
+        mState = savedInstanceState.getInt("STATE");
+        mStkMenu = savedInstanceState.getParcelable("MENU");
+    }
+    
+    private void cancelTimeOut() {
+        mTimeoutHandler.removeMessages(MSG_ID_TIMEOUT);
+    }
+
+    private void startTimeOut() {
+        if (mState == STATE_SECONDARY) {
+            // Reset timeout.
+            cancelTimeOut();
+            mTimeoutHandler.sendMessageDelayed(mTimeoutHandler
+                    .obtainMessage(MSG_ID_TIMEOUT), StkApp.UI_TIMEOUT);
+        }
+    }
+     
+    // Bind list adapter to the items list.
+    private void displayMenu() {
+
+        if (mStkMenu != null) {
+            // Display title & title icon
+            if (mStkMenu.titleIcon != null) {
+                mTitleIconView.setImageBitmap(mStkMenu.titleIcon);
+                mTitleIconView.setVisibility(View.VISIBLE);
+            } else {
+                mTitleIconView.setVisibility(View.GONE);
+            }
+            if (!mStkMenu.titleIconSelfExplanatory) {
+                mTitleTextView.setVisibility(View.VISIBLE);
+                if (mStkMenu.title == null) {
+                    mTitleTextView.setText(R.string.app_name);
+                } else {
+                    mTitleTextView.setText(mStkMenu.title);
+                }
+            } else {
+                mTitleTextView.setVisibility(View.INVISIBLE);
+            }
+            // create an array adapter for the menu list
+            StkMenuAdapter adapter = new StkMenuAdapter(this,
+                    mStkMenu.items, mStkMenu.itemsIconSelfExplanatory);
+            // Bind menu list to the new adapter.
+            setListAdapter(adapter);
+            // Set default item
+            setSelection(mStkMenu.defaultItem);
+        }
+    }
+
+    private void initFromIntent(Intent intent) {
+
+        if (intent != null) {
+            mState = intent.getIntExtra("STATE", STATE_MAIN);
+        } else {
+            finish();
+        }
+    }
+
+    private Item getSelectedItem(int position) {
+        Item item = null;
+        if (mStkMenu != null) {
+            try {
+                item = mStkMenu.items.get(position);
+            } catch (IndexOutOfBoundsException e) {
+                if (StkApp.DBG) {
+                    Log.d(TAG, "Invalid menu");
+                }
+            } catch (NullPointerException e) {
+                if (StkApp.DBG) {
+                    Log.d(TAG, "Invalid menu");
+                }
+            }
+        }
+        return item;
+    }
+
+    private void sendResponse(int resId) {
+        sendResponse(resId, 0, false);
+    }
+
+    private void sendResponse(int resId, int itemId, boolean help) {
+        Bundle args = new Bundle();
+        args.putInt(StkAppService.OPCODE, StkAppService.OP_RESPONSE);
+        args.putInt(StkAppService.RES_ID, resId);
+        args.putInt(StkAppService.MENU_SELECTION, itemId);
+        args.putBoolean(StkAppService.HELP, help);
+        mContext.startService(new Intent(mContext, StkAppService.class)
+                .putExtras(args));
+    }
+}
diff --git a/src/com/android/stk/StkMenuAdapter.java b/src/com/android/stk/StkMenuAdapter.java
index cd0e7f9..253b39a 100644
--- a/src/com/android/stk/StkMenuAdapter.java
+++ b/src/com/android/stk/StkMenuAdapter.java
@@ -19,7 +19,6 @@
 import com.android.internal.telephony.gsm.stk.Item;
 
 import android.content.Context;
-import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -27,7 +26,6 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 
-import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -61,6 +59,7 @@
             imageView.setVisibility(View.GONE);
         } else {
             imageView.setImageBitmap(item.icon);
+            imageView.setVisibility(View.VISIBLE);
         }
 
         return convertView;
diff --git a/src/com/android/stk/StkSettings.java b/src/com/android/stk/StkSettings.java
deleted file mode 100644
index d1f07c4..0000000
--- a/src/com/android/stk/StkSettings.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (C) 2007 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.stk;
-
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.preference.Preference;
-import android.preference.PreferenceActivity;
-import android.preference.PreferenceScreen;
-import android.preference.CheckBoxPreference;
-import com.android.internal.telephony.gsm.stk.Service;
-
-/**
- * This class controls the UI for STK global settings.
- */
-public class StkSettings extends PreferenceActivity {
-    
-    // members
-    private Preference mServiceName = null;
-    private CheckBoxPreference mButtonOnOff = null;
-    private Service mStkService = null;
-    private static boolean mFirstCreate = true;
-    private static int mAppState;
-
-    //String keys for preference lookup
-    private static final String SERVICE_NAME  = "service_name";
-    private static final String TOGGLE_BUTTON  = "stk_app_enable_disable";
-
-    private static final int APP_ON = 1;
-    private static final int APP_OFF = 2;
-
-    @Override
-    protected void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-        // set the preference layout.
-        addPreferencesFromResource(R.xml.stk_settings);
-        
-        // Initialize members.
-        mStkService = Service.getInstance();
-        if (mStkService == null) {
-            finish();
-            return;
-        }
-        PreferenceScreen prefSet = getPreferenceScreen();
-        mServiceName  = prefSet.findPreference(SERVICE_NAME);
-        mButtonOnOff  = (CheckBoxPreference) prefSet.findPreference(TOGGLE_BUTTON);
-        
-        // Synchronize activity UI state with STK service.
-        refreshUiState();
-        mFirstCreate = false;
-    }
-    
-    // Click listener for all toggle events
-    public boolean onPreferenceTreeClick(PreferenceScreen preferences, Preference preference) {
-        if (preference instanceof CheckBoxPreference) {
-            CheckBoxPreference tp = (CheckBoxPreference) preference;
-
-            if (tp == mButtonOnOff) {
-                if (tp.isChecked()) {
-                    mAppState = APP_ON;
-                    sendBroadcast(new Intent("com.android.stk.action.INSTALL"));
-                    //StkInstaller.installApp(this);
-                } else {
-                    mAppState = APP_OFF;
-                    sendBroadcast(new Intent("com.android.stk.action.INSTALL"));
-                    //StkInstaller.unInstallApp(this);
-                }
-                return true;
-            }
-        }
-        return false;
-    }
-
-    // This function update the UI state according the the Service or package 
-    // manager state. ON the first time it is called the state should fit the 
-    // service. Sequential calls update the ui according to the state of the 
-    /// package manager.  
-    private void refreshUiState() {
-        if (!mFirstCreate) {
-            PackageManager pm = this.getPackageManager();
-            if (pm == null) return;
-    
-            // Set application state.
-            setAppState(mAppState == APP_ON);
-        } else {
-            boolean enabled = mStkService.isStkSupported();
-            mAppState = enabled ? APP_ON : APP_OFF;
-            setAppState(enabled);
-        }
-    }
-
-    private void setAppState(boolean enabled) {
-        if (enabled) {
-            String name = mStkService.getServiceName();
-            mServiceName.setSummary(mStkService.getServiceName());
-            mButtonOnOff.setChecked(true);
-        } else {
-            mServiceName.setSummary(R.string.stk_no_service);
-            mButtonOnOff.setChecked(false);
-        }
-    }
-}
diff --git a/src/com/android/stk/ToneDialog.java b/src/com/android/stk/ToneDialog.java
new file mode 100644
index 0000000..9cf4295
--- /dev/null
+++ b/src/com/android/stk/ToneDialog.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2007 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.stk;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Vibrator;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.internal.telephony.gsm.stk.TextMessage;
+import com.android.internal.telephony.gsm.stk.ToneSettings;
+
+/**
+ * Activity used for PLAY TONE command.
+ * 
+ */
+public class ToneDialog extends Activity {
+    TextMessage toneMsg = null;
+    ToneSettings settings = null;
+    TonePlayer player = null;
+
+    /**
+     * Handler used to stop tones from playing when the duration ends.
+     */
+    Handler mToneStopper = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+            case MSG_ID_STOP_TONE:
+                sendResponse(StkAppService.RES_ID_DONE);
+                finish();
+                break;
+            }
+        }
+    };
+
+    Vibrator mVibrator = new Vibrator();
+
+    // Message id to signal tone duration timeout.
+    private static final int MSG_ID_STOP_TONE = 0xda;
+
+    @Override
+    protected void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+       initFromIntent(getIntent());
+
+        // remove window title
+        View title = findViewById(com.android.internal.R.id.title);
+        title.setVisibility(View.GONE);
+        // set customized content view
+        setContentView(R.layout.stk_tone_dialog);
+
+        TextView tv = (TextView) findViewById(R.id.message);
+        ImageView iv = (ImageView) findViewById(R.id.icon);
+
+        // set text and icon
+        tv.setText(toneMsg.text);
+        if (toneMsg.icon == null) {
+            iv.setImageResource(com.android.internal.R.drawable.ic_volume);
+        } else {
+            iv.setImageBitmap(toneMsg.icon);
+        }
+
+        // Start playing tone and vibration
+        player = new TonePlayer();
+        player.play(settings.tone);
+        int timeout = StkApp.calculateDurationInMilis(settings.duration);
+        if (timeout == 0) {
+            timeout = StkApp.TONE_DFEAULT_TIMEOUT;
+        }
+        mToneStopper.sendEmptyMessageDelayed(MSG_ID_STOP_TONE, timeout);
+        if (settings.vibrate) {
+            mVibrator.vibrate(timeout);
+        }
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+
+        mToneStopper.removeMessages(MSG_ID_STOP_TONE);
+        player.stop();
+        player.release();
+        mVibrator.cancel();
+    }
+    
+    @Override
+    public boolean onKeyDown(int keyCode, KeyEvent event) {
+        switch (keyCode) {
+        case KeyEvent.KEYCODE_BACK:
+            sendResponse(StkAppService.RES_ID_END_SESSION);
+            finish();
+            break;
+        }
+        return false;
+    }
+
+    private void initFromIntent(Intent intent) {
+        if (intent == null) {
+            finish();
+        }
+        toneMsg = intent.getParcelableExtra("TEXT");
+        settings = intent.getParcelableExtra("TONE");
+    }
+
+    private void sendResponse(int resId) {
+        Bundle args = new Bundle();
+        args.putInt(StkAppService.OPCODE, StkAppService.OP_RESPONSE);
+        args.putInt(StkAppService.RES_ID, resId);
+        startService(new Intent(this, StkAppService.class).putExtras(args));
+    }
+}
diff --git a/src/com/android/stk/TonePlayer.java b/src/com/android/stk/TonePlayer.java
index d8d9195..1ba61ca 100644
--- a/src/com/android/stk/TonePlayer.java
+++ b/src/com/android/stk/TonePlayer.java
@@ -48,7 +48,7 @@
     private ToneGenerator mToneGenerator = null;
 
     TonePlayer() {
-        mToneGenerator = new ToneGenerator(AudioManager.STREAM_RING, 80);
+        mToneGenerator = new ToneGenerator(AudioManager.STREAM_SYSTEM, 100);
     }
 
     public void play(Tone tone) {
diff --git a/src/com/android/stk/Util.java b/src/com/android/stk/Util.java
deleted file mode 100644
index edde82f..0000000
--- a/src/com/android/stk/Util.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2007 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.stk;
-
-import android.os.Bundle;
-import com.android.internal.telephony.gsm.stk.FontSize;
-import com.android.internal.telephony.gsm.stk.TextAlignment;
-import com.android.internal.telephony.gsm.stk.TextAttribute;
-import com.android.internal.telephony.gsm.stk.TextColor;
-
-public class Util {
-    // Constants
-    public static final String INPUT_TYPE                   = "Stk.InputType";
-    public static final String INPUT_PROMPT                 = "Stk.InputPrompt";
-    public static final String INPUT_DEFAULT                = "Stk.InputDefault";
-    public static final String INPUT_CALL_PERMISSION        = "Stk.InputCallPermission";
-    public static final String INPUT_TYPE_TEXT              = "Stk.InputType.Text";
-    public static final String INPUT_TYPE_KEY               = "Stk.InputType.Key";
-    
-    public static final String INPUT_TEXT_ATTRS             = "Stk.TextAtrs";
-    public static final String INPUT_ATTR_START             = "Stk.Atr.Start";
-    public static final String INPUT_ATTR_LENGHT            = "Stk.Atr.Length";
-    public static final String INPUT_ATTR_ALIGN             = "Stk.Atr.Align";
-    public static final String INPUT_ATTR_SIZE              = "Stk.Atr.Size";
-    public static final String INPUT_ATTR_BOLD              = "Stk.Atr.Bold'";
-    public static final String INPUT_ATTR_ITALIC            = "Stk.Atr.Italic";
-    public static final String INPUT_ATTR_UNDERLINED        = "Stk.Atr.underlined'";    
-    public static final String INPUT_ATTR_STRIKE_THROUGH    = "Stk.Atr.Strike.Through";
-    public static final String INPUT_ATTR_COLOR             = "Stk.Atr.Color";
-
-    public static final String INPUT_GLBL_ATTRS             = "Stk.GlblAtrs";
-    public static final String INPUT_ATTR_MINLEN            = "Stk.Atr.MinLen";
-    public static final String INPUT_ATTR_MAXLEN            = "Stk.Atr.MaxLen";
-    public static final String INPUT_ATTR_NOMAAXLIM         = "Stk.Atr.NoMaxLimit";
-    public static final String INPUT_ATTR_DIGITS            = "Stk.Atr.Digits";
-    public static final String INPUT_ATTR_UCS2              = "Stk.Atr.UCS2";
-    public static final String INPUT_ATTR_ECHO              = "Stk.Atr.Echo";
-    public static final String INPUT_ATTR_HELP              = "Stk.Atr.Help";
-    public static final String INPUT_ATTR_IMD_RESPONSE      = "Stk.Atr.ImdResponse";
-    public static final String INPUT_ATTR_YES_NO            = "Stk.Atr.YesNo";
-
-    // Packing text attributes into a bundle to pass with an Intent.
-    public static Bundle packTextAttr(TextAttribute textAttrs) {
-        if (textAttrs == null) return null;
-
-        Bundle bundle = new Bundle();
-
-        bundle.putInt(INPUT_ATTR_START, textAttrs.start);
-        bundle.putInt(INPUT_ATTR_LENGHT, textAttrs.length);
-        if (textAttrs.align != null) {
-            bundle.putInt(INPUT_ATTR_ALIGN, textAttrs.align.ordinal());
-        }
-        if (textAttrs.size != null) {
-            bundle.putInt(INPUT_ATTR_SIZE, textAttrs.size.ordinal());
-        }
-        bundle.putBoolean(INPUT_ATTR_BOLD, textAttrs.bold);
-        bundle.putBoolean(INPUT_ATTR_ITALIC, textAttrs.italic);
-        bundle.putBoolean(INPUT_ATTR_UNDERLINED, textAttrs.underlined);
-        bundle.putBoolean(INPUT_ATTR_STRIKE_THROUGH, textAttrs.strikeThrough);
-        if (textAttrs.color != null) {
-            bundle.putInt(INPUT_ATTR_COLOR, textAttrs.color.ordinal());
-        }
-        return bundle;
-    }
-
-    // Unpacking text attributes from a bundle passed with an Intent.
-    public static TextAttribute unPackTextAttr(Bundle bundle) {
-        if (bundle == null) return null;
-         
-        int start = bundle.getInt(INPUT_ATTR_START);
-        int length = bundle.getInt(INPUT_ATTR_LENGHT);
-        TextAlignment align = TextAlignment.fromInt(bundle.getInt(INPUT_ATTR_ALIGN));
-        FontSize size = FontSize.fromInt(bundle.getInt(INPUT_ATTR_SIZE));
-        boolean bold = bundle.getBoolean(INPUT_ATTR_BOLD);
-        boolean italic = bundle.getBoolean(INPUT_ATTR_ITALIC);
-        boolean underlined = bundle.getBoolean(INPUT_ATTR_UNDERLINED);
-        boolean strikeThrough = bundle.getBoolean(INPUT_ATTR_STRIKE_THROUGH);
-        TextColor color = TextColor.fromInt(bundle.getInt(INPUT_ATTR_COLOR));
-        
-        TextAttribute textAttrs = new TextAttribute(start, length, align, size,
-                bold, italic, underlined, strikeThrough, color);
-        
-        return textAttrs;
-    }
-}
-
-
-
-
-
diff --git a/src/com/android/stk/WatchDog.java b/src/com/android/stk/WatchDog.java
deleted file mode 100644
index 423e694..0000000
--- a/src/com/android/stk/WatchDog.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2007 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.stk;
-
-import android.os.Handler;
-import android.util.Log;
-
-/**
- * This interface defines Event to be used by WatchDog.
- * Watchdog expires when event is set.
- */
-interface Event {
-
-    public void set();
-    
-    public void unSet();
-
-    public boolean isSet();
-}
-
-/**
- * This class implements Watch Dog using a daemon thread.
- * WatchDog waits for an event to expire and execute Runnable in the caller 
- * context.
- */
-class WatchDog extends Thread {
-    // Constants
-    private static final int POLLING_INTERVAL = 150;
-    public static final int TIMEOUT_WAIT_FOREVER = Integer.MAX_VALUE;
-
-    private static final String TAG = "WatchDog";
-    private static final boolean DBG = true;
-
-    // Members
-    private Event mEvent = null;  
-    private Handler mCaller = null;
-    private Runnable mRunnable = null;
-    private int mTimeout = TIMEOUT_WAIT_FOREVER;
-    private int mInterval = POLLING_INTERVAL;
-    private int mElapsedTime = 0;
-    private Object mElapsedTimeLock = new Object();
-    private boolean mCanceled = false;
-    private boolean mPaused = false; 
-
-    class VoidEvent implements Event {
-        public void set() {}
-        
-        public void unSet() {}
-
-        public boolean isSet() {
-            return false;
-        }
-    }
-
-    WatchDog(Event event, Handler caller, Runnable onEventResponse, int timeout) {
-        mEvent = event == null ? new VoidEvent() : event;
-        mCaller = caller;
-        mRunnable = onEventResponse;
-        mTimeout = timeout;
-
-        this.setDaemon(true);
-        this.start();
-    }
-
-    public void cancel() {
-        mTimeout = 0;
-        mCanceled = true;
-    }
-
-    public void reset() {
-        synchronized (mElapsedTimeLock) {
-            mElapsedTime = 0;
-        }
-    }
-    
-    public void pause() {
-        mPaused = true;
-    }
-    
-    public void unpause() {
-        mPaused = false;
-    }
-
-    @Override
-    public void run() {
-        watchEvent();
-        // When event expires post response to caller.
-        if (mCaller != null && mRunnable != null) {
-            if (!mCanceled) {
-                mCaller.post(mRunnable);
-            }
-        }
-    }
-
-    // Synchronized method, block until event expires.
-    private void watchEvent() {
-        while (!isEventSet() && !isTimedOut()) {
-            try {
-                Thread.sleep(mInterval);
-                incrementTime();
-            } catch (InterruptedException ie) {
-                if (DBG) Log.d(TAG, ie.toString());
-            }
-        }
-    }
-
-    private void incrementTime() {
-        if (mPaused) {
-            return;
-        }
-        synchronized (mElapsedTimeLock) {
-            mElapsedTime += (mTimeout == TIMEOUT_WAIT_FOREVER ? 0 : mInterval);
-        }
-    }
-
-    private boolean isTimedOut() {
-        if (mPaused) {
-            return false;
-        }
-        return (mElapsedTime >= mTimeout);
-    }
-
-    private boolean isEventSet() {
-        if (mPaused) {
-            return false;
-        }
-        return mEvent.isSet();
-    }
-}