gps: Network initiated SUPL
Initial contribution from Qualcomm. Signed-off-by: Mike Lockwood <lockwood@android.com>
This commit is contained in:
@@ -147,6 +147,7 @@ LOCAL_SRC_FILES += \
|
|||||||
location/java/android/location/ILocationListener.aidl \
|
location/java/android/location/ILocationListener.aidl \
|
||||||
location/java/android/location/ILocationManager.aidl \
|
location/java/android/location/ILocationManager.aidl \
|
||||||
location/java/android/location/ILocationProvider.aidl \
|
location/java/android/location/ILocationProvider.aidl \
|
||||||
|
location/java/android/location/INetInitiatedListener.aidl \
|
||||||
media/java/android/media/IAudioService.aidl \
|
media/java/android/media/IAudioService.aidl \
|
||||||
media/java/android/media/IMediaScannerListener.aidl \
|
media/java/android/media/IMediaScannerListener.aidl \
|
||||||
media/java/android/media/IMediaScannerService.aidl \
|
media/java/android/media/IMediaScannerService.aidl \
|
||||||
|
|||||||
139
core/java/com/android/internal/app/NetInitiatedActivity.java
Executable file
139
core/java/com/android/internal/app/NetInitiatedActivity.java
Executable file
@@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.internal.app;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.IMountService;
|
||||||
|
import android.os.Message;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.os.ServiceManager;
|
||||||
|
import android.widget.Toast;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.location.LocationManager;
|
||||||
|
import com.android.internal.location.GpsLocationProvider;
|
||||||
|
import com.android.internal.location.GpsNetInitiatedHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This activity is shown to the user for him/her to accept or deny network-initiated
|
||||||
|
* requests. It uses the alert dialog style. It will be launched from a notification.
|
||||||
|
*/
|
||||||
|
public class NetInitiatedActivity extends AlertActivity implements DialogInterface.OnClickListener {
|
||||||
|
|
||||||
|
private static final String TAG = "NetInitiatedActivity";
|
||||||
|
|
||||||
|
private static final boolean DEBUG = true;
|
||||||
|
private static final boolean VERBOSE = false;
|
||||||
|
|
||||||
|
private static final int POSITIVE_BUTTON = AlertDialog.BUTTON1;
|
||||||
|
private static final int NEGATIVE_BUTTON = AlertDialog.BUTTON2;
|
||||||
|
|
||||||
|
// Dialog button text
|
||||||
|
public static final String BUTTON_TEXT_ACCEPT = "Accept";
|
||||||
|
public static final String BUTTON_TEXT_DENY = "Deny";
|
||||||
|
|
||||||
|
// Received ID from intent, -1 when no notification is in progress
|
||||||
|
private int notificationId = -1;
|
||||||
|
|
||||||
|
/** Used to detect when NI request is received */
|
||||||
|
private BroadcastReceiver mNetInitiatedReceiver = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
if (DEBUG) Log.d(TAG, "NetInitiatedReceiver onReceive: " + intent.getAction());
|
||||||
|
if (intent.getAction() == GpsNetInitiatedHandler.ACTION_NI_VERIFY) {
|
||||||
|
handleNIVerify(intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
// Set up the "dialog"
|
||||||
|
final Intent intent = getIntent();
|
||||||
|
final AlertController.AlertParams p = mAlertParams;
|
||||||
|
p.mIconId = com.android.internal.R.drawable.ic_dialog_usb;
|
||||||
|
p.mTitle = intent.getStringExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_TITLE);
|
||||||
|
p.mMessage = intent.getStringExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_MESSAGE);
|
||||||
|
p.mPositiveButtonText = BUTTON_TEXT_ACCEPT;
|
||||||
|
p.mPositiveButtonListener = this;
|
||||||
|
p.mNegativeButtonText = BUTTON_TEXT_DENY;
|
||||||
|
p.mNegativeButtonListener = this;
|
||||||
|
|
||||||
|
notificationId = intent.getIntExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_NOTIF_ID, -1);
|
||||||
|
if (DEBUG) Log.d(TAG, "onCreate, notifId: " + notificationId);
|
||||||
|
|
||||||
|
setupAlert();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
if (DEBUG) Log.d(TAG, "onResume");
|
||||||
|
registerReceiver(mNetInitiatedReceiver, new IntentFilter(GpsNetInitiatedHandler.ACTION_NI_VERIFY));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPause() {
|
||||||
|
super.onPause();
|
||||||
|
if (DEBUG) Log.d(TAG, "onPause");
|
||||||
|
unregisterReceiver(mNetInitiatedReceiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
if (which == POSITIVE_BUTTON) {
|
||||||
|
sendUserResponse(GpsNetInitiatedHandler.GPS_NI_RESPONSE_ACCEPT);
|
||||||
|
}
|
||||||
|
if (which == NEGATIVE_BUTTON) {
|
||||||
|
sendUserResponse(GpsNetInitiatedHandler.GPS_NI_RESPONSE_DENY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// No matter what, finish the activity
|
||||||
|
finish();
|
||||||
|
notificationId = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Respond to NI Handler under GpsLocationProvider, 1 = accept, 2 = deny
|
||||||
|
private void sendUserResponse(int response) {
|
||||||
|
if (DEBUG) Log.d(TAG, "sendUserResponse, response: " + response);
|
||||||
|
LocationManager locationManager = (LocationManager)
|
||||||
|
this.getSystemService(Context.LOCATION_SERVICE);
|
||||||
|
locationManager.sendNiResponse(notificationId, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleNIVerify(Intent intent) {
|
||||||
|
int notifId = intent.getIntExtra(GpsNetInitiatedHandler.NI_INTENT_KEY_NOTIF_ID, -1);
|
||||||
|
notificationId = notifId;
|
||||||
|
|
||||||
|
if (DEBUG) Log.d(TAG, "handleNIVerify action: " + intent.getAction());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showNIError() {
|
||||||
|
Toast.makeText(this, "NI error" /* com.android.internal.R.string.usb_storage_error_message */,
|
||||||
|
Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,16 +16,18 @@
|
|||||||
|
|
||||||
#define LOG_TAG "GpsLocationProvider"
|
#define LOG_TAG "GpsLocationProvider"
|
||||||
|
|
||||||
|
//#define LOG_NDDEBUG 0
|
||||||
|
|
||||||
#include "JNIHelp.h"
|
#include "JNIHelp.h"
|
||||||
#include "jni.h"
|
#include "jni.h"
|
||||||
#include "hardware_legacy/gps.h"
|
#include "hardware_legacy/gps.h"
|
||||||
|
#include "hardware_legacy/gps_ni.h"
|
||||||
#include "utils/Log.h"
|
#include "utils/Log.h"
|
||||||
#include "utils/misc.h"
|
#include "utils/misc.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
|
|
||||||
static pthread_mutex_t sEventMutex = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t sEventMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
static pthread_cond_t sEventCond = PTHREAD_COND_INITIALIZER;
|
static pthread_cond_t sEventCond = PTHREAD_COND_INITIALIZER;
|
||||||
static jmethodID method_reportLocation;
|
static jmethodID method_reportLocation;
|
||||||
@@ -34,16 +36,19 @@ static jmethodID method_reportSvStatus;
|
|||||||
static jmethodID method_reportAGpsStatus;
|
static jmethodID method_reportAGpsStatus;
|
||||||
static jmethodID method_reportNmea;
|
static jmethodID method_reportNmea;
|
||||||
static jmethodID method_xtraDownloadRequest;
|
static jmethodID method_xtraDownloadRequest;
|
||||||
|
static jmethodID method_reportNiNotification;
|
||||||
|
|
||||||
static const GpsInterface* sGpsInterface = NULL;
|
static const GpsInterface* sGpsInterface = NULL;
|
||||||
static const GpsXtraInterface* sGpsXtraInterface = NULL;
|
static const GpsXtraInterface* sGpsXtraInterface = NULL;
|
||||||
static const AGpsInterface* sAGpsInterface = NULL;
|
static const AGpsInterface* sAGpsInterface = NULL;
|
||||||
|
static const GpsNiInterface* sGpsNiInterface = NULL;
|
||||||
|
|
||||||
// data written to by GPS callbacks
|
// data written to by GPS callbacks
|
||||||
static GpsLocation sGpsLocation;
|
static GpsLocation sGpsLocation;
|
||||||
static GpsStatus sGpsStatus;
|
static GpsStatus sGpsStatus;
|
||||||
static GpsSvStatus sGpsSvStatus;
|
static GpsSvStatus sGpsSvStatus;
|
||||||
static AGpsStatus sAGpsStatus;
|
static AGpsStatus sAGpsStatus;
|
||||||
|
static GpsNiNotification sGpsNiNotification;
|
||||||
|
|
||||||
// buffer for NMEA data
|
// buffer for NMEA data
|
||||||
#define NMEA_SENTENCE_LENGTH 100
|
#define NMEA_SENTENCE_LENGTH 100
|
||||||
@@ -62,6 +67,7 @@ static GpsStatus sGpsStatusCopy;
|
|||||||
static GpsSvStatus sGpsSvStatusCopy;
|
static GpsSvStatus sGpsSvStatusCopy;
|
||||||
static AGpsStatus sAGpsStatusCopy;
|
static AGpsStatus sAGpsStatusCopy;
|
||||||
static NmeaSentence sNmeaBufferCopy[NMEA_SENTENCE_LENGTH];
|
static NmeaSentence sNmeaBufferCopy[NMEA_SENTENCE_LENGTH];
|
||||||
|
static GpsNiNotification sGpsNiNotificationCopy;
|
||||||
|
|
||||||
enum CallbackType {
|
enum CallbackType {
|
||||||
kLocation = 1,
|
kLocation = 1,
|
||||||
@@ -71,6 +77,7 @@ enum CallbackType {
|
|||||||
kXtraDownloadRequest = 16,
|
kXtraDownloadRequest = 16,
|
||||||
kDisableRequest = 32,
|
kDisableRequest = 32,
|
||||||
kNmeaAvailable = 64,
|
kNmeaAvailable = 64,
|
||||||
|
kNiNotification = 128,
|
||||||
};
|
};
|
||||||
static int sPendingCallbacks;
|
static int sPendingCallbacks;
|
||||||
|
|
||||||
@@ -160,6 +167,20 @@ download_request_callback()
|
|||||||
pthread_mutex_unlock(&sEventMutex);
|
pthread_mutex_unlock(&sEventMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gps_ni_notify_callback(GpsNiNotification *notification)
|
||||||
|
{
|
||||||
|
LOGD("gps_ni_notify_callback: notif=%d", notification->notification_id);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&sEventMutex);
|
||||||
|
|
||||||
|
sPendingCallbacks |= kNiNotification;
|
||||||
|
memcpy(&sGpsNiNotification, notification, sizeof(GpsNiNotification));
|
||||||
|
|
||||||
|
pthread_cond_signal(&sEventCond);
|
||||||
|
pthread_mutex_unlock(&sEventMutex);
|
||||||
|
}
|
||||||
|
|
||||||
GpsXtraCallbacks sGpsXtraCallbacks = {
|
GpsXtraCallbacks sGpsXtraCallbacks = {
|
||||||
download_request_callback,
|
download_request_callback,
|
||||||
};
|
};
|
||||||
@@ -168,6 +189,10 @@ AGpsCallbacks sAGpsCallbacks = {
|
|||||||
agps_status_callback,
|
agps_status_callback,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GpsNiCallbacks sGpsNiCallbacks = {
|
||||||
|
gps_ni_notify_callback,
|
||||||
|
};
|
||||||
|
|
||||||
static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
|
static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
|
||||||
method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
|
method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)V");
|
||||||
method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
|
method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
|
||||||
@@ -175,6 +200,7 @@ static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env,
|
|||||||
method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II)V");
|
method_reportAGpsStatus = env->GetMethodID(clazz, "reportAGpsStatus", "(II)V");
|
||||||
method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(IJ)V");
|
method_reportNmea = env->GetMethodID(clazz, "reportNmea", "(IJ)V");
|
||||||
method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
|
method_xtraDownloadRequest = env->GetMethodID(clazz, "xtraDownloadRequest", "()V");
|
||||||
|
method_reportNiNotification = env->GetMethodID(clazz, "reportNiNotification", "(IIIIILjava/lang/String;Ljava/lang/String;IILjava/lang/String;)V");
|
||||||
}
|
}
|
||||||
|
|
||||||
static jboolean android_location_GpsLocationProvider_is_supported(JNIEnv* env, jclass clazz) {
|
static jboolean android_location_GpsLocationProvider_is_supported(JNIEnv* env, jclass clazz) {
|
||||||
@@ -194,6 +220,12 @@ static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject o
|
|||||||
sAGpsInterface = (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
|
sAGpsInterface = (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
|
||||||
if (sAGpsInterface)
|
if (sAGpsInterface)
|
||||||
sAGpsInterface->init(&sAGpsCallbacks);
|
sAGpsInterface->init(&sAGpsCallbacks);
|
||||||
|
|
||||||
|
if (!sGpsNiInterface)
|
||||||
|
sGpsNiInterface = (const GpsNiInterface*)sGpsInterface->get_extension(GPS_NI_INTERFACE);
|
||||||
|
if (sGpsNiInterface)
|
||||||
|
sGpsNiInterface->init(&sGpsNiCallbacks);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,6 +286,8 @@ static void android_location_GpsLocationProvider_wait_for_event(JNIEnv* env, job
|
|||||||
memcpy(&sAGpsStatusCopy, &sAGpsStatus, sizeof(sAGpsStatusCopy));
|
memcpy(&sAGpsStatusCopy, &sAGpsStatus, sizeof(sAGpsStatusCopy));
|
||||||
if (pendingCallbacks & kNmeaAvailable)
|
if (pendingCallbacks & kNmeaAvailable)
|
||||||
memcpy(&sNmeaBufferCopy, &sNmeaBuffer, nmeaSentenceCount * sizeof(sNmeaBuffer[0]));
|
memcpy(&sNmeaBufferCopy, &sNmeaBuffer, nmeaSentenceCount * sizeof(sNmeaBuffer[0]));
|
||||||
|
if (pendingCallbacks & kNiNotification)
|
||||||
|
memcpy(&sGpsNiNotificationCopy, &sGpsNiNotification, sizeof(sGpsNiNotificationCopy));
|
||||||
pthread_mutex_unlock(&sEventMutex);
|
pthread_mutex_unlock(&sEventMutex);
|
||||||
|
|
||||||
if (pendingCallbacks & kLocation) {
|
if (pendingCallbacks & kLocation) {
|
||||||
@@ -283,6 +317,24 @@ static void android_location_GpsLocationProvider_wait_for_event(JNIEnv* env, job
|
|||||||
if (pendingCallbacks & kDisableRequest) {
|
if (pendingCallbacks & kDisableRequest) {
|
||||||
// don't need to do anything - we are just poking so wait_for_event will return.
|
// don't need to do anything - we are just poking so wait_for_event will return.
|
||||||
}
|
}
|
||||||
|
if (pendingCallbacks & kNiNotification) {
|
||||||
|
LOGD("android_location_GpsLocationProvider_wait_for_event: sent notification callback.");
|
||||||
|
jstring reqId = env->NewStringUTF(sGpsNiNotificationCopy.requestor_id);
|
||||||
|
jstring text = env->NewStringUTF(sGpsNiNotificationCopy.text);
|
||||||
|
jstring extras = env->NewStringUTF(sGpsNiNotificationCopy.extras);
|
||||||
|
env->CallVoidMethod(obj, method_reportNiNotification,
|
||||||
|
sGpsNiNotificationCopy.notification_id,
|
||||||
|
sGpsNiNotificationCopy.ni_type,
|
||||||
|
sGpsNiNotificationCopy.notify_flags,
|
||||||
|
sGpsNiNotificationCopy.timeout,
|
||||||
|
sGpsNiNotificationCopy.default_response,
|
||||||
|
reqId,
|
||||||
|
text,
|
||||||
|
sGpsNiNotificationCopy.requestor_id_encoding,
|
||||||
|
sGpsNiNotificationCopy.text_encoding,
|
||||||
|
extras
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static jint android_location_GpsLocationProvider_read_sv_status(JNIEnv* env, jobject obj,
|
static jint android_location_GpsLocationProvider_read_sv_status(JNIEnv* env, jobject obj,
|
||||||
@@ -415,6 +467,16 @@ static void android_location_GpsLocationProvider_set_agps_server(JNIEnv* env, jo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void android_location_GpsLocationProvider_send_ni_response(JNIEnv* env, jobject obj,
|
||||||
|
jint notifId, jint response)
|
||||||
|
{
|
||||||
|
if (!sGpsNiInterface)
|
||||||
|
sGpsNiInterface = (const GpsNiInterface*)sGpsInterface->get_extension(GPS_NI_INTERFACE);
|
||||||
|
if (sGpsNiInterface) {
|
||||||
|
sGpsNiInterface->respond(notifId, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static JNINativeMethod sMethods[] = {
|
static JNINativeMethod sMethods[] = {
|
||||||
/* name, signature, funcPtr */
|
/* name, signature, funcPtr */
|
||||||
{"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native},
|
{"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native},
|
||||||
@@ -436,6 +498,7 @@ static JNINativeMethod sMethods[] = {
|
|||||||
{"native_agps_data_conn_closed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_closed},
|
{"native_agps_data_conn_closed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_closed},
|
||||||
{"native_agps_data_conn_failed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_failed},
|
{"native_agps_data_conn_failed", "()V", (void*)android_location_GpsLocationProvider_agps_data_conn_failed},
|
||||||
{"native_set_agps_server", "(ILjava/lang/String;I)V", (void*)android_location_GpsLocationProvider_set_agps_server},
|
{"native_set_agps_server", "(ILjava/lang/String;I)V", (void*)android_location_GpsLocationProvider_set_agps_server},
|
||||||
|
{"native_send_ni_response", "(II)V", (void*)android_location_GpsLocationProvider_send_ni_response},
|
||||||
};
|
};
|
||||||
|
|
||||||
int register_android_location_GpsLocationProvider(JNIEnv* env)
|
int register_android_location_GpsLocationProvider(JNIEnv* env)
|
||||||
|
|||||||
@@ -1163,6 +1163,10 @@
|
|||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
<activity android:name="com.android.internal.app.NetInitiatedActivity"
|
||||||
|
android:theme="@style/Theme.Dialog.Alert"
|
||||||
|
android:excludeFromRecents="true">
|
||||||
|
</activity>
|
||||||
|
|
||||||
<service android:name="com.android.server.LoadAverageService"
|
<service android:name="com.android.server.LoadAverageService"
|
||||||
android:exported="true" />
|
android:exported="true" />
|
||||||
|
|||||||
@@ -83,4 +83,7 @@ interface ILocationManager
|
|||||||
/* for installing external Location Providers */
|
/* for installing external Location Providers */
|
||||||
void installLocationProvider(String name, ILocationProvider provider);
|
void installLocationProvider(String name, ILocationProvider provider);
|
||||||
void installGeocodeProvider(IGeocodeProvider provider);
|
void installGeocodeProvider(IGeocodeProvider provider);
|
||||||
|
|
||||||
|
// for NI support
|
||||||
|
boolean sendNiResponse(int notifId, int userResponse);
|
||||||
}
|
}
|
||||||
|
|||||||
26
location/java/android/location/INetInitiatedListener.aidl
Executable file
26
location/java/android/location/INetInitiatedListener.aidl
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
**
|
||||||
|
** 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package android.location;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@hide}
|
||||||
|
*/
|
||||||
|
interface INetInitiatedListener
|
||||||
|
{
|
||||||
|
boolean sendNiResponse(int notifId, int userResponse);
|
||||||
|
}
|
||||||
@@ -1417,4 +1417,20 @@ public class LocationManager {
|
|||||||
Log.e(TAG, "RemoteException in reportLocation: ", e);
|
Log.e(TAG, "RemoteException in reportLocation: ", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used by NetInitiatedActivity to report user response
|
||||||
|
* for network initiated GPS fix requests.
|
||||||
|
*
|
||||||
|
* {@hide}
|
||||||
|
*/
|
||||||
|
public boolean sendNiResponse(int notifId, int userResponse) {
|
||||||
|
try {
|
||||||
|
return mService.sendNiResponse(notifId, userResponse);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.e(TAG, "RemoteException in sendNiResponse: ", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import android.location.IGpsStatusListener;
|
|||||||
import android.location.IGpsStatusProvider;
|
import android.location.IGpsStatusProvider;
|
||||||
import android.location.ILocationManager;
|
import android.location.ILocationManager;
|
||||||
import android.location.ILocationProvider;
|
import android.location.ILocationProvider;
|
||||||
|
import android.location.INetInitiatedListener;
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
import android.location.LocationManager;
|
import android.location.LocationManager;
|
||||||
import android.location.LocationProvider;
|
import android.location.LocationProvider;
|
||||||
@@ -46,14 +47,18 @@ import android.util.SparseIntArray;
|
|||||||
import com.android.internal.app.IBatteryStats;
|
import com.android.internal.app.IBatteryStats;
|
||||||
import com.android.internal.telephony.Phone;
|
import com.android.internal.telephony.Phone;
|
||||||
import com.android.internal.telephony.TelephonyIntents;
|
import com.android.internal.telephony.TelephonyIntents;
|
||||||
|
import com.android.internal.location.GpsNetInitiatedHandler;
|
||||||
|
import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.StringBufferInputStream;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A GPS implementation of LocationProvider used by LocationManager.
|
* A GPS implementation of LocationProvider used by LocationManager.
|
||||||
@@ -214,6 +219,7 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
|
|||||||
private String mAGpsApn;
|
private String mAGpsApn;
|
||||||
private int mAGpsDataConnectionState;
|
private int mAGpsDataConnectionState;
|
||||||
private final ConnectivityManager mConnMgr;
|
private final ConnectivityManager mConnMgr;
|
||||||
|
private final GpsNetInitiatedHandler mNIHandler;
|
||||||
|
|
||||||
// Wakelocks
|
// Wakelocks
|
||||||
private final static String WAKELOCK_KEY = "GpsLocationProvider";
|
private final static String WAKELOCK_KEY = "GpsLocationProvider";
|
||||||
@@ -324,6 +330,7 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
|
|||||||
public GpsLocationProvider(Context context, ILocationManager locationManager) {
|
public GpsLocationProvider(Context context, ILocationManager locationManager) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mLocationManager = locationManager;
|
mLocationManager = locationManager;
|
||||||
|
mNIHandler= new GpsNetInitiatedHandler(context, this);
|
||||||
|
|
||||||
// Create a wake lock
|
// Create a wake lock
|
||||||
PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
|
PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
|
||||||
@@ -1047,6 +1054,96 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//=============================================================
|
||||||
|
// NI Client support
|
||||||
|
//=============================================================
|
||||||
|
private final INetInitiatedListener mNetInitiatedListener = new INetInitiatedListener.Stub() {
|
||||||
|
// Sends a response for an NI reqeust to HAL.
|
||||||
|
public boolean sendNiResponse(int notificationId, int userResponse)
|
||||||
|
{
|
||||||
|
// TODO Add Permission check
|
||||||
|
|
||||||
|
StringBuilder extrasBuf = new StringBuilder();
|
||||||
|
|
||||||
|
if (Config.LOGD) Log.d(TAG, "sendNiResponse, notifId: " + notificationId +
|
||||||
|
", response: " + userResponse);
|
||||||
|
|
||||||
|
native_send_ni_response(notificationId, userResponse);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public INetInitiatedListener getNetInitiatedListener() {
|
||||||
|
return mNetInitiatedListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by JNI function to report an NI request.
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public void reportNiNotification(
|
||||||
|
int notificationId,
|
||||||
|
int niType,
|
||||||
|
int notifyFlags,
|
||||||
|
int timeout,
|
||||||
|
int defaultResponse,
|
||||||
|
String requestorId,
|
||||||
|
String text,
|
||||||
|
int requestorIdEncoding,
|
||||||
|
int textEncoding,
|
||||||
|
String extras // Encoded extra data
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Log.i(TAG, "reportNiNotification: entered");
|
||||||
|
Log.i(TAG, "notificationId: " + notificationId +
|
||||||
|
", niType: " + niType +
|
||||||
|
", notifyFlags: " + notifyFlags +
|
||||||
|
", timeout: " + timeout +
|
||||||
|
", defaultResponse: " + defaultResponse);
|
||||||
|
|
||||||
|
Log.i(TAG, "requestorId: " + requestorId +
|
||||||
|
", text: " + text +
|
||||||
|
", requestorIdEncoding: " + requestorIdEncoding +
|
||||||
|
", textEncoding: " + textEncoding);
|
||||||
|
|
||||||
|
GpsNiNotification notification = new GpsNiNotification();
|
||||||
|
|
||||||
|
notification.notificationId = notificationId;
|
||||||
|
notification.niType = niType;
|
||||||
|
notification.needNotify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_NOTIFY) != 0;
|
||||||
|
notification.needVerify = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_NEED_VERIFY) != 0;
|
||||||
|
notification.privacyOverride = (notifyFlags & GpsNetInitiatedHandler.GPS_NI_PRIVACY_OVERRIDE) != 0;
|
||||||
|
notification.timeout = timeout;
|
||||||
|
notification.defaultResponse = defaultResponse;
|
||||||
|
notification.requestorId = requestorId;
|
||||||
|
notification.text = text;
|
||||||
|
notification.requestorIdEncoding = requestorIdEncoding;
|
||||||
|
notification.textEncoding = textEncoding;
|
||||||
|
|
||||||
|
// Process extras, assuming the format is
|
||||||
|
// one of more lines of "key = value"
|
||||||
|
Bundle bundle = new Bundle();
|
||||||
|
|
||||||
|
if (extras == null) extras = "";
|
||||||
|
Properties extraProp = new Properties();
|
||||||
|
|
||||||
|
try {
|
||||||
|
extraProp.load(new StringBufferInputStream(extras));
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
Log.e(TAG, "reportNiNotification cannot parse extras data: " + extras);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Entry<Object, Object> ent : extraProp.entrySet())
|
||||||
|
{
|
||||||
|
bundle.putString((String) ent.getKey(), (String) ent.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
notification.extras = bundle;
|
||||||
|
|
||||||
|
mNIHandler.handleNiNotification(notification);
|
||||||
|
}
|
||||||
|
|
||||||
private class GpsEventThread extends Thread {
|
private class GpsEventThread extends Thread {
|
||||||
|
|
||||||
public GpsEventThread() {
|
public GpsEventThread() {
|
||||||
@@ -1252,4 +1349,7 @@ public class GpsLocationProvider extends ILocationProvider.Stub {
|
|||||||
private native void native_agps_data_conn_closed();
|
private native void native_agps_data_conn_closed();
|
||||||
private native void native_agps_data_conn_failed();
|
private native void native_agps_data_conn_failed();
|
||||||
private native void native_set_agps_server(int type, String hostname, int port);
|
private native void native_set_agps_server(int type, String hostname, int port);
|
||||||
|
|
||||||
|
// Network-initiated (NI) Support
|
||||||
|
private native void native_send_ni_response(int notificationId, int userResponse);
|
||||||
}
|
}
|
||||||
|
|||||||
457
location/java/com/android/internal/location/GpsNetInitiatedHandler.java
Executable file
457
location/java/com/android/internal/location/GpsNetInitiatedHandler.java
Executable file
@@ -0,0 +1,457 @@
|
|||||||
|
/*
|
||||||
|
* 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.internal.location;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
|
||||||
|
import android.app.Notification;
|
||||||
|
import android.app.NotificationManager;
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A GPS Network-initiated Handler class used by LocationManager.
|
||||||
|
*
|
||||||
|
* {@hide}
|
||||||
|
*/
|
||||||
|
public class GpsNetInitiatedHandler {
|
||||||
|
|
||||||
|
private static final String TAG = "GpsNetInitiatedHandler";
|
||||||
|
|
||||||
|
private static final boolean DEBUG = true;
|
||||||
|
private static final boolean VERBOSE = false;
|
||||||
|
|
||||||
|
// NI verify activity for bringing up UI (not used yet)
|
||||||
|
public static final String ACTION_NI_VERIFY = "android.intent.action.NETWORK_INITIATED_VERIFY";
|
||||||
|
|
||||||
|
// string constants for defining data fields in NI Intent
|
||||||
|
public static final String NI_INTENT_KEY_NOTIF_ID = "notif_id";
|
||||||
|
public static final String NI_INTENT_KEY_TITLE = "title";
|
||||||
|
public static final String NI_INTENT_KEY_MESSAGE = "message";
|
||||||
|
public static final String NI_INTENT_KEY_TIMEOUT = "timeout";
|
||||||
|
public static final String NI_INTENT_KEY_DEFAULT_RESPONSE = "default_resp";
|
||||||
|
|
||||||
|
// the extra command to send NI response to GpsLocationProvider
|
||||||
|
public static final String NI_RESPONSE_EXTRA_CMD = "send_ni_response";
|
||||||
|
|
||||||
|
// the extra command parameter names in the Bundle
|
||||||
|
public static final String NI_EXTRA_CMD_NOTIF_ID = "notif_id";
|
||||||
|
public static final String NI_EXTRA_CMD_RESPONSE = "response";
|
||||||
|
|
||||||
|
// these need to match GpsNiType constants in gps_ni.h
|
||||||
|
public static final int GPS_NI_TYPE_VOICE = 1;
|
||||||
|
public static final int GPS_NI_TYPE_UMTS_SUPL = 2;
|
||||||
|
public static final int GPS_NI_TYPE_UMTS_CTRL_PLANE = 3;
|
||||||
|
|
||||||
|
// these need to match GpsUserResponseType constants in gps_ni.h
|
||||||
|
public static final int GPS_NI_RESPONSE_ACCEPT = 1;
|
||||||
|
public static final int GPS_NI_RESPONSE_DENY = 2;
|
||||||
|
public static final int GPS_NI_RESPONSE_NORESP = 3;
|
||||||
|
|
||||||
|
// these need to match GpsNiNotifyFlags constants in gps_ni.h
|
||||||
|
public static final int GPS_NI_NEED_NOTIFY = 0x0001;
|
||||||
|
public static final int GPS_NI_NEED_VERIFY = 0x0002;
|
||||||
|
public static final int GPS_NI_PRIVACY_OVERRIDE = 0x0004;
|
||||||
|
|
||||||
|
// these need to match GpsNiEncodingType in gps_ni.h
|
||||||
|
public static final int GPS_ENC_NONE = 0;
|
||||||
|
public static final int GPS_ENC_SUPL_GSM_DEFAULT = 1;
|
||||||
|
public static final int GPS_ENC_SUPL_UTF8 = 2;
|
||||||
|
public static final int GPS_ENC_SUPL_UCS2 = 3;
|
||||||
|
public static final int GPS_ENC_UNKNOWN = -1;
|
||||||
|
|
||||||
|
private final Context mContext;
|
||||||
|
|
||||||
|
// parent gps location provider
|
||||||
|
private final GpsLocationProvider mGpsLocationProvider;
|
||||||
|
|
||||||
|
// configuration of notificaiton behavior
|
||||||
|
private boolean mPlaySounds = false;
|
||||||
|
private boolean visible = true;
|
||||||
|
private boolean mPopupImmediately = true;
|
||||||
|
|
||||||
|
// Set to true if string from HAL is encoded as Hex, e.g., "3F0039"
|
||||||
|
static private boolean mIsHexInput = true;
|
||||||
|
|
||||||
|
public static class GpsNiNotification
|
||||||
|
{
|
||||||
|
int notificationId;
|
||||||
|
int niType;
|
||||||
|
boolean needNotify;
|
||||||
|
boolean needVerify;
|
||||||
|
boolean privacyOverride;
|
||||||
|
int timeout;
|
||||||
|
int defaultResponse;
|
||||||
|
String requestorId;
|
||||||
|
String text;
|
||||||
|
int requestorIdEncoding;
|
||||||
|
int textEncoding;
|
||||||
|
Bundle extras;
|
||||||
|
};
|
||||||
|
|
||||||
|
public static class GpsNiResponse {
|
||||||
|
/* User reponse, one of the values in GpsUserResponseType */
|
||||||
|
int userResponse;
|
||||||
|
/* Optional extra data to pass with the user response */
|
||||||
|
Bundle extras;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The notification that is shown when a network-initiated notification
|
||||||
|
* (and verification) event is received.
|
||||||
|
* <p>
|
||||||
|
* This is lazily created, so use {@link #setNINotification()}.
|
||||||
|
*/
|
||||||
|
private Notification mNiNotification;
|
||||||
|
|
||||||
|
public GpsNetInitiatedHandler(Context context, GpsLocationProvider gpsLocationProvider) {
|
||||||
|
mContext = context;
|
||||||
|
mGpsLocationProvider = gpsLocationProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handles NI events from HAL
|
||||||
|
public void handleNiNotification(GpsNiNotification notif)
|
||||||
|
{
|
||||||
|
if (DEBUG) Log.d(TAG, "handleNiNotification" + " notificationId: " + notif.notificationId
|
||||||
|
+ " requestorId: " + notif.requestorId + " text: " + notif.text);
|
||||||
|
|
||||||
|
// Notify and verify with immediate pop-up
|
||||||
|
if (notif.needNotify && notif.needVerify && mPopupImmediately)
|
||||||
|
{
|
||||||
|
// Popup the dialog box now
|
||||||
|
openNiDialog(notif);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify only, or delayed pop-up (change mPopupImmediately to FALSE)
|
||||||
|
if (notif.needNotify && !notif.needVerify ||
|
||||||
|
notif.needNotify && notif.needVerify && !mPopupImmediately)
|
||||||
|
{
|
||||||
|
// Show the notification
|
||||||
|
|
||||||
|
// if mPopupImmediately == FALSE and needVerify == TRUE, a dialog will be opened
|
||||||
|
// when the user opens the notification message
|
||||||
|
|
||||||
|
setNiNotification(notif);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACCEPT cases: 1. Notify, no verify; 2. no notify, no verify; 3. privacy override.
|
||||||
|
if ( notif.needNotify && !notif.needVerify ||
|
||||||
|
!notif.needNotify && !notif.needVerify ||
|
||||||
|
notif.privacyOverride)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
mGpsLocationProvider.getNetInitiatedListener().sendNiResponse(notif.notificationId, GPS_NI_RESPONSE_ACCEPT);
|
||||||
|
}
|
||||||
|
catch (RemoteException e)
|
||||||
|
{
|
||||||
|
Log.e(TAG, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// A note about timeout
|
||||||
|
// According to the protocol, in the need_notify and need_verify case,
|
||||||
|
// a default response should be sent when time out.
|
||||||
|
//
|
||||||
|
// In some GPS hardware, the GPS driver (under HAL) can handle the timeout case
|
||||||
|
// and this class GpsNetInitiatedHandler does not need to do anything.
|
||||||
|
//
|
||||||
|
// However, the UI should at least close the dialog when timeout. Further,
|
||||||
|
// for more general handling, timeout response should be added to the Handler here.
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets the NI notification.
|
||||||
|
private synchronized void setNiNotification(GpsNiNotification notif) {
|
||||||
|
NotificationManager notificationManager = (NotificationManager) mContext
|
||||||
|
.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
if (notificationManager == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String title = getNotifTitle(notif);
|
||||||
|
String message = getNotifMessage(notif);
|
||||||
|
|
||||||
|
if (DEBUG) Log.d(TAG, "setNiNotification, notifyId: " + notif.notificationId +
|
||||||
|
", title: " + title +
|
||||||
|
", message: " + message);
|
||||||
|
|
||||||
|
// Construct Notification
|
||||||
|
if (mNiNotification == null) {
|
||||||
|
mNiNotification = new Notification();
|
||||||
|
mNiNotification.icon = com.android.internal.R.drawable.stat_sys_gps_on; /* Change notification icon here */
|
||||||
|
mNiNotification.when = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mPlaySounds) {
|
||||||
|
mNiNotification.defaults |= Notification.DEFAULT_SOUND;
|
||||||
|
} else {
|
||||||
|
mNiNotification.defaults &= ~Notification.DEFAULT_SOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
mNiNotification.flags = Notification.FLAG_ONGOING_EVENT;
|
||||||
|
mNiNotification.tickerText = getNotifTicker(notif);
|
||||||
|
|
||||||
|
// if not to popup dialog immediately, pending intent will open the dialog
|
||||||
|
Intent intent = !mPopupImmediately ? getDlgIntent(notif) : new Intent();
|
||||||
|
PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, intent, 0);
|
||||||
|
mNiNotification.setLatestEventInfo(mContext, title, message, pi);
|
||||||
|
|
||||||
|
if (visible) {
|
||||||
|
notificationManager.notify(notif.notificationId, mNiNotification);
|
||||||
|
} else {
|
||||||
|
notificationManager.cancel(notif.notificationId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Opens the notification dialog and waits for user input
|
||||||
|
private void openNiDialog(GpsNiNotification notif)
|
||||||
|
{
|
||||||
|
Intent intent = getDlgIntent(notif);
|
||||||
|
|
||||||
|
if (DEBUG) Log.d(TAG, "openNiDialog, notifyId: " + notif.notificationId +
|
||||||
|
", requestorId: " + notif.requestorId +
|
||||||
|
", text: " + notif.text);
|
||||||
|
|
||||||
|
mContext.startActivity(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct the intent for bringing up the dialog activity, which shows the
|
||||||
|
// notification and takes user input
|
||||||
|
private Intent getDlgIntent(GpsNiNotification notif)
|
||||||
|
{
|
||||||
|
Intent intent = new Intent();
|
||||||
|
String title = getDialogTitle(notif);
|
||||||
|
String message = getDialogMessage(notif);
|
||||||
|
|
||||||
|
// directly bring up the NI activity
|
||||||
|
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
intent.setClass(mContext, com.android.internal.app.NetInitiatedActivity.class);
|
||||||
|
|
||||||
|
// put data in the intent
|
||||||
|
intent.putExtra(NI_INTENT_KEY_NOTIF_ID, notif.notificationId);
|
||||||
|
intent.putExtra(NI_INTENT_KEY_TITLE, title);
|
||||||
|
intent.putExtra(NI_INTENT_KEY_MESSAGE, message);
|
||||||
|
intent.putExtra(NI_INTENT_KEY_TIMEOUT, notif.timeout);
|
||||||
|
intent.putExtra(NI_INTENT_KEY_DEFAULT_RESPONSE, notif.defaultResponse);
|
||||||
|
|
||||||
|
if (DEBUG) Log.d(TAG, "generateIntent, title: " + title + ", message: " + message +
|
||||||
|
", timeout: " + notif.timeout);
|
||||||
|
|
||||||
|
return intent;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Converts a string (or Hex string) to a char array
|
||||||
|
static byte[] stringToByteArray(String original, boolean isHex)
|
||||||
|
{
|
||||||
|
int length = isHex ? original.length() / 2 : original.length();
|
||||||
|
byte[] output = new byte[length];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (isHex)
|
||||||
|
{
|
||||||
|
for (i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
output[i] = (byte) Integer.parseInt(original.substring(i*2, i*2+2), 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
output[i] = (byte) original.charAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unpacks an byte array containing 7-bit packed characters into a String.
|
||||||
|
*
|
||||||
|
* @param input a 7-bit packed char array
|
||||||
|
* @return the unpacked String
|
||||||
|
*/
|
||||||
|
static String decodeGSMPackedString(byte[] input)
|
||||||
|
{
|
||||||
|
final char CHAR_CR = 0x0D;
|
||||||
|
int nStridx = 0;
|
||||||
|
int nPckidx = 0;
|
||||||
|
int num_bytes = input.length;
|
||||||
|
int cPrev = 0;
|
||||||
|
int cCurr = 0;
|
||||||
|
byte nShift;
|
||||||
|
byte nextChar;
|
||||||
|
byte[] stringBuf = new byte[input.length * 2];
|
||||||
|
String result = "";
|
||||||
|
|
||||||
|
while(nPckidx < num_bytes)
|
||||||
|
{
|
||||||
|
nShift = (byte) (nStridx & 0x07);
|
||||||
|
cCurr = input[nPckidx++];
|
||||||
|
if (cCurr < 0) cCurr += 256;
|
||||||
|
|
||||||
|
/* A 7-bit character can be split at the most between two bytes of packed
|
||||||
|
** data.
|
||||||
|
*/
|
||||||
|
nextChar = (byte) (( (cCurr << nShift) | (cPrev >> (8-nShift)) ) & 0x7F);
|
||||||
|
stringBuf[nStridx++] = nextChar;
|
||||||
|
|
||||||
|
/* Special case where the whole of the next 7-bit character fits inside
|
||||||
|
** the current byte of packed data.
|
||||||
|
*/
|
||||||
|
if(nShift == 6)
|
||||||
|
{
|
||||||
|
/* If the next 7-bit character is a CR (0x0D) and it is the last
|
||||||
|
** character, then it indicates a padding character. Drop it.
|
||||||
|
*/
|
||||||
|
if (nPckidx == num_bytes || (cCurr >> 1) == CHAR_CR)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
nextChar = (byte) (cCurr >> 1);
|
||||||
|
stringBuf[nStridx++] = nextChar;
|
||||||
|
}
|
||||||
|
|
||||||
|
cPrev = cCurr;
|
||||||
|
}
|
||||||
|
|
||||||
|
try{
|
||||||
|
result = new String(stringBuf, 0, nStridx, "US-ASCII");
|
||||||
|
}
|
||||||
|
catch (UnsupportedEncodingException e)
|
||||||
|
{
|
||||||
|
Log.e(TAG, e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String decodeUTF8String(byte[] input)
|
||||||
|
{
|
||||||
|
String decoded = "";
|
||||||
|
try {
|
||||||
|
decoded = new String(input, "UTF-8");
|
||||||
|
}
|
||||||
|
catch (UnsupportedEncodingException e)
|
||||||
|
{
|
||||||
|
Log.e(TAG, e.getMessage());
|
||||||
|
}
|
||||||
|
return decoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String decodeUCS2String(byte[] input)
|
||||||
|
{
|
||||||
|
String decoded = "";
|
||||||
|
try {
|
||||||
|
decoded = new String(input, "UTF-16");
|
||||||
|
}
|
||||||
|
catch (UnsupportedEncodingException e)
|
||||||
|
{
|
||||||
|
Log.e(TAG, e.getMessage());
|
||||||
|
}
|
||||||
|
return decoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Decode NI string
|
||||||
|
*
|
||||||
|
* @param original The text string to be decoded
|
||||||
|
* @param isHex Specifies whether the content of the string has been encoded as a Hex string. Encoding
|
||||||
|
* a string as Hex can allow zeros inside the coded text.
|
||||||
|
* @param coding Specifies the coding scheme of the string, such as GSM, UTF8, UCS2, etc. This coding scheme
|
||||||
|
* needs to match those used passed to HAL from the native GPS driver. Decoding is done according
|
||||||
|
* to the <code> coding </code>, after a Hex string is decoded. Generally, if the
|
||||||
|
* notification strings don't need further decoding, <code> coding </code> encoding can be
|
||||||
|
* set to -1, and <code> isHex </code> can be false.
|
||||||
|
* @return the decoded string
|
||||||
|
*/
|
||||||
|
static private String decodeString(String original, boolean isHex, int coding)
|
||||||
|
{
|
||||||
|
String decoded = original;
|
||||||
|
byte[] input = stringToByteArray(original, isHex);
|
||||||
|
|
||||||
|
switch (coding) {
|
||||||
|
case GPS_ENC_NONE:
|
||||||
|
decoded = original;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GPS_ENC_SUPL_GSM_DEFAULT:
|
||||||
|
decoded = decodeGSMPackedString(input);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GPS_ENC_SUPL_UTF8:
|
||||||
|
decoded = decodeUTF8String(input);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GPS_ENC_SUPL_UCS2:
|
||||||
|
decoded = decodeUCS2String(input);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GPS_ENC_UNKNOWN:
|
||||||
|
decoded = original;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Log.e(TAG, "Unknown encoding " + coding + " for NI text " + original);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return decoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
// change this to configure notification display
|
||||||
|
static private String getNotifTicker(GpsNiNotification notif)
|
||||||
|
{
|
||||||
|
String ticker = String.format("Position request! ReqId: [%s] ClientName: [%s]",
|
||||||
|
decodeString(notif.requestorId, mIsHexInput, notif.requestorIdEncoding),
|
||||||
|
decodeString(notif.text, mIsHexInput, notif.textEncoding));
|
||||||
|
return ticker;
|
||||||
|
}
|
||||||
|
|
||||||
|
// change this to configure notification display
|
||||||
|
static private String getNotifTitle(GpsNiNotification notif)
|
||||||
|
{
|
||||||
|
String title = String.format("Position Request");
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
// change this to configure notification display
|
||||||
|
static private String getNotifMessage(GpsNiNotification notif)
|
||||||
|
{
|
||||||
|
String message = String.format(
|
||||||
|
"NI Request received from [%s] for client [%s]!",
|
||||||
|
decodeString(notif.requestorId, mIsHexInput, notif.requestorIdEncoding),
|
||||||
|
decodeString(notif.text, mIsHexInput, notif.textEncoding));
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
// change this to configure dialog display (for verification)
|
||||||
|
static public String getDialogTitle(GpsNiNotification notif)
|
||||||
|
{
|
||||||
|
return getNotifTitle(notif);
|
||||||
|
}
|
||||||
|
|
||||||
|
// change this to configure dialog display (for verification)
|
||||||
|
static private String getDialogMessage(GpsNiNotification notif)
|
||||||
|
{
|
||||||
|
return getNotifMessage(notif);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -49,6 +49,7 @@ import android.location.IGpsStatusProvider;
|
|||||||
import android.location.ILocationListener;
|
import android.location.ILocationListener;
|
||||||
import android.location.ILocationManager;
|
import android.location.ILocationManager;
|
||||||
import android.location.ILocationProvider;
|
import android.location.ILocationProvider;
|
||||||
|
import android.location.INetInitiatedListener;
|
||||||
import android.location.Location;
|
import android.location.Location;
|
||||||
import android.location.LocationManager;
|
import android.location.LocationManager;
|
||||||
import android.location.LocationProvider;
|
import android.location.LocationProvider;
|
||||||
@@ -71,6 +72,7 @@ import android.util.PrintWriterPrinter;
|
|||||||
import com.android.internal.location.GpsLocationProvider;
|
import com.android.internal.location.GpsLocationProvider;
|
||||||
import com.android.internal.location.LocationProviderProxy;
|
import com.android.internal.location.LocationProviderProxy;
|
||||||
import com.android.internal.location.MockProvider;
|
import com.android.internal.location.MockProvider;
|
||||||
|
import com.android.internal.location.GpsNetInitiatedHandler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The service class that manages LocationProviders and issues location
|
* The service class that manages LocationProviders and issues location
|
||||||
@@ -118,6 +120,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private IGeocodeProvider mGeocodeProvider;
|
private IGeocodeProvider mGeocodeProvider;
|
||||||
private IGpsStatusProvider mGpsStatusProvider;
|
private IGpsStatusProvider mGpsStatusProvider;
|
||||||
|
private INetInitiatedListener mNetInitiatedListener;
|
||||||
private LocationWorkerHandler mLocationHandler;
|
private LocationWorkerHandler mLocationHandler;
|
||||||
|
|
||||||
// Cache the real providers for use in addTestProvider() and removeTestProvider()
|
// Cache the real providers for use in addTestProvider() and removeTestProvider()
|
||||||
@@ -541,6 +544,7 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
// Create a gps location provider
|
// Create a gps location provider
|
||||||
GpsLocationProvider provider = new GpsLocationProvider(mContext, this);
|
GpsLocationProvider provider = new GpsLocationProvider(mContext, this);
|
||||||
mGpsStatusProvider = provider.getGpsStatusProvider();
|
mGpsStatusProvider = provider.getGpsStatusProvider();
|
||||||
|
mNetInitiatedListener = provider.getNetInitiatedListener();
|
||||||
LocationProviderProxy proxy = new LocationProviderProxy(LocationManager.GPS_PROVIDER, provider);
|
LocationProviderProxy proxy = new LocationProviderProxy(LocationManager.GPS_PROVIDER, provider);
|
||||||
addProvider(proxy);
|
addProvider(proxy);
|
||||||
mGpsLocationProvider = proxy;
|
mGpsLocationProvider = proxy;
|
||||||
@@ -1131,6 +1135,18 @@ public class LocationManagerService extends ILocationManager.Stub implements Run
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean sendNiResponse(int notifId, int userResponse)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return mNetInitiatedListener.sendNiResponse(notifId, userResponse);
|
||||||
|
}
|
||||||
|
catch (RemoteException e)
|
||||||
|
{
|
||||||
|
Log.e(TAG, "RemoteException in LocationManagerService.sendNiResponse");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ProximityAlert {
|
class ProximityAlert {
|
||||||
final int mUid;
|
final int mUid;
|
||||||
final double mLatitude;
|
final double mLatitude;
|
||||||
|
|||||||
Reference in New Issue
Block a user