diff options
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 @@ -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 Binary files differnew file mode 100755 index 0000000..0dfec74 --- /dev/null +++ b/res/drawable/ic_launcher_sim_toolkit.png 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; + } +} |