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();
- }
-}