summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk13
-rw-r--r--AndroidManifest.xml90
-rw-r--r--MODULE_LICENSE_APACHE20
-rw-r--r--NOTICE190
-rwxr-xr-xres/drawable/ic_launcher_sim_toolkit.pngbin0 -> 3131 bytes
-rw-r--r--res/layout/stk_event_msg.xml43
-rw-r--r--res/layout/stk_input.xml100
-rw-r--r--res/layout/stk_menu_item.xml44
-rw-r--r--res/layout/stk_menu_list.xml42
-rw-r--r--res/layout/stk_msg_dialog.xml74
-rw-r--r--res/layout/stk_title.xml75
-rw-r--r--res/layout/stk_tone_dialog.xml44
-rw-r--r--res/values-cs/strings.xml34
-rw-r--r--res/values-de/strings.xml34
-rw-r--r--res/values-es/strings.xml34
-rw-r--r--res/values-fr/strings.xml34
-rw-r--r--res/values-it/strings.xml34
-rw-r--r--res/values-ja/strings.xml34
-rw-r--r--res/values-ko/strings.xml34
-rw-r--r--res/values-nb/strings.xml34
-rw-r--r--res/values-nl/strings.xml34
-rw-r--r--res/values-pl/strings.xml34
-rw-r--r--res/values-ru/strings.xml34
-rw-r--r--res/values-zh-rCN/strings.xml34
-rw-r--r--res/values-zh-rTW/strings.xml34
-rw-r--r--res/values/colors.xml20
-rw-r--r--res/values/strings.xml48
-rw-r--r--res/xml/stk_settings.xml33
-rw-r--r--src/com/android/stk/BootCompletedReceiver.java42
-rw-r--r--src/com/android/stk/StkApp.java66
-rw-r--r--src/com/android/stk/StkAppInstaller.java61
-rw-r--r--src/com/android/stk/StkAppService.java743
-rw-r--r--src/com/android/stk/StkCmdReceiver.java58
-rw-r--r--src/com/android/stk/StkDialogActivity.java189
-rw-r--r--src/com/android/stk/StkDigitsKeyListener.java54
-rw-r--r--src/com/android/stk/StkInputActivity.java328
-rw-r--r--src/com/android/stk/StkLauncherActivity.java39
-rw-r--r--src/com/android/stk/StkMenuActivity.java333
-rw-r--r--src/com/android/stk/StkMenuAdapter.java67
-rw-r--r--src/com/android/stk/ToneDialog.java133
-rw-r--r--src/com/android/stk/TonePlayer.java78
41 files changed, 3449 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..079d7ad
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,13 @@
+# Copyright 2007-2008 The Android Open Source Project
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := eng user
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := Stk
+LOCAL_CERTIFICATE := platform
+
+include $(BUILD_PACKAGE)
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
new file mode 100644
index 0000000..b8472f5
--- /dev/null
+++ b/AndroidManifest.xml
@@ -0,0 +1,90 @@
+<?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.
+-->
+
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ 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="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>
+ </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" />
+ <action android:name="android.intent.action.EDIT" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
+
+ <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/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/MODULE_LICENSE_APACHE2
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..c5b1efa
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,190 @@
+
+ Copyright (c) 2005-2008, 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.
+
+ 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.
+
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
diff --git a/res/drawable/ic_launcher_sim_toolkit.png b/res/drawable/ic_launcher_sim_toolkit.png
new file mode 100755
index 0000000..0dfec74
--- /dev/null
+++ b/res/drawable/ic_launcher_sim_toolkit.png
Binary files differ
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_input.xml b/res/layout/stk_input.xml
new file mode 100644
index 0000000..fdaa39f
--- /dev/null
+++ b/res/layout/stk_input.xml
@@ -0,0 +1,100 @@
+<?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.
+-->
+
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:padding="20dip"
+ android:layout_gravity="center_horizontal">
+ <TextView
+ android:id="@+id/prompt"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:textStyle="bold"
+ android:gravity="center_horizontal"
+ android:paddingBottom="30dip" />
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content">
+ <LinearLayout
+ android:id="@+id/normal_layout"
+ android:visibility="visible"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_marginLeft="10dip"
+ android:layout_marginRight="10dip"
+ android:layout_height="wrap_content">
+ <LinearLayout
+ android:id="@+id/input_restriction_info"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="4dip"
+ android:orientation="horizontal">
+ <TextView
+ android:id="@+id/input_type"
+ android:gravity="left"
+ android:textColor="@color/ltgrey"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ <TextView
+ android:id="@+id/num_of_chars"
+ android:textColor="@color/ltgrey"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="4dip" />
+ </LinearLayout>
+ <EditText
+ android:id="@+id/in_text"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginBottom="20dip"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" />
+ <Button
+ android:id="@+id/button_ok"
+ android:layout_gravity="center_horizontal"
+ android:layout_width="100sp"
+ android:layout_height="wrap_content"
+ android:textStyle="bold"
+ android:text="@string/button_ok" />
+ </LinearLayout>
+ <LinearLayout
+ android:id="@+id/yes_no_layout"
+ android:visibility="gone"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal">
+ <Button
+ android:id="@+id/button_yes"
+ android:layout_width="100sp"
+ android:layout_height="wrap_content"
+ android:textStyle="bold"
+ android:text="@string/button_yes" />
+ <Button
+ android:id="@+id/button_no"
+ android:layout_marginLeft="10dip"
+ android:layout_width="100sp"
+ android:layout_height="wrap_content"
+ android:textStyle="bold"
+ android:text="@string/button_no" />
+ </LinearLayout>
+ </LinearLayout>
+ </LinearLayout>
+</ScrollView>
diff --git a/res/layout/stk_menu_item.xml b/res/layout/stk_menu_item.xml
new file mode 100644
index 0000000..98d7828
--- /dev/null
+++ b/res/layout/stk_menu_item.xml
@@ -0,0 +1,44 @@
+<?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="fill_parent"
+ android:layout_height="fill_parent"
+ android:gravity="center"
+ android:orientation="horizontal">
+
+ <ImageView
+ android:id="@+id/icon"
+ android:scaleType="fitCenter"
+ android:layout_width="@android:dimen/app_icon_size"
+ android:layout_height="@android:dimen/app_icon_size"
+ android:layout_gravity="center_vertical"
+ android:layout_marginLeft="5dip"
+ />
+
+ <TextView
+ android:id="@+id/text"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:maxLength="234"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:gravity="center_vertical"
+ android:layout_marginLeft="9dip"
+ />
+
+</LinearLayout>
diff --git a/res/layout/stk_menu_list.xml b/res/layout/stk_menu_list.xml
new file mode 100644
index 0000000..50e5717
--- /dev/null
+++ b/res/layout/stk_menu_list.xml
@@ -0,0 +1,42 @@
+<?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="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <!-- Include stk title layout. -->
+ <include
+ android:id="@+id/stk_menu_title"
+ layout="@layout/stk_title" />
+
+ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <ListView android:id="@android:id/list"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent" />
+
+ <TextView android:id="@android:id/empty"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:textSize="12sp" />
+ </LinearLayout>
+</LinearLayout>
diff --git a/res/layout/stk_msg_dialog.xml b/res/layout/stk_msg_dialog.xml
new file mode 100644
index 0000000..c8ec5b0
--- /dev/null
+++ b/res/layout/stk_msg_dialog.xml
@@ -0,0 +1,74 @@
+<?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="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical" >
+
+ <LinearLayout android:id="@+id/messagePanel"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ 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: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
new file mode 100644
index 0000000..4d09368
--- /dev/null
+++ b/res/layout/stk_title.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:fitsSystemWindows="true">
+
+ <LinearLayout android:id="@+id/stk_title"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:layout_centerVertical="true"
+ style="?android:attr/windowTitleBackgroundStyle" >
+
+ <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"
+ 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"
+ android:layout_weight="1"
+ android:foregroundGravity="fill_horizontal|top"
+ android:foreground="?android:attr/windowContentOverlay" />
+</LinearLayout>
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-cs/strings.xml b/res/values-cs/strings.xml
new file mode 100644
index 0000000..cc93b0f
--- /dev/null
+++ b/res/values-cs/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name">"Nástroje SIM"</string>
+ <string name="menu_end_session">"Ukončit relaci"</string>
+ <string name="help">"Nápověda"</string>
+ <string name="menu_back">"Zpět"</string>
+ <string name="service_name">"Název služby"</string>
+ <string name="stk_no_service">"Žádná služba není dostupná"</string>
+ <string name="button_ok">"OK"</string>
+ <string name="button_cancel">"Zrušit"</string>
+ <string name="button_yes">"Ano"</string>
+ <string name="button_no">"Ne"</string>
+ <string name="alphabet">"Abecedy"</string>
+ <string name="digits">"Číslice (0-9, *, #, +)"</string>
+ <string name="default_call_setup_msg">"Probíhá hovor..."</string>
+ <string name="stk_app_state">"Stav aplikace"</string>
+ <string name="enable_app">"Povoleno"</string>
+ <string name="disable_app">"Vypnuto"</string>
+</resources>
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
new file mode 100644
index 0000000..ee33189
--- /dev/null
+++ b/res/values-de/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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 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>
+ <string name="stk_app_state">"Status der Anwendung"</string>
+ <string name="enable_app">"Aktiviert"</string>
+ <string name="disable_app">"Deaktiviert"</string>
+</resources>
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
new file mode 100644
index 0000000..ba118c7
--- /dev/null
+++ b/res/values-es/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name">"Servicios SIM"</string>
+ <string name="menu_end_session">"Finalizar sesión"</string>
+ <string name="help">"Ayuda"</string>
+ <string name="menu_back">"Anterior"</string>
+ <string name="service_name">"Nombre de servicio"</string>
+ <string name="stk_no_service">"Ningún servicio disponible"</string>
+ <string name="button_ok">"Aceptar"</string>
+ <string name="button_cancel">"Cancelar"</string>
+ <string name="button_yes">"Sí"</string>
+ <string name="button_no">"No"</string>
+ <string name="alphabet">"Caracteres alfabéticos"</string>
+ <string name="digits">"Caracteres numéricos (0-9, *, #, +)"</string>
+ <string name="default_call_setup_msg">"Llamada en curso..."</string>
+ <string name="stk_app_state">"Estado de la aplicación"</string>
+ <string name="enable_app">"Habilitado"</string>
+ <string name="disable_app">"Inhabilitado"</string>
+</resources>
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
new file mode 100644
index 0000000..09f2ace
--- /dev/null
+++ b/res/values-fr/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name">"Boîte à outils SIM"</string>
+ <string name="menu_end_session">"Fermer la session"</string>
+ <string name="help">"Aide"</string>
+ <string name="menu_back">"Retour"</string>
+ <string name="service_name">"Nom du service"</string>
+ <string name="stk_no_service">"Aucun service disponible"</string>
+ <string name="button_ok">"OK"</string>
+ <string name="button_cancel">"Annuler"</string>
+ <string name="button_yes">"Oui"</string>
+ <string name="button_no">"Non"</string>
+ <string name="alphabet">"Alphabets"</string>
+ <string name="digits">"Chiffres (0-9, *, #, +)"</string>
+ <string name="default_call_setup_msg">"Appel en cours..."</string>
+ <string name="stk_app_state">"État de l\'application"</string>
+ <string name="enable_app">"Activé"</string>
+ <string name="disable_app">"Désactivé"</string>
+</resources>
diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml
new file mode 100644
index 0000000..11b5742
--- /dev/null
+++ b/res/values-it/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name">"Kit strumenti SIM"</string>
+ <string name="menu_end_session">"Termina sessione"</string>
+ <string name="help">"Guida"</string>
+ <string name="menu_back">"Indietro"</string>
+ <string name="service_name">"Nome servizio"</string>
+ <string name="stk_no_service">"Nessun servizio disponibile"</string>
+ <string name="button_ok">"OK"</string>
+ <string name="button_cancel">"Annulla"</string>
+ <string name="button_yes">"Sì"</string>
+ <string name="button_no">"No"</string>
+ <string name="alphabet">"Caratteri alfabetici"</string>
+ <string name="digits">"Cifre (0-9, *, #, +)"</string>
+ <string name="default_call_setup_msg">"Chiamata in corso..."</string>
+ <string name="stk_app_state">"Stato applicazione"</string>
+ <string name="enable_app">"Attivato"</string>
+ <string name="disable_app">"Disattivato"</string>
+</resources>
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
new file mode 100644
index 0000000..8e10981
--- /dev/null
+++ b/res/values-ja/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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 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>
+ <string name="stk_app_state">"アプリケーションの状態"</string>
+ <string name="enable_app">"有効"</string>
+ <string name="disable_app">"無効"</string>
+</resources>
diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml
new file mode 100644
index 0000000..a12bda5
--- /dev/null
+++ b/res/values-ko/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name">"SIM 툴킷"</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">"확인"</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>
+ <string name="stk_app_state">"응용프로그램 상태"</string>
+ <string name="enable_app">"사용"</string>
+ <string name="disable_app">"사용 안 함"</string>
+</resources>
diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml
new file mode 100644
index 0000000..694e6ff
--- /dev/null
+++ b/res/values-nb/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name">"SIM-verktøy"</string>
+ <string name="menu_end_session">"Avslutt økt"</string>
+ <string name="help">"Hjelp"</string>
+ <string name="menu_back">"Tilbake"</string>
+ <string name="service_name">"Tjenestenavn"</string>
+ <string name="stk_no_service">"Ingen tjenester er tilgjengelig"</string>
+ <string name="button_ok">"OK"</string>
+ <string name="button_cancel">"Avbryt"</string>
+ <string name="button_yes">"Ja"</string>
+ <string name="button_no">"Nei"</string>
+ <string name="alphabet">"Alfabeter"</string>
+ <string name="digits">"Siffer (0-9, *, #, +)"</string>
+ <string name="default_call_setup_msg">"Anrop underveis…"</string>
+ <string name="stk_app_state">"Applikasjonstilstand"</string>
+ <string name="enable_app">"Aktivert"</string>
+ <string name="disable_app">"Deaktivert"</string>
+</resources>
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
new file mode 100644
index 0000000..cf17363
--- /dev/null
+++ b/res/values-nl/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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 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">"Sessie beëindigen"</string>
+ <string name="help">"Help"</string>
+ <string name="menu_back">"Terug"</string>
+ <string name="service_name">"Servicenaam"</string>
+ <string name="stk_no_service">"Geen service beschikbaar"</string>
+ <string name="button_ok">"OK"</string>
+ <string name="button_cancel">"Annuleren"</string>
+ <string name="button_yes">"Ja"</string>
+ <string name="button_no">"Nee"</string>
+ <string name="alphabet">"Alfabetten"</string>
+ <string name="digits">"Symbolen (0-9, *, #, +)"</string>
+ <string name="default_call_setup_msg">"Actieve oproep..."</string>
+ <string name="stk_app_state">"Toepassingsstatus"</string>
+ <string name="enable_app">"Ingeschakeld"</string>
+ <string name="disable_app">"Uitgeschakeld"</string>
+</resources>
diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml
new file mode 100644
index 0000000..b80fefb
--- /dev/null
+++ b/res/values-pl/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name">"Zestaw narzędzi SIM"</string>
+ <string name="menu_end_session">"Zakończ sesję"</string>
+ <string name="help">"Pomoc"</string>
+ <string name="menu_back">"Wstecz"</string>
+ <string name="service_name">"Nazwa usługi"</string>
+ <string name="stk_no_service">"Brak dostępnej usługi"</string>
+ <string name="button_ok">"OK"</string>
+ <string name="button_cancel">"Anuluj"</string>
+ <string name="button_yes">"Tak"</string>
+ <string name="button_no">"Nie"</string>
+ <string name="alphabet">"Znaki alfanumeryczne"</string>
+ <string name="digits">"Cyfry (0–9, *, #, +)"</string>
+ <string name="default_call_setup_msg">"Połączenie w toku..."</string>
+ <string name="stk_app_state">"Stan aplikacji"</string>
+ <string name="enable_app">"Włączone"</string>
+ <string name="disable_app">"Wyłączone"</string>
+</resources>
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
new file mode 100644
index 0000000..7dcb8e1
--- /dev/null
+++ b/res/values-ru/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name">"Инструментарий SIM"</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">"ОК"</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>
+ <string name="stk_app_state">"Состояние приложения"</string>
+ <string name="enable_app">"Включено"</string>
+ <string name="disable_app">"Отключено"</string>
+</resources>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
new file mode 100644
index 0000000..1d35740
--- /dev/null
+++ b/res/values-zh-rCN/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name">"SIM 卡工具包"</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">"确定"</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>
+ <string name="stk_app_state">"应用程序状态"</string>
+ <string name="enable_app">"已启用"</string>
+ <string name="disable_app">"已禁用"</string>
+</resources>
diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml
new file mode 100644
index 0000000..30d035c
--- /dev/null
+++ b/res/values-zh-rTW/strings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2009 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 xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="app_name">"SIM 工具箱"</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">"確定"</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>
+ <string name="stk_app_state">"應用程式狀態"</string>
+ <string name="enable_app">"已啟用"</string>
+ <string name="disable_app">"已停用"</string>
+</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
new file mode 100644
index 0000000..9435d30
--- /dev/null
+++ b/res/values/colors.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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>
+ <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
new file mode 100644
index 0000000..1252912
--- /dev/null
+++ b/res/values/strings.xml
@@ -0,0 +1,48 @@
+<?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>
+ <!-- Default Application label used on home screen with an icon -->
+ <string name="app_name">SIM Toolkit</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>
+ <!-- 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>
+</resources>
diff --git a/res/xml/stk_settings.xml b/res/xml/stk_settings.xml
new file mode 100644
index 0000000..e265406
--- /dev/null
+++ b/res/xml/stk_settings.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:title="@string/app_name" >
+
+ <PreferenceScreen
+ android:key="service_name"
+ android:title="@string/service_name"
+ android:summary="@string/stk_no_service"
+ android:persistent="false"/>
+
+ <CheckBoxPreference
+ android:key="stk_app_enable_disable"
+ android:title="@string/stk_app_state"
+ android:persistent="false"
+ android:summaryOn="@string/enable_app"
+ android:summaryOff="@string/disable_app"/>
+
+</PreferenceScreen>
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/StkApp.java b/src/com/android/stk/StkApp.java
new file mode 100644
index 0000000..ebd52b1
--- /dev/null
+++ b/src/com/android/stk/StkApp.java
@@ -0,0 +1,66 @@
+/*
+ * 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.Application;
+
+import com.android.internal.telephony.gsm.stk.Duration;
+
+/**
+ * Top-level Application class for STK app.
+ */
+abstract class StkApp extends Application {
+ // Application constants
+ public static final boolean DBG = true;
+
+ // Identifiers for option menu items
+ 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 = (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 from a duration instance.
+ * returns zero when duration is null.
+ */
+ public static int calculateDurationInMilis(Duration duration) {
+ int timeout = 0;
+ if (duration != null) {
+ switch (duration.timeUnit) {
+ case MINUTE:
+ timeout = 1000 * 60;
+ break;
+ case TENTH_SECOND:
+ timeout = 1000 * 10;
+ break;
+ case SECOND:
+ default:
+ timeout = 1000;
+ break;
+ }
+ timeout *= duration.timeInterval;
+ }
+ return timeout;
+ }
+}
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..136bc71
--- /dev/null
+++ b/src/com/android/stk/StkAppService.java
@@ -0,0 +1,743 @@
+/*
+ * 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;
+
+ // Used for setting FLAG_ACTIVITY_NO_USER_ACTION when
+ // creating an intent.
+ private enum InitiatedByUserAction {
+ yes, // The action was started via a user initiated action
+ unknown, // Not known for sure if user initated the action
+ }
+
+ // 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 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.StkService
+ .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 visibility) {
+ mMenuIsVisibile = visibility;
+ }
+
+ /*
+ * 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);
+ }
+
+ /**
+ * Returns 0 or FLAG_ACTIVITY_NO_USER_ACTION, 0 means the user initiated the action.
+ *
+ * @param userAction If the userAction is yes then we always return 0 otherwise
+ * mMenuIsVisible is used to determine what to return. If mMenuIsVisible is true
+ * then we are the foreground app and we'll return 0 as from our perspective a
+ * user action did cause. If it's false than we aren't the foreground app and
+ * FLAG_ACTIVITY_NO_USER_ACTION is returned.
+ *
+ * @return 0 or FLAG_ACTIVITY_NO_USER_ACTION
+ */
+ private int getFlagActivityNoUserAction(InitiatedByUserAction userAction) {
+ return ((userAction == InitiatedByUserAction.yes) | mMenuIsVisibile) ?
+ 0 : Intent.FLAG_ACTIVITY_NO_USER_ACTION;
+ }
+
+ private void launchMenuActivity(Menu menu) {
+ Intent newIntent = new Intent(Intent.ACTION_VIEW);
+ newIntent.setClassName(PACKAGE_NAME, MENU_ACTIVITY_NAME);
+ int intentFlags = Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_CLEAR_TOP;
+ if (menu == null) {
+ // We assume this was initiated by the user pressing the tool kit icon
+ intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.yes);
+
+ newIntent.putExtra("STATE", StkMenuActivity.STATE_MAIN);
+ } else {
+ // We don't know and we'll let getFlagActivityNoUserAction decide.
+ intentFlags |= getFlagActivityNoUserAction(InitiatedByUserAction.unknown);
+
+ newIntent.putExtra("STATE", StkMenuActivity.STATE_SECONDARY);
+ }
+ newIntent.setFlags(intentFlags);
+ mContext.startActivity(newIntent);
+ }
+
+ private void launchInputActivity() {
+ Intent newIntent = new Intent(Intent.ACTION_VIEW);
+ newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | getFlagActivityNoUserAction(InitiatedByUserAction.unknown));
+ 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
+ | getFlagActivityNoUserAction(InitiatedByUserAction.unknown));
+ 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
+ | getFlagActivityNoUserAction(InitiatedByUserAction.unknown));
+ 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
+ | getFlagActivityNoUserAction(InitiatedByUserAction.unknown));
+ 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..15eacec
--- /dev/null
+++ b/src/com/android/stk/StkDialogActivity.java
@@ -0,0 +1,189 @@
+/*
+ * 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() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch(msg.what) {
+ case MSG_ID_TIMEOUT:
+ sendResponse(StkAppService.RES_ID_TIMEOUT);
+ finish();
+ break;
+ }
+ }
+ };
+
+ //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
new file mode 100644
index 0000000..eb3d53a
--- /dev/null
+++ b/src/com/android/stk/StkDigitsKeyListener.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2006 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.text.method.NumberKeyListener;
+import android.view.KeyEvent;
+import android.view.inputmethod.EditorInfo;
+
+/**
+ * For entering dates in a text field.
+ */
+public class StkDigitsKeyListener extends NumberKeyListener {
+ @Override
+ protected char[] getAcceptedChars() {
+ return CHARACTERS;
+ }
+
+ public int getInputType() {
+ return EditorInfo.TYPE_CLASS_PHONE;
+ }
+
+ public static StkDigitsKeyListener getInstance() {
+ if (sInstance != null) {
+ return sInstance;
+ }
+ sInstance = new StkDigitsKeyListener();
+ return sInstance;
+ }
+
+ /**
+ * The characters that are used.
+ *
+ * @see KeyEvent#getMatch
+ * @see #getAcceptedChars
+ */
+ public static final char[] CHARACTERS = new char[] {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '*', '#', '+'};
+
+ private static StkDigitsKeyListener sInstance;
+}
diff --git a/src/com/android/stk/StkInputActivity.java b/src/com/android/stk/StkInputActivity.java
new file mode 100644
index 0000000..f1627e8
--- /dev/null
+++ b/src/com/android/stk/StkInputActivity.java
@@ -0,0 +1,328 @@
+/*
+ * 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.Context;
+import android.content.Intent;
+import android.graphics.drawable.BitmapDrawable;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.text.Editable;
+import android.text.InputFilter;
+import android.text.TextWatcher;
+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.FontSize;
+import com.android.internal.telephony.gsm.stk.Input;
+import com.android.internal.telephony.gsm.stk.StkLog;
+
+/**
+ * Display a request for a text input a long with a text edit form.
+ */
+public class StkInputActivity extends Activity implements View.OnClickListener,
+ TextWatcher {
+
+ // Members
+ private int mState;
+ private Context mContext;
+ private EditText mTextIn = null;
+ private TextView mPromptView = null;
+ private View mYesNoLayout = null;
+ private View mNormalLayout = null;
+ private Input mStkInput = null;
+
+ // Constants
+ private static final int STATE_TEXT = 1;
+ private static final int STATE_YES_NO = 2;
+
+ static final String YES_STR_RESPONSE = "YES";
+ static final String NO_STR_RESPONSE = "NO";
+
+ // 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);
+
+ // 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);
+ finish();
+ break;
+ }
+ }
+ };
+
+ // Click listener to handle buttons press..
+ public void onClick(View v) {
+ String input = null;
+
+ switch (v.getId()) {
+ case R.id.button_ok:
+ // Check that text entered is valid .
+ if (!verfiyTypedText()) {
+ return;
+ }
+ input = mTextIn.getText().toString();
+ break;
+ // Yes/No layout buttons.
+ case R.id.button_yes:
+ input = YES_STR_RESPONSE;
+ break;
+ case R.id.button_no:
+ input = NO_STR_RESPONSE;
+ break;
+ }
+
+ sendResponse(StkAppService.RES_ID_INPUT, input, false);
+ finish();
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ // Set the layout for this activity.
+ requestWindowFeature(Window.FEATURE_LEFT_ICON);
+ setContentView(R.layout.stk_input);
+
+ // Initialize members
+ mTextIn = (EditText) this.findViewById(R.id.in_text);
+ mPromptView = (TextView) this.findViewById(R.id.prompt);
+
+ // Set buttons listeners.
+ Button okButton = (Button) findViewById(R.id.button_ok);
+ Button yesButton = (Button) findViewById(R.id.button_yes);
+ Button noButton = (Button) findViewById(R.id.button_no);
+
+ okButton.setOnClickListener(this);
+ yesButton.setOnClickListener(this);
+ noButton.setOnClickListener(this);
+
+ mYesNoLayout = findViewById(R.id.yes_no_layout);
+ mNormalLayout = findViewById(R.id.normal_layout);
+
+ // Get the calling intent type: text/key, and setup the
+ // display parameters.
+ 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();
+ }
+ mContext = getBaseContext();
+ }
+
+ @Override
+ protected void onPostCreate(Bundle savedInstanceState) {
+ super.onPostCreate(savedInstanceState);
+
+ mTextIn.addTextChangedListener(this);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ startTimeOut();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+
+ cancelTimeOut();
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_BACK:
+ sendResponse(StkAppService.RES_ID_BACKWARD, null, false);
+ finish();
+ break;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ private void sendResponse(int resId) {
+ sendResponse(resId, null, false);
+ }
+
+ 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(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;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(android.view.Menu menu) {
+ super.onPrepareOptionsMenu(menu);
+ menu.findItem(StkApp.MENU_ID_END_SESSION).setVisible(true);
+ menu.findItem(StkApp.MENU_ID_HELP).setVisible(mStkInput.helpAvailable);
+
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case StkApp.MENU_ID_END_SESSION:
+ sendResponse(StkAppService.RES_ID_END_SESSION);
+ finish();
+ return true;
+ case StkApp.MENU_ID_HELP:
+ sendResponse(StkAppService.RES_ID_INPUT, "", true);
+ finish();
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ public void beforeTextChanged(CharSequence s, int start, int count,
+ int after) {
+ }
+
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ // Reset timeout.
+ startTimeOut();
+ }
+
+ public void afterTextChanged(Editable s) {
+ }
+
+ private boolean verfiyTypedText() {
+ // If not enough input was typed in stay on the edit screen.
+ if (mTextIn.getText().length() < mStkInput.minLen) {
+ return false;
+ }
+
+ return true;
+ }
+
+ 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);
+
+ int inTypeId = R.string.alphabet;
+
+ // set the prompt.
+ mPromptView.setText(mStkInput.text);
+
+ // Set input type (alphabet/digit) info close to the InText form.
+ if (mStkInput.digitOnly) {
+ mTextIn.setKeyListener(StkDigitsKeyListener.getInstance());
+ inTypeId = R.string.digits;
+ }
+ inTypeView.setText(inTypeId);
+
+ if (mStkInput.icon != null) {
+ setFeatureDrawable(Window.FEATURE_LEFT_ICON, new BitmapDrawable(
+ mStkInput.icon));
+ }
+
+ // Handle specific global and text attributes.
+ switch (mState) {
+ case STATE_TEXT:
+ int maxLen = mStkInput.maxLen;
+ int minLen = mStkInput.minLen;
+ mTextIn.setFilters(new InputFilter[] {new InputFilter.LengthFilter(
+ maxLen)});
+
+ // Set number of chars info.
+ String lengthLimit = String.valueOf(minLen);
+ if (maxLen != minLen) {
+ lengthLimit = minLen + " - " + maxLen;
+ }
+ numOfCharsView.setText(lengthLimit);
+
+ if (!mStkInput.echo) {
+ mTextIn.setTransformationMethod(PasswordTransformationMethod
+ .getInstance());
+ }
+ // Set default text if present.
+ if (mStkInput.defaultText != null) {
+ mTextIn.setText(mStkInput.defaultText);
+ } else {
+ // make sure the text is cleared
+ mTextIn.setText("", BufferType.EDITABLE);
+ }
+
+ break;
+ case STATE_YES_NO:
+ // Set display mode - normal / yes-no layout
+ mYesNoLayout.setVisibility(View.VISIBLE);
+ mNormalLayout.setVisibility(View.GONE);
+ break;
+ }
+ }
+
+ private float getFontSizeFactor(FontSize size) {
+ final float[] fontSizes =
+ {NORMAL_FONT_FACTOR, LARGE_FONT_FACTOR, SMALL_FONT_FACTOR};
+
+ return fontSizes[size.ordinal()];
+ }
+}
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..9b6d027
--- /dev/null
+++ b/src/com/android/stk/StkMenuActivity.java
@@ -0,0 +1,333 @@
+/*
+ * 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.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;
+import com.android.internal.telephony.gsm.stk.StkLog;
+
+/**
+ * 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();
+
+ // 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);
+
+ StkLog.d(this, "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);
+
+ StkLog.d(this, "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();
+
+ StkLog.d(this, "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) {
+ StkLog.d(this, "Invalid menu");
+ }
+ } catch (NullPointerException e) {
+ if (StkApp.DBG) {
+ StkLog.d(this, "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
new file mode 100644
index 0000000..253b39a
--- /dev/null
+++ b/src/com/android/stk/StkMenuAdapter.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2008 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.Item;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import java.util.List;
+
+/**
+ * Icon list view adapter to show the list of STK items.
+ */
+public class StkMenuAdapter extends ArrayAdapter<Item> {
+ private final LayoutInflater mInflater;
+ private boolean mIcosSelfExplanatory = false;
+
+ public StkMenuAdapter(Context context, List<Item> items,
+ boolean icosSelfExplanatory) {
+ super(context, 0, items);
+ mInflater = LayoutInflater.from(context);
+ mIcosSelfExplanatory = icosSelfExplanatory;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ final Item item = getItem(position);
+
+ if (convertView == null) {
+ convertView = mInflater.inflate(R.layout.stk_menu_item, parent,
+ false);
+ }
+
+ if (!mIcosSelfExplanatory || (mIcosSelfExplanatory && item.icon == null)) {
+ ((TextView) convertView.findViewById(R.id.text)).setText(item.text);
+ }
+ ImageView imageView = ((ImageView) convertView.findViewById(R.id.icon));
+ if (item.icon == null) {
+ imageView.setVisibility(View.GONE);
+ } else {
+ imageView.setImageBitmap(item.icon);
+ imageView.setVisibility(View.VISIBLE);
+ }
+
+ return convertView;
+ }
+}
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
new file mode 100644
index 0000000..00e859d
--- /dev/null
+++ b/src/com/android/stk/TonePlayer.java
@@ -0,0 +1,78 @@
+/*
+ * 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 java.util.HashMap;
+
+import android.media.AudioManager;
+import android.media.ToneGenerator;
+import com.android.internal.telephony.gsm.stk.Tone;
+
+/**
+ * Class that implements a tones player for the SIM toolkit application.
+ *
+ */
+public class TonePlayer {
+ private static final HashMap<Tone, Integer> mToneMap = new HashMap<Tone, Integer>();
+
+ static {
+ // Map STK tone ids to the system tone ids.
+ mToneMap.put(Tone.DIAL, ToneGenerator.TONE_SUP_DIAL);
+ mToneMap.put(Tone.BUSY, ToneGenerator.TONE_SUP_BUSY);
+ mToneMap.put(Tone.CONGESTION, ToneGenerator.TONE_SUP_CONGESTION);
+ mToneMap.put(Tone.RADIO_PATH_ACK, ToneGenerator.TONE_SUP_RADIO_ACK);
+ mToneMap.put(Tone.RADIO_PATH_NOT_AVAILABLE, ToneGenerator.TONE_SUP_RADIO_NOTAVAIL);
+ mToneMap.put(Tone.ERROR_SPECIAL_INFO, ToneGenerator.TONE_SUP_ERROR);
+ mToneMap.put(Tone.CALL_WAITING, ToneGenerator.TONE_SUP_CALL_WAITING);
+ mToneMap.put(Tone.RINGING, ToneGenerator.TONE_SUP_RINGTONE);
+ mToneMap.put(Tone.GENERAL_BEEP, ToneGenerator.TONE_PROP_BEEP);
+ mToneMap.put(Tone.POSITIVE_ACK, ToneGenerator.TONE_PROP_ACK);
+ mToneMap.put(Tone.NEGATIVE_ACK, ToneGenerator.TONE_PROP_NACK);
+ }
+
+ private ToneGenerator mToneGenerator = null;
+
+ TonePlayer() {
+ mToneGenerator = new ToneGenerator(AudioManager.STREAM_SYSTEM, 100);
+ }
+
+ public void play(Tone tone) {
+ int toneId = getToneId(tone);
+ if (toneId > 0 && mToneGenerator != null) {
+ mToneGenerator.startTone(toneId);
+ }
+ }
+
+ public void stop() {
+ if (mToneGenerator != null) {
+ mToneGenerator.stopTone();
+ }
+ }
+
+ public void release() {
+ mToneGenerator.release();
+ }
+
+ private int getToneId(Tone tone) {
+ int toneId = ToneGenerator.TONE_PROP_BEEP;
+
+ if (tone != null && mToneMap.containsKey(tone)) {
+ toneId = mToneMap.get(tone);
+ }
+ return toneId;
+ }
+}