WAPPushManager, WAP Push over SMS message handler
The WAPPushManager is a new, optional service for handling WAP Push over SMS messages. This service allows a carrier to designate a high priority handler for specific WAP Push over SMS messages without affecting other WAP Push over SMS, binary SMS, or SMS text messages. It is also optional, so that it can be configured out of the target image resulting in no change in the WAP Push over SMS handling behavior compared to the current AOSP. - This patch contains the WAPPushManager itself, the associated test code, and the modifications to telephony to use the WAPPushManager. Change-Id: I4f7fb5b68fc666da9bdeeea525e8797ae317e4b5
This commit is contained in:
@@ -184,6 +184,7 @@ LOCAL_SRC_FILES += \
|
||||
telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl \
|
||||
telephony/java/com/android/internal/telephony/IIccPhoneBook.aidl \
|
||||
telephony/java/com/android/internal/telephony/ISms.aidl \
|
||||
telephony/java/com/android/internal/telephony/IWapPushManager.aidl \
|
||||
wifi/java/android/net/wifi/IWifiManager.aidl \
|
||||
telephony/java/com/android/internal/telephony/IExtendedNetworkService.aidl \
|
||||
vpn/java/android/net/vpn/IVpnService.aidl \
|
||||
|
||||
20
packages/WAPPushManager/Android.mk
Normal file
20
packages/WAPPushManager/Android.mk
Normal file
@@ -0,0 +1,20 @@
|
||||
# Copyright 2007-2008 The Android Open Source Project
|
||||
|
||||
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE_TAGS := optional
|
||||
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||
|
||||
LOCAL_PACKAGE_NAME := WAPPushManager
|
||||
|
||||
LOCAL_STATIC_JAVA_LIBRARIES += android-common
|
||||
|
||||
LOCAL_PROGUARD_FLAGS := -include $(LOCAL_PATH)/proguard.flags
|
||||
|
||||
include $(BUILD_PACKAGE)
|
||||
|
||||
# This finds and builds the test apk as well, so a single make does both.
|
||||
include $(call all-makefiles-under,$(LOCAL_PATH))
|
||||
38
packages/WAPPushManager/AndroidManifest.xml
Normal file
38
packages/WAPPushManager/AndroidManifest.xml
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
* Copyright (C) 2007-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.
|
||||
*/
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.smspush">
|
||||
|
||||
<permission android:name="com.android.smspush.WAPPUSH_MANAGER_BIND"
|
||||
android:protectionLevel="signatureOrSystem" />
|
||||
|
||||
<original-package android:name="com.android.smspush" />
|
||||
<application>
|
||||
<service android:name=".WapPushManager"
|
||||
android:permission="com.android.smspush.WAPPUSH_MANAGER_BIND"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.android.internal.telephony.IWapPushManager"></action>
|
||||
</intent-filter>
|
||||
</service>
|
||||
</application>
|
||||
|
||||
|
||||
</manifest>
|
||||
49
packages/WAPPushManager/CleanSpec.mk
Normal file
49
packages/WAPPushManager/CleanSpec.mk
Normal file
@@ -0,0 +1,49 @@
|
||||
# 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.
|
||||
#
|
||||
|
||||
# If you don't need to do a full clean build but would like to touch
|
||||
# a file or delete some intermediate files, add a clean step to the end
|
||||
# of the list. These steps will only be run once, if they haven't been
|
||||
# run before.
|
||||
#
|
||||
# E.g.:
|
||||
# $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
|
||||
# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
|
||||
#
|
||||
# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
|
||||
# files that are missing or have been moved.
|
||||
#
|
||||
# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
|
||||
# Use $(OUT_DIR) to refer to the "out" directory.
|
||||
#
|
||||
# If you need to re-do something that's already mentioned, just copy
|
||||
# the command and add it to the bottom of the list. E.g., if a change
|
||||
# that you made last week required touching a file and a change you
|
||||
# made today requires touching the same file, just copy the old
|
||||
# touch step and add it to the end of the list.
|
||||
#
|
||||
# ************************************************
|
||||
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
|
||||
# ************************************************
|
||||
|
||||
# For example:
|
||||
#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
|
||||
#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
|
||||
#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
|
||||
#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
|
||||
|
||||
# ************************************************
|
||||
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
|
||||
# ************************************************
|
||||
0
packages/WAPPushManager/MODULE_LICENSE_APACHE2
Normal file
0
packages/WAPPushManager/MODULE_LICENSE_APACHE2
Normal file
190
packages/WAPPushManager/NOTICE
Normal file
190
packages/WAPPushManager/NOTICE
Normal file
@@ -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
|
||||
|
||||
18
packages/WAPPushManager/proguard.flags
Normal file
18
packages/WAPPushManager/proguard.flags
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
#apply method is dynamically referenced by the reflection class.
|
||||
-keep class android.app.ContextImpl$SharedPreferencesImpl$EditorImpl {
|
||||
void apply();
|
||||
}
|
||||
-keep class android.content.SharedPreferences$Editor {
|
||||
void apply();
|
||||
}
|
||||
|
||||
#WapPushManager is referenced only by AndroidManifest.xml
|
||||
-keep class com.android.smspush.WapPushManager {
|
||||
#CTS module method
|
||||
public boolean isDataExist(java.lang.String, java.lang.String,
|
||||
java.lang.String, java.lang.String);
|
||||
public boolean verifyData(java.lang.String, java.lang.String,
|
||||
java.lang.String, java.lang.String, int, boolean, boolean);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,424 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.smspush;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ComponentName;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.telephony.IWapPushManager;
|
||||
import com.android.internal.telephony.WapPushManagerParams;
|
||||
|
||||
/**
|
||||
* The WapPushManager service is implemented to process incoming
|
||||
* WAP Push messages and to maintain the Receiver Application/Application
|
||||
* ID mapping. The WapPushManager runs as a system service, and only the
|
||||
* WapPushManager can update the WAP Push message and Receiver Application
|
||||
* mapping (Application ID Table). When the device receives an SMS WAP Push
|
||||
* message, the WapPushManager looks up the Receiver Application name in
|
||||
* Application ID Table. If an application is found, the application is
|
||||
* launched using its full component name instead of broadcasting an implicit
|
||||
* Intent. If a Receiver Application is not found in the Application ID
|
||||
* Table or the WapPushManager returns a process-further value, the
|
||||
* telephony stack will process the message using existing message processing
|
||||
* flow, and broadcast an implicit Intent.
|
||||
*/
|
||||
public class WapPushManager extends Service {
|
||||
|
||||
private static final String LOG_TAG = "WAP PUSH";
|
||||
private static final String DATABASE_NAME = "wappush.db";
|
||||
private static final String APPID_TABLE_NAME = "appid_tbl";
|
||||
|
||||
/**
|
||||
* Version number must be incremented when table structure is changed.
|
||||
*/
|
||||
private static final int WAP_PUSH_MANAGER_VERSION = 1;
|
||||
private static final boolean DEBUG_SQL = false;
|
||||
private static final boolean LOCAL_LOGV = false;
|
||||
|
||||
/**
|
||||
* Inner class that deals with application ID table
|
||||
*/
|
||||
private class WapPushManDBHelper extends SQLiteOpenHelper {
|
||||
WapPushManDBHelper(Context context) {
|
||||
super(context, DATABASE_NAME, null, WAP_PUSH_MANAGER_VERSION);
|
||||
if (LOCAL_LOGV) Log.v(LOG_TAG, "helper instance created.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(SQLiteDatabase db) {
|
||||
if (LOCAL_LOGV) Log.v(LOG_TAG, "db onCreate.");
|
||||
String sql = "CREATE TABLE " + APPID_TABLE_NAME + " ("
|
||||
+ "id INTEGER PRIMARY KEY, "
|
||||
+ "x_wap_application TEXT, "
|
||||
+ "content_type TEXT, "
|
||||
+ "package_name TEXT, "
|
||||
+ "class_name TEXT, "
|
||||
+ "app_type INTEGER, "
|
||||
+ "need_signature INTEGER, "
|
||||
+ "further_processing INTEGER, "
|
||||
+ "install_order INTEGER "
|
||||
+ ")";
|
||||
|
||||
if (DEBUG_SQL) Log.v(LOG_TAG, "sql: " + sql);
|
||||
db.execSQL(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(SQLiteDatabase db,
|
||||
int oldVersion, int newVersion) {
|
||||
// TODO: when table structure is changed, need to dump and restore data.
|
||||
/*
|
||||
db.execSQL(
|
||||
"drop table if exists "+APPID_TABLE_NAME);
|
||||
onCreate(db);
|
||||
*/
|
||||
Log.w(LOG_TAG, "onUpgrade is not implemented yet. do nothing.");
|
||||
}
|
||||
|
||||
protected class queryData {
|
||||
public String packageName;
|
||||
public String className;
|
||||
int appType;
|
||||
int needSignature;
|
||||
int furtherProcessing;
|
||||
int installOrder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the latest receiver application info with supplied application ID and
|
||||
* content type.
|
||||
* @param app_id application ID to look up
|
||||
* @param content_type content type to look up
|
||||
*/
|
||||
protected queryData queryLastApp(SQLiteDatabase db,
|
||||
String app_id, String content_type) {
|
||||
String sql = "select install_order, package_name, class_name, "
|
||||
+ " app_type, need_signature, further_processing"
|
||||
+ " from " + APPID_TABLE_NAME
|
||||
+ " where x_wap_application=\'" + app_id + "\'"
|
||||
+ " and content_type=\'" + content_type + "\'"
|
||||
+ " order by install_order desc";
|
||||
if (DEBUG_SQL) Log.v(LOG_TAG, "sql: " + sql);
|
||||
Cursor cur = db.rawQuery(sql, null);
|
||||
queryData ret = null;
|
||||
|
||||
if (cur.moveToNext()) {
|
||||
ret = new queryData();
|
||||
ret.installOrder = cur.getInt(cur.getColumnIndex("install_order"));
|
||||
ret.packageName = cur.getString(cur.getColumnIndex("package_name"));
|
||||
ret.className = cur.getString(cur.getColumnIndex("class_name"));
|
||||
ret.appType = cur.getInt(cur.getColumnIndex("app_type"));
|
||||
ret.needSignature = cur.getInt(cur.getColumnIndex("need_signature"));
|
||||
ret.furtherProcessing = cur.getInt(cur.getColumnIndex("further_processing"));
|
||||
}
|
||||
cur.close();
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The exported API implementations class
|
||||
*/
|
||||
private class IWapPushManagerStub extends IWapPushManager.Stub {
|
||||
public Context mContext;
|
||||
|
||||
public IWapPushManagerStub() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the package signature with WapPushManager package
|
||||
*/
|
||||
protected boolean signatureCheck(String package_name) {
|
||||
PackageManager pm = mContext.getPackageManager();
|
||||
int match = pm.checkSignatures(mContext.getPackageName(), package_name);
|
||||
|
||||
if (LOCAL_LOGV) Log.v(LOG_TAG, "compare signature " + mContext.getPackageName()
|
||||
+ " and " + package_name + ", match=" + match);
|
||||
|
||||
return match == PackageManager.SIGNATURE_MATCH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the status value of the message processing.
|
||||
* The message will be processed as follows:
|
||||
* 1.Look up Application ID Table with x-wap-application-id + content type
|
||||
* 2.Check the signature of package name that is found in the
|
||||
* Application ID Table by using PackageManager.checkSignature
|
||||
* 3.Trigger the Application
|
||||
* 4.Returns the process status value.
|
||||
*/
|
||||
public int processMessage(String app_id, String content_type, Intent intent)
|
||||
throws RemoteException {
|
||||
Log.d(LOG_TAG, "wpman processMsg " + app_id + ":" + content_type);
|
||||
|
||||
WapPushManDBHelper dbh = getDatabase(mContext);
|
||||
SQLiteDatabase db = dbh.getReadableDatabase();
|
||||
WapPushManDBHelper.queryData lastapp = dbh.queryLastApp(db, app_id, content_type);
|
||||
db.close();
|
||||
|
||||
if (lastapp == null) {
|
||||
Log.w(LOG_TAG, "no receiver app found for " + app_id + ":" + content_type);
|
||||
return WapPushManagerParams.APP_QUERY_FAILED;
|
||||
}
|
||||
if (LOCAL_LOGV) Log.v(LOG_TAG, "starting " + lastapp.packageName
|
||||
+ "/" + lastapp.className);
|
||||
|
||||
if (lastapp.needSignature != 0) {
|
||||
if (!signatureCheck(lastapp.packageName)) {
|
||||
return WapPushManagerParams.SIGNATURE_NO_MATCH;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastapp.appType == WapPushManagerParams.APP_TYPE_ACTIVITY) {
|
||||
//Intent intent = new Intent(Intent.ACTION_MAIN);
|
||||
intent.setClassName(lastapp.packageName, lastapp.className);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
try {
|
||||
mContext.startActivity(intent);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Log.w(LOG_TAG, "invalid name " +
|
||||
lastapp.packageName + "/" + lastapp.className);
|
||||
return WapPushManagerParams.INVALID_RECEIVER_NAME;
|
||||
}
|
||||
} else {
|
||||
intent.setClassName(mContext, lastapp.className);
|
||||
intent.setComponent(new ComponentName(lastapp.packageName,
|
||||
lastapp.className));
|
||||
if (mContext.startService(intent) == null) {
|
||||
Log.w(LOG_TAG, "invalid name " +
|
||||
lastapp.packageName + "/" + lastapp.className);
|
||||
return WapPushManagerParams.INVALID_RECEIVER_NAME;
|
||||
}
|
||||
}
|
||||
|
||||
return WapPushManagerParams.MESSAGE_HANDLED
|
||||
| (lastapp.furtherProcessing == 1 ?
|
||||
WapPushManagerParams.FURTHER_PROCESSING : 0);
|
||||
}
|
||||
|
||||
protected boolean appTypeCheck(int app_type) {
|
||||
if (app_type == WapPushManagerParams.APP_TYPE_ACTIVITY ||
|
||||
app_type == WapPushManagerParams.APP_TYPE_SERVICE) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if adding the package succeeded.
|
||||
*/
|
||||
public boolean addPackage(String x_app_id, String content_type,
|
||||
String package_name, String class_name,
|
||||
int app_type, boolean need_signature, boolean further_processing) {
|
||||
WapPushManDBHelper dbh = getDatabase(mContext);
|
||||
SQLiteDatabase db = dbh.getWritableDatabase();
|
||||
WapPushManDBHelper.queryData lastapp = dbh.queryLastApp(db, x_app_id, content_type);
|
||||
boolean ret = false;
|
||||
boolean insert = false;
|
||||
int sq = 0;
|
||||
|
||||
if (!appTypeCheck(app_type)) {
|
||||
Log.w(LOG_TAG, "invalid app_type " + app_type + ". app_type must be "
|
||||
+ WapPushManagerParams.APP_TYPE_ACTIVITY + " or "
|
||||
+ WapPushManagerParams.APP_TYPE_SERVICE);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (lastapp == null) {
|
||||
insert = true;
|
||||
sq = 0;
|
||||
} else if (!lastapp.packageName.equals(package_name) ||
|
||||
!lastapp.className.equals(class_name)) {
|
||||
insert = true;
|
||||
sq = lastapp.installOrder + 1;
|
||||
}
|
||||
|
||||
if (insert) {
|
||||
ContentValues values = new ContentValues();
|
||||
|
||||
values.put("x_wap_application", x_app_id);
|
||||
values.put("content_type", content_type);
|
||||
values.put("package_name", package_name);
|
||||
values.put("class_name", class_name);
|
||||
values.put("app_type", app_type);
|
||||
values.put("need_signature", need_signature ? 1 : 0);
|
||||
values.put("further_processing", further_processing ? 1 : 0);
|
||||
values.put("install_order", sq);
|
||||
db.insert(APPID_TABLE_NAME, null, values);
|
||||
if (LOCAL_LOGV) Log.v(LOG_TAG, "add:" + x_app_id + ":" + content_type
|
||||
+ " " + package_name + "." + class_name
|
||||
+ ", newsq:" + sq);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
db.close();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if updating the package succeeded.
|
||||
*/
|
||||
public boolean updatePackage(String x_app_id, String content_type,
|
||||
String package_name, String class_name,
|
||||
int app_type, boolean need_signature, boolean further_processing) {
|
||||
|
||||
if (!appTypeCheck(app_type)) {
|
||||
Log.w(LOG_TAG, "invalid app_type " + app_type + ". app_type must be "
|
||||
+ WapPushManagerParams.APP_TYPE_ACTIVITY + " or "
|
||||
+ WapPushManagerParams.APP_TYPE_SERVICE);
|
||||
return false;
|
||||
}
|
||||
|
||||
WapPushManDBHelper dbh = getDatabase(mContext);
|
||||
SQLiteDatabase db = dbh.getWritableDatabase();
|
||||
WapPushManDBHelper.queryData lastapp = dbh.queryLastApp(db, x_app_id, content_type);
|
||||
|
||||
if (lastapp == null) {
|
||||
db.close();
|
||||
return false;
|
||||
}
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
String where = "x_wap_application=\'" + x_app_id + "\'"
|
||||
+ " and content_type=\'" + content_type + "\'"
|
||||
+ " and install_order=" + lastapp.installOrder;
|
||||
|
||||
values.put("package_name", package_name);
|
||||
values.put("class_name", class_name);
|
||||
values.put("app_type", app_type);
|
||||
values.put("need_signature", need_signature ? 1 : 0);
|
||||
values.put("further_processing", further_processing ? 1 : 0);
|
||||
|
||||
int num = db.update(APPID_TABLE_NAME, values, where, null);
|
||||
if (LOCAL_LOGV) Log.v(LOG_TAG, "update:" + x_app_id + ":" + content_type + " "
|
||||
+ package_name + "." + class_name
|
||||
+ ", sq:" + lastapp.installOrder);
|
||||
|
||||
db.close();
|
||||
|
||||
return num > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if deleting the package succeeded.
|
||||
*/
|
||||
public boolean deletePackage(String x_app_id, String content_type,
|
||||
String package_name, String class_name) {
|
||||
WapPushManDBHelper dbh = getDatabase(mContext);
|
||||
SQLiteDatabase db = dbh.getWritableDatabase();
|
||||
String where = "x_wap_application=\'" + x_app_id + "\'"
|
||||
+ " and content_type=\'" + content_type + "\'"
|
||||
+ " and package_name=\'" + package_name + "\'"
|
||||
+ " and class_name=\'" + class_name + "\'";
|
||||
int num_removed = db.delete(APPID_TABLE_NAME, where, null);
|
||||
|
||||
db.close();
|
||||
if (LOCAL_LOGV) Log.v(LOG_TAG, "deleted " + num_removed + " rows:"
|
||||
+ x_app_id + ":" + content_type + " "
|
||||
+ package_name + "." + class_name);
|
||||
return num_removed > 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Linux IPC Binder
|
||||
*/
|
||||
private final IWapPushManagerStub mBinder = new IWapPushManagerStub();
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public WapPushManager() {
|
||||
super();
|
||||
mBinder.mContext = this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent arg0) {
|
||||
return mBinder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Application ID database instance
|
||||
*/
|
||||
private WapPushManDBHelper mDbHelper = null;
|
||||
protected WapPushManDBHelper getDatabase(Context context) {
|
||||
if (mDbHelper == null) {
|
||||
if (LOCAL_LOGV) Log.v(LOG_TAG, "create new db inst.");
|
||||
mDbHelper = new WapPushManDBHelper(context);
|
||||
}
|
||||
return mDbHelper;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method is used for testing
|
||||
*/
|
||||
public boolean verifyData(String x_app_id, String content_type,
|
||||
String package_name, String class_name,
|
||||
int app_type, boolean need_signature, boolean further_processing) {
|
||||
WapPushManDBHelper dbh = getDatabase(this);
|
||||
SQLiteDatabase db = dbh.getReadableDatabase();
|
||||
WapPushManDBHelper.queryData lastapp = dbh.queryLastApp(db, x_app_id, content_type);
|
||||
|
||||
db.close();
|
||||
|
||||
if (lastapp == null) return false;
|
||||
|
||||
if (lastapp.packageName.equals(package_name)
|
||||
&& lastapp.className.equals(class_name)
|
||||
&& lastapp.appType == app_type
|
||||
&& lastapp.needSignature == (need_signature ? 1 : 0)
|
||||
&& lastapp.furtherProcessing == (further_processing ? 1 : 0)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used for testing
|
||||
*/
|
||||
public boolean isDataExist(String x_app_id, String content_type,
|
||||
String package_name, String class_name) {
|
||||
WapPushManDBHelper dbh = getDatabase(this);
|
||||
SQLiteDatabase db = dbh.getReadableDatabase();
|
||||
boolean ret = dbh.queryLastApp(db, x_app_id, content_type) != null;
|
||||
|
||||
db.close();
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
38
packages/WAPPushManager/tests/Android.mk
Normal file
38
packages/WAPPushManager/tests/Android.mk
Normal file
@@ -0,0 +1,38 @@
|
||||
# Copyright 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.
|
||||
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
# We only want this apk build for tests.
|
||||
LOCAL_MODULE_TAGS := tests
|
||||
|
||||
LOCAL_JAVA_LIBRARIES := android.test.runner
|
||||
|
||||
# Include all test java files.
|
||||
LOCAL_SRC_FILES := $(call all-java-files-under, src)
|
||||
LOCAL_SRC_FILES += \
|
||||
src/com/android/smspush/unitTests/IDataVerify.aidl
|
||||
|
||||
|
||||
# Notice that we don't have to include the src files of Email because, by
|
||||
# running the tests using an instrumentation targeting Eamil, we
|
||||
# automatically get all of its classes loaded into our environment.
|
||||
|
||||
LOCAL_PACKAGE_NAME := WAPPushManagerTests
|
||||
|
||||
LOCAL_INSTRUMENTATION_FOR := WAPPushManager
|
||||
|
||||
include $(BUILD_PACKAGE)
|
||||
|
||||
71
packages/WAPPushManager/tests/AndroidManifest.xml
Normal file
71
packages/WAPPushManager/tests/AndroidManifest.xml
Normal file
@@ -0,0 +1,71 @@
|
||||
<?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.
|
||||
|
||||
-->
|
||||
|
||||
<!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.smspush.unitTests">
|
||||
|
||||
|
||||
<uses-permission android:name="com.android.smspush.WAPPUSH_MANAGER_BIND" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_WAP_PUSH" />
|
||||
<!--testing.../-->
|
||||
<application android:icon="@drawable/icon" android:label="wappush test">
|
||||
<uses-library android:name="android.test.runner" />
|
||||
<activity android:name=".ClientTest"
|
||||
android:label="wappush test">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<receiver android:name=".DrmReceiver" android:enabled="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" />
|
||||
<data android:mimeType="application/vnd.oma.drm.rights+xml" />
|
||||
<data android:value="application/vnd.oma.drm.rights+wbxml" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<service android:enabled="true" android:name=".ReceiverService"
|
||||
android:exported="true"/>
|
||||
|
||||
<activity android:name=".ReceiverActivity"
|
||||
android:exported="true" android:label="test receiver" />
|
||||
|
||||
<service android:name=".DataVerify"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.android.smspush.unitTests.IDataVerify" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
</application>
|
||||
|
||||
<!--
|
||||
This declares that this application uses the instrumentation test runner targeting
|
||||
the package of com.android.smspush. To run the tests use the command:
|
||||
"adb shell am instrument -w
|
||||
com.android.smspush.unitTests/android.test.InstrumentationTestRunner"
|
||||
-->
|
||||
<instrumentation android:name="android.test.InstrumentationTestRunner"
|
||||
android:targetPackage="com.android.smspush"
|
||||
android:label="Tests for WAPPushManager"/>
|
||||
|
||||
</manifest>
|
||||
|
||||
BIN
packages/WAPPushManager/tests/res/drawable-hdpi/icon.png
Normal file
BIN
packages/WAPPushManager/tests/res/drawable-hdpi/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
BIN
packages/WAPPushManager/tests/res/drawable-ldpi/icon.png
Normal file
BIN
packages/WAPPushManager/tests/res/drawable-ldpi/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
BIN
packages/WAPPushManager/tests/res/drawable-mdpi/icon.png
Normal file
BIN
packages/WAPPushManager/tests/res/drawable-mdpi/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
152
packages/WAPPushManager/tests/res/layout/main.xml
Normal file
152
packages/WAPPushManager/tests/res/layout/main.xml
Normal file
@@ -0,0 +1,152 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2010 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.
|
||||
-->
|
||||
<AbsoluteLayout
|
||||
android:id="@+id/widget133"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
>
|
||||
<EditText
|
||||
android:id="@+id/app_id"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="10"
|
||||
android:textSize="18sp"
|
||||
android:layout_x="0px"
|
||||
android:layout_y="26px"
|
||||
>
|
||||
</EditText>
|
||||
<EditText
|
||||
android:id="@+id/cont"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="20"
|
||||
android:textSize="18sp"
|
||||
android:layout_x="47px"
|
||||
android:layout_y="26px"
|
||||
>
|
||||
</EditText>
|
||||
<EditText
|
||||
android:id="@+id/pkg"
|
||||
android:layout_width="125px"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="pkg"
|
||||
android:textSize="18sp"
|
||||
android:layout_x="0px"
|
||||
android:layout_y="81px"
|
||||
>
|
||||
</EditText>
|
||||
<EditText
|
||||
android:id="@+id/cls"
|
||||
android:layout_width="173px"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="cls"
|
||||
android:textSize="18sp"
|
||||
android:layout_x="147px"
|
||||
android:layout_y="81px"
|
||||
>
|
||||
</EditText>
|
||||
<Button
|
||||
android:id="@+id/addpkg"
|
||||
android:layout_width="182px"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="add/update package"
|
||||
android:layout_x="15px"
|
||||
android:layout_y="225px"
|
||||
>
|
||||
</Button>
|
||||
<TextView
|
||||
android:id="@+id/widget52"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="input app_id, cont_type, pkg, cls"
|
||||
android:textSize="18sp"
|
||||
android:layout_x="0px"
|
||||
android:layout_y="0px"
|
||||
>
|
||||
</TextView>
|
||||
<Button
|
||||
android:id="@+id/procmsg"
|
||||
android:layout_width="109px"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="process msg"
|
||||
android:layout_x="197px"
|
||||
android:layout_y="361px"
|
||||
>
|
||||
</Button>
|
||||
<RadioGroup
|
||||
android:id="@+id/widget137"
|
||||
android:layout_width="83px"
|
||||
android:layout_height="80px"
|
||||
android:orientation="vertical"
|
||||
android:layout_x="19px"
|
||||
android:layout_y="137px"
|
||||
>
|
||||
<RadioButton
|
||||
android:id="@+id/act"
|
||||
android:layout_width="182px"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="act"
|
||||
android:checked="true"
|
||||
>
|
||||
</RadioButton>
|
||||
<RadioButton
|
||||
android:id="@+id/svc"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="svc"
|
||||
>
|
||||
</RadioButton>
|
||||
</RadioGroup>
|
||||
<Button
|
||||
android:id="@+id/delpkg"
|
||||
android:layout_width="174px"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="delete pkg"
|
||||
android:layout_x="14px"
|
||||
android:layout_y="283px"
|
||||
>
|
||||
</Button>
|
||||
<EditText
|
||||
android:id="@+id/pdu"
|
||||
android:layout_width="186px"
|
||||
android:layout_height="83px"
|
||||
android:text="0006080302030aaf02905c030d6a0085070373616d706c6540646f636f6d6f2e6e652e6a700005c3072009102012345601"
|
||||
android:textSize="18sp"
|
||||
android:layout_x="10px"
|
||||
android:layout_y="341px"
|
||||
>
|
||||
</EditText>
|
||||
<CheckBox
|
||||
android:id="@+id/ftr"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="ftr_proc"
|
||||
android:layout_x="143px"
|
||||
android:layout_y="181px"
|
||||
>
|
||||
</CheckBox>
|
||||
<CheckBox
|
||||
android:id="@+id/sig"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="nd_sig"
|
||||
android:checked="true"
|
||||
android:layout_x="142px"
|
||||
android:layout_y="140px"
|
||||
>
|
||||
</CheckBox>
|
||||
</AbsoluteLayout>
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.smspush.unitTests;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.RadioButton;
|
||||
|
||||
import com.android.internal.telephony.IWapPushManager;
|
||||
import com.android.internal.telephony.WapPushManagerParams;
|
||||
import com.android.internal.telephony.WapPushOverSms;
|
||||
import com.android.internal.util.HexDump;
|
||||
import com.android.smspush.WapPushManager;
|
||||
|
||||
/**
|
||||
* WapPushManager test application
|
||||
*/
|
||||
public class ClientTest extends Activity {
|
||||
private static final String LOG_TAG = "WAP PUSH";
|
||||
|
||||
/** Called when the activity is first created. */
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.main);
|
||||
|
||||
Button addpbtn = (Button) findViewById(R.id.addpkg);
|
||||
Button procbtn = (Button) findViewById(R.id.procmsg);
|
||||
Button delbtn = (Button) findViewById(R.id.delpkg);
|
||||
|
||||
Log.v(LOG_TAG, "activity created!!");
|
||||
|
||||
addpbtn.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
EditText app_id = (EditText) findViewById(R.id.app_id);
|
||||
EditText cont = (EditText) findViewById(R.id.cont);
|
||||
EditText pkg = (EditText) findViewById(R.id.pkg);
|
||||
EditText cls = (EditText) findViewById(R.id.cls);
|
||||
RadioButton act = (RadioButton) findViewById(R.id.act);
|
||||
CheckBox sig = (CheckBox) findViewById(R.id.sig);
|
||||
CheckBox ftr = (CheckBox) findViewById(R.id.ftr);
|
||||
|
||||
try {
|
||||
if (!mWapPushMan.addPackage(
|
||||
app_id.getText().toString(),
|
||||
cont.getText().toString(),
|
||||
pkg.getText().toString(),
|
||||
cls.getText().toString(),
|
||||
act.isChecked() ? WapPushManagerParams.APP_TYPE_ACTIVITY :
|
||||
WapPushManagerParams.APP_TYPE_SERVICE,
|
||||
sig.isChecked(), ftr.isChecked())) {
|
||||
|
||||
Log.w(LOG_TAG, "remote add pkg failed...");
|
||||
mWapPushMan.updatePackage(
|
||||
app_id.getText().toString(),
|
||||
cont.getText().toString(),
|
||||
pkg.getText().toString(),
|
||||
cls.getText().toString(),
|
||||
act.isChecked() ? WapPushManagerParams.APP_TYPE_ACTIVITY :
|
||||
WapPushManagerParams.APP_TYPE_SERVICE,
|
||||
sig.isChecked(), ftr.isChecked());
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.w(LOG_TAG, "remote func failed...");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
delbtn.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
EditText app_id = (EditText) findViewById(R.id.app_id);
|
||||
EditText cont = (EditText) findViewById(R.id.cont);
|
||||
EditText pkg = (EditText) findViewById(R.id.pkg);
|
||||
EditText cls = (EditText) findViewById(R.id.cls);
|
||||
// CheckBox delall = (CheckBox) findViewById(R.id.delall);
|
||||
// Log.d(LOG_TAG, "button clicked");
|
||||
|
||||
try {
|
||||
mWapPushMan.deletePackage(
|
||||
app_id.getText().toString(),
|
||||
cont.getText().toString(),
|
||||
pkg.getText().toString(),
|
||||
cls.getText().toString());
|
||||
// delall.isChecked());
|
||||
} catch (RemoteException e) {
|
||||
Log.w(LOG_TAG, "remote func failed...");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
procbtn.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
EditText pdu = (EditText) findViewById(R.id.pdu);
|
||||
EditText app_id = (EditText) findViewById(R.id.app_id);
|
||||
EditText cont = (EditText) findViewById(R.id.cont);
|
||||
|
||||
// WapPushOverSms wap = new WapPushOverSms();
|
||||
// wap.dispatchWapPdu(strToHex(pdu.getText().toString()));
|
||||
try {
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("transactionId", 0);
|
||||
intent.putExtra("pduType", 6);
|
||||
intent.putExtra("header",
|
||||
HexDump.hexStringToByteArray(pdu.getText().toString()));
|
||||
intent.putExtra("data",
|
||||
HexDump.hexStringToByteArray(pdu.getText().toString()));
|
||||
|
||||
mWapPushMan.processMessage(
|
||||
app_id.getText().toString(),
|
||||
cont.getText().toString(),
|
||||
intent);
|
||||
//HexDump.hexStringToByteArray(pdu.getText().toString()), 0, 6, 5, 5);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(LOG_TAG, "remote func failed...");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private IWapPushManager mWapPushMan;
|
||||
private ServiceConnection conn = new ServiceConnection() {
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
mWapPushMan = null;
|
||||
Log.v(LOG_TAG, "service disconnected.");
|
||||
}
|
||||
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
mWapPushMan = IWapPushManager.Stub.asInterface(service);
|
||||
Log.v(LOG_TAG, "service connected.");
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
Log.v(LOG_TAG, "onStart bind WAPPushManager service "
|
||||
+ IWapPushManager.class.getName());
|
||||
this.bindService(new Intent(IWapPushManager.class.getName()), conn,
|
||||
Context.BIND_AUTO_CREATE);
|
||||
Log.v(LOG_TAG, "bind service done.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
this.unbindService(conn);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.smspush.unitTests;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.util.HexDump;
|
||||
|
||||
/**
|
||||
* To verify that receiver application receives correct body data.
|
||||
*/
|
||||
public class DataVerify extends Service {
|
||||
private static final String LOG_TAG = "WAP PUSH";
|
||||
private static final int TIME_WAIT = 100;
|
||||
private static final int WAIT_COUNT = 100;
|
||||
private static byte[] mLastReceivedPdu = null;
|
||||
private static boolean sDataSet = false;
|
||||
|
||||
private class IDataVerifyStub extends IDataVerify.Stub {
|
||||
public Context mContext;
|
||||
|
||||
public IDataVerifyStub() {
|
||||
}
|
||||
|
||||
boolean arrayCompare(byte[] arr1, byte[] arr2) {
|
||||
int i;
|
||||
|
||||
if (arr1 == null || arr2 == null) {
|
||||
if (arr1 == null) {
|
||||
Log.w(LOG_TAG, "arr1 is null");
|
||||
} else {
|
||||
Log.w(LOG_TAG, "arr2 is null");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (arr1.length != arr2.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < arr1.length; i++) {
|
||||
if (arr1[i] != arr2[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare pdu and received pdu
|
||||
*/
|
||||
public synchronized boolean verifyData(byte[] pdu) {
|
||||
int cnt = 0;
|
||||
|
||||
while (!sDataSet) {
|
||||
// wait for the activity receive data.
|
||||
try {
|
||||
Thread.sleep(TIME_WAIT);
|
||||
if (cnt++ > WAIT_COUNT) {
|
||||
// don't wait more than 10 sec.
|
||||
return false;
|
||||
}
|
||||
} catch (InterruptedException e) {}
|
||||
}
|
||||
|
||||
Log.v(LOG_TAG, "verify pdu");
|
||||
boolean ret = arrayCompare(pdu, mLastReceivedPdu);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the old data. This method must be called before starting the test
|
||||
*/
|
||||
public void resetData() {
|
||||
mLastReceivedPdu = null;
|
||||
sDataSet = false;
|
||||
}
|
||||
}
|
||||
|
||||
private final IDataVerifyStub binder = new IDataVerifyStub();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public DataVerify() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Receiver application must call this method when it receives the wap push message
|
||||
*/
|
||||
public static void SetLastReceivedPdu(byte[] pdu) {
|
||||
mLastReceivedPdu = pdu;
|
||||
sDataSet = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent arg0) {
|
||||
return binder;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.smspush.unitTests;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.util.HexDump;
|
||||
|
||||
/**
|
||||
* A sample wap push receiver application for existing framework
|
||||
* This class is listening for "application/vnd.oma.drm.rights+xml" message
|
||||
*/
|
||||
public class DrmReceiver extends BroadcastReceiver {
|
||||
private static final String LOG_TAG = "WAP PUSH";
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Log.d(LOG_TAG, "DrmReceiver received.");
|
||||
|
||||
byte[] body;
|
||||
byte[] header;
|
||||
|
||||
body = intent.getByteArrayExtra("data");
|
||||
header = intent.getByteArrayExtra("header");
|
||||
|
||||
Log.d(LOG_TAG, "header:");
|
||||
Log.d(LOG_TAG, HexDump.dumpHexString(header));
|
||||
Log.d(LOG_TAG, "body:");
|
||||
Log.d(LOG_TAG, HexDump.dumpHexString(body));
|
||||
|
||||
DataVerify.SetLastReceivedPdu(body);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.smspush.unitTests;
|
||||
|
||||
/**
|
||||
* Interface to receiver application data verifyer class
|
||||
*/
|
||||
interface IDataVerify {
|
||||
/**
|
||||
* Verify data
|
||||
*/
|
||||
boolean verifyData(in byte[] pdu);
|
||||
|
||||
/**
|
||||
* Initialize data
|
||||
*/
|
||||
void resetData();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.smspush.unitTests;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.util.HexDump;
|
||||
|
||||
/**
|
||||
* Activity type receiver application
|
||||
*/
|
||||
public class ReceiverActivity extends Activity {
|
||||
private static final String LOG_TAG = "WAP PUSH";
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
Log.d(LOG_TAG, "activity created!!");
|
||||
|
||||
Intent in = getIntent();
|
||||
byte[] body;
|
||||
byte[] header;
|
||||
|
||||
body = in.getByteArrayExtra("data");
|
||||
header = in.getByteArrayExtra("header");
|
||||
|
||||
Log.d(LOG_TAG, "header:");
|
||||
Log.d(LOG_TAG, HexDump.dumpHexString(header));
|
||||
Log.d(LOG_TAG, "body:");
|
||||
Log.d(LOG_TAG, HexDump.dumpHexString(body));
|
||||
|
||||
DataVerify.SetLastReceivedPdu(body);
|
||||
|
||||
finish();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.smspush.unitTests;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.util.HexDump;
|
||||
|
||||
/**
|
||||
* Service type receiver application
|
||||
*/
|
||||
public class ReceiverService extends Service {
|
||||
private static final String LOG_TAG = "WAP PUSH";
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
Log.d(LOG_TAG, "Receiver service created");
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
Log.d(LOG_TAG, "Receiver service started");
|
||||
|
||||
byte[] body;
|
||||
byte[] header;
|
||||
body = intent.getByteArrayExtra("data");
|
||||
header = intent.getByteArrayExtra("header");
|
||||
|
||||
Log.d(LOG_TAG, "header:");
|
||||
Log.d(LOG_TAG, HexDump.dumpHexString(header));
|
||||
Log.d(LOG_TAG, "body:");
|
||||
Log.d(LOG_TAG, HexDump.dumpHexString(body));
|
||||
|
||||
DataVerify.SetLastReceivedPdu(body);
|
||||
return START_STICKY;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.internal.telephony;
|
||||
|
||||
import android.content.Intent;
|
||||
|
||||
interface IWapPushManager {
|
||||
/**
|
||||
* Processes WAP push message and triggers the receiver application registered
|
||||
* in the application ID table.
|
||||
*/
|
||||
int processMessage(String app_id, String content_type, in Intent intent);
|
||||
|
||||
/**
|
||||
* Add receiver application into the application ID table.
|
||||
* Returns true if inserting the information is successfull. Inserting the duplicated
|
||||
* record in the application ID table is not allowed. Use update/delete method.
|
||||
*/
|
||||
boolean addPackage(String x_app_id, String content_type,
|
||||
String package_name, String class_name,
|
||||
int app_type, boolean need_signature, boolean further_processing);
|
||||
|
||||
/**
|
||||
* Updates receiver application that is last added.
|
||||
* Returns true if updating the information is successfull.
|
||||
*/
|
||||
boolean updatePackage(String x_app_id, String content_type,
|
||||
String package_name, String class_name,
|
||||
int app_type, boolean need_signature, boolean further_processing);
|
||||
|
||||
/**
|
||||
* Delites receiver application information.
|
||||
* Returns true if deleting is successfull.
|
||||
*/
|
||||
boolean deletePackage(String x_app_id, String content_type,
|
||||
String package_name, String class_name);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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.internal.telephony;
|
||||
|
||||
/**
|
||||
* WapPushManager constant value definitions
|
||||
*/
|
||||
public class WapPushManagerParams {
|
||||
/**
|
||||
* Application type activity
|
||||
*/
|
||||
public static final int APP_TYPE_ACTIVITY = 0;
|
||||
|
||||
/**
|
||||
* Application type service
|
||||
*/
|
||||
public static final int APP_TYPE_SERVICE = 1;
|
||||
|
||||
/**
|
||||
* Process Message return value
|
||||
* Message is handled
|
||||
*/
|
||||
public static final int MESSAGE_HANDLED = 0x1;
|
||||
|
||||
/**
|
||||
* Process Message return value
|
||||
* Application ID or content type was not found in the application ID table
|
||||
*/
|
||||
public static final int APP_QUERY_FAILED = 0x2;
|
||||
|
||||
/**
|
||||
* Process Message return value
|
||||
* Receiver application signature check failed
|
||||
*/
|
||||
public static final int SIGNATURE_NO_MATCH = 0x4;
|
||||
|
||||
/**
|
||||
* Process Message return value
|
||||
* Receiver application was not found
|
||||
*/
|
||||
public static final int INVALID_RECEIVER_NAME = 0x8;
|
||||
|
||||
/**
|
||||
* Process Message return value
|
||||
* Unknown exception
|
||||
*/
|
||||
public static final int EXCEPTION_CAUGHT = 0x10;
|
||||
|
||||
/**
|
||||
* Process Message return value
|
||||
* Need further processing after WapPushManager message processing
|
||||
*/
|
||||
public static final int FURTHER_PROCESSING = 0x8000;
|
||||
|
||||
}
|
||||
|
||||
@@ -14,15 +14,20 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package com.android.internal.telephony;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.provider.Telephony;
|
||||
import android.provider.Telephony.Sms.Intents;
|
||||
import android.util.Config;
|
||||
import android.util.Log;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
|
||||
/**
|
||||
* WAP push handler class.
|
||||
@@ -42,11 +47,83 @@ public class WapPushOverSms {
|
||||
*/
|
||||
private final int WAKE_LOCK_TIMEOUT = 5000;
|
||||
|
||||
private final int BIND_RETRY_INTERVAL = 1000;
|
||||
/**
|
||||
* A handle to WapPushManager interface
|
||||
*/
|
||||
private WapPushConnection mWapConn = null;
|
||||
private class WapPushConnection implements ServiceConnection {
|
||||
private IWapPushManager mWapPushMan;
|
||||
private Context mOwner;
|
||||
|
||||
public WapPushConnection(Context ownerContext) {
|
||||
mOwner = ownerContext;
|
||||
}
|
||||
|
||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||
mWapPushMan = IWapPushManager.Stub.asInterface(service);
|
||||
if (Config.DEBUG) Log.v(LOG_TAG, "wappush manager connected to " +
|
||||
mOwner.hashCode());
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
mWapPushMan = null;
|
||||
if (Config.DEBUG) Log.v(LOG_TAG, "wappush manager disconnected.");
|
||||
// WapPushManager must be always attached.
|
||||
rebindWapPushManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* bind WapPushManager
|
||||
*/
|
||||
public void bindWapPushManager() {
|
||||
if (mWapPushMan != null) return;
|
||||
|
||||
final ServiceConnection wapPushConnection = this;
|
||||
|
||||
mOwner.bindService(new Intent(IWapPushManager.class.getName()),
|
||||
wapPushConnection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* rebind WapPushManager
|
||||
* This method is called when WapPushManager is disconnected unexpectedly.
|
||||
*/
|
||||
private void rebindWapPushManager() {
|
||||
if (mWapPushMan != null) return;
|
||||
|
||||
final ServiceConnection wapPushConnection = this;
|
||||
new Thread() {
|
||||
public void run() {
|
||||
while (mWapPushMan == null) {
|
||||
mOwner.bindService(new Intent(IWapPushManager.class.getName()),
|
||||
wapPushConnection, Context.BIND_AUTO_CREATE);
|
||||
try {
|
||||
Thread.sleep(BIND_RETRY_INTERVAL);
|
||||
} catch (InterruptedException e) {
|
||||
if (Config.DEBUG) Log.v(LOG_TAG, "sleep interrupted.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns interface to WapPushManager
|
||||
*/
|
||||
public IWapPushManager getWapPushManager() {
|
||||
return mWapPushMan;
|
||||
}
|
||||
}
|
||||
|
||||
public WapPushOverSms(Phone phone, SMSDispatcher smsDispatcher) {
|
||||
mSmsDispatcher = smsDispatcher;
|
||||
mContext = phone.getContext();
|
||||
mWapConn = new WapPushConnection(mContext);
|
||||
mWapConn.bindWapPushManager();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Dispatches inbound messages that are in the WAP PDU format. See
|
||||
* wap-230-wsp-20010705-a section 8 for details on the WAP PDU format.
|
||||
@@ -106,16 +183,15 @@ public class WapPushOverSms {
|
||||
}
|
||||
|
||||
String mimeType = pduDecoder.getValueString();
|
||||
|
||||
long binaryContentType = pduDecoder.getValue32();
|
||||
index += pduDecoder.getDecodedDataLength();
|
||||
|
||||
byte[] header = new byte[headerLength];
|
||||
System.arraycopy(pdu, headerStartIndex, header, 0, header.length);
|
||||
|
||||
byte[] intentData;
|
||||
String permission;
|
||||
|
||||
if (mimeType.equals(WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO)) {
|
||||
if (mimeType != null && mimeType.equals(WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO)) {
|
||||
intentData = pdu;
|
||||
} else {
|
||||
int dataIndex = headerStartIndex + headerLength;
|
||||
@@ -123,6 +199,62 @@ public class WapPushOverSms {
|
||||
System.arraycopy(pdu, dataIndex, intentData, 0, intentData.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Seek for application ID field in WSP header.
|
||||
* If application ID is found, WapPushManager substitute the message
|
||||
* processing. Since WapPushManager is optional module, if WapPushManager
|
||||
* is not found, legacy message processing will be continued.
|
||||
*/
|
||||
if (pduDecoder.seekXWapApplicationId(index, index + headerLength - 1)) {
|
||||
index = (int) pduDecoder.getValue32();
|
||||
pduDecoder.decodeXWapApplicationId(index);
|
||||
String wapAppId = pduDecoder.getValueString();
|
||||
if (wapAppId == null) {
|
||||
wapAppId = Integer.toString((int) pduDecoder.getValue32());
|
||||
}
|
||||
|
||||
String contentType = ((mimeType == null) ?
|
||||
Long.toString(binaryContentType) : mimeType);
|
||||
if (Config.DEBUG) Log.v(LOG_TAG, "appid found: " + wapAppId + ":" + contentType);
|
||||
|
||||
try {
|
||||
boolean processFurther = true;
|
||||
IWapPushManager wapPushMan = mWapConn.getWapPushManager();
|
||||
|
||||
if (wapPushMan == null) {
|
||||
if (Config.DEBUG) Log.w(LOG_TAG, "wap push manager not found!");
|
||||
} else {
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra("transactionId", transactionId);
|
||||
intent.putExtra("pduType", pduType);
|
||||
intent.putExtra("header", header);
|
||||
intent.putExtra("data", intentData);
|
||||
intent.putExtra("contentTypeParameters",
|
||||
pduDecoder.getContentParameters());
|
||||
|
||||
int procRet = wapPushMan.processMessage(wapAppId, contentType, intent);
|
||||
if (Config.DEBUG) Log.v(LOG_TAG, "procRet:" + procRet);
|
||||
if ((procRet & WapPushManagerParams.MESSAGE_HANDLED) > 0
|
||||
&& (procRet & WapPushManagerParams.FURTHER_PROCESSING) == 0) {
|
||||
processFurther = false;
|
||||
}
|
||||
}
|
||||
if (!processFurther) {
|
||||
return Intents.RESULT_SMS_HANDLED;
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
if (Config.DEBUG) Log.w(LOG_TAG, "remote func failed...");
|
||||
}
|
||||
}
|
||||
if (Config.DEBUG) Log.v(LOG_TAG, "fall back to existing handler");
|
||||
|
||||
if (mimeType == null) {
|
||||
if (Config.DEBUG) Log.w(LOG_TAG, "Header Content-Type error.");
|
||||
return Intents.RESULT_SMS_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
String permission;
|
||||
|
||||
if (mimeType.equals(WspTypeDecoder.CONTENT_TYPE_B_MMS)) {
|
||||
permission = "android.permission.RECEIVE_MMS";
|
||||
} else {
|
||||
@@ -141,4 +273,4 @@ public class WapPushOverSms {
|
||||
|
||||
return Activity.RESULT_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@ public class WspTypeDecoder {
|
||||
private final static HashMap<Integer, String> WELL_KNOWN_PARAMETERS =
|
||||
new HashMap<Integer, String>();
|
||||
|
||||
public static final int PARAMETER_ID_X_WAP_APPLICATION_ID = 0x2f;
|
||||
private static final int Q_VALUE = 0x00;
|
||||
|
||||
static {
|
||||
@@ -602,6 +603,70 @@ public class WspTypeDecoder {
|
||||
return decodeTextString(startIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Seek for the "X-Wap-Application-Id" field for WSP pdu
|
||||
*
|
||||
* @param startIndex The starting position of seek pointer
|
||||
* @param endIndex Valid seek area end point
|
||||
*
|
||||
* @return false when error(not a X-Wap-Application-Id) occur
|
||||
* return value can be retrieved by getValue32()
|
||||
*/
|
||||
public boolean seekXWapApplicationId(int startIndex, int endIndex) {
|
||||
int index = startIndex;
|
||||
|
||||
try {
|
||||
for (index = startIndex; index <= endIndex; ) {
|
||||
/**
|
||||
* 8.4.1.1 Field name
|
||||
* Field name is integer or text.
|
||||
*/
|
||||
if (decodeIntegerValue(index)) {
|
||||
int fieldValue = (int) getValue32();
|
||||
|
||||
if (fieldValue == PARAMETER_ID_X_WAP_APPLICATION_ID) {
|
||||
unsigned32bit = index + 1;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (!decodeTextString(index)) return false;
|
||||
}
|
||||
index += getDecodedDataLength();
|
||||
if (index > endIndex) return false;
|
||||
|
||||
/**
|
||||
* 8.4.1.2 Field values
|
||||
* Value Interpretation of First Octet
|
||||
* 0 - 30 This octet is followed by the indicated number (0 - 30)
|
||||
of data octets
|
||||
* 31 This octet is followed by a uintvar, which indicates the number
|
||||
* of data octets after it
|
||||
* 32 - 127 The value is a text string, terminated by a zero octet
|
||||
(NUL character)
|
||||
* 128 - 255 It is an encoded 7-bit value; this header has no more data
|
||||
*/
|
||||
byte val = wspData[index];
|
||||
if (0 <= val && val <= WAP_PDU_SHORT_LENGTH_MAX) {
|
||||
index += wspData[index] + 1;
|
||||
} else if (val == WAP_PDU_LENGTH_QUOTE) {
|
||||
if (index + 1 >= endIndex) return false;
|
||||
index++;
|
||||
if (!decodeUintvarInteger(index)) return false;
|
||||
index += getDecodedDataLength();
|
||||
} else if (WAP_PDU_LENGTH_QUOTE < val && val <= 127) {
|
||||
if (!decodeTextString(index)) return false;
|
||||
index += getDecodedDataLength();
|
||||
} else {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
//seek application ID failed. WSP header might be corrupted
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the "X-Wap-Content-URI" type for WSP pdu
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user