Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 22d1f9fb authored by Danke Xie's avatar Danke Xie Committed by Mike Lockwood
Browse files

gps: Network initiated SUPL



Initial contribution from Qualcomm.

Signed-off-by: default avatarMike Lockwood <lockwood@android.com>
parent 0409cde3
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -147,6 +147,7 @@ LOCAL_SRC_FILES += \
	location/java/android/location/ILocationListener.aidl \
	location/java/android/location/ILocationManager.aidl \
	location/java/android/location/ILocationProvider.aidl \
	location/java/android/location/INetInitiatedListener.aidl \
	media/java/android/media/IAudioService.aidl \
	media/java/android/media/IMediaScannerListener.aidl \
	media/java/android/media/IMediaScannerService.aidl \
+139 −0
Original line number Diff line number Diff line
/*
 * 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();
    }
}
+74 −11
Original line number Diff line number Diff line
@@ -16,16 +16,18 @@

#define LOG_TAG "GpsLocationProvider"

//#define LOG_NDDEBUG 0

#include "JNIHelp.h"
#include "jni.h"
#include "hardware_legacy/gps.h"
#include "hardware_legacy/gps_ni.h"
#include "utils/Log.h"
#include "utils/misc.h"

#include <string.h>
#include <pthread.h>


static pthread_mutex_t sEventMutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t sEventCond = PTHREAD_COND_INITIALIZER;
static jmethodID method_reportLocation;
@@ -34,16 +36,19 @@ static jmethodID method_reportSvStatus;
static jmethodID method_reportAGpsStatus;
static jmethodID method_reportNmea;
static jmethodID method_xtraDownloadRequest;
static jmethodID method_reportNiNotification;

static const GpsInterface* sGpsInterface = NULL;
static const GpsXtraInterface* sGpsXtraInterface = NULL;
static const AGpsInterface* sAGpsInterface = NULL;
static const GpsNiInterface* sGpsNiInterface = NULL;

// data written to by GPS callbacks
static GpsLocation  sGpsLocation;
static GpsStatus    sGpsStatus;
static GpsSvStatus  sGpsSvStatus;
static AGpsStatus   sAGpsStatus;
static GpsNiNotification  sGpsNiNotification;

// buffer for NMEA data
#define NMEA_SENTENCE_LENGTH    100
@@ -62,6 +67,7 @@ static GpsStatus sGpsStatusCopy;
static GpsSvStatus  sGpsSvStatusCopy;
static AGpsStatus   sAGpsStatusCopy;
static NmeaSentence sNmeaBufferCopy[NMEA_SENTENCE_LENGTH];
static GpsNiNotification  sGpsNiNotificationCopy;

enum CallbackType {
    kLocation = 1,
@@ -71,6 +77,7 @@ enum CallbackType {
    kXtraDownloadRequest = 16,
    kDisableRequest = 32,
    kNmeaAvailable = 64,
    kNiNotification = 128,
}; 
static int sPendingCallbacks;

@@ -160,6 +167,20 @@ download_request_callback()
    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 = {
    download_request_callback,
};
@@ -168,6 +189,10 @@ AGpsCallbacks sAGpsCallbacks = {
    agps_status_callback,
};

GpsNiCallbacks sGpsNiCallbacks = {
    gps_ni_notify_callback,
};

static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
    method_reportLocation = env->GetMethodID(clazz, "reportLocation", "(IDDDFFFJ)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_reportNmea = env->GetMethodID(clazz, "reportNmea", "(IJ)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) {
@@ -194,6 +220,12 @@ static jboolean android_location_GpsLocationProvider_init(JNIEnv* env, jobject o
        sAGpsInterface = (const AGpsInterface*)sGpsInterface->get_extension(AGPS_INTERFACE);
    if (sAGpsInterface)
        sAGpsInterface->init(&sAGpsCallbacks);

    if (!sGpsNiInterface)
       sGpsNiInterface = (const GpsNiInterface*)sGpsInterface->get_extension(GPS_NI_INTERFACE);
    if (sGpsNiInterface)
       sGpsNiInterface->init(&sGpsNiCallbacks);

    return true;
}

@@ -254,6 +286,8 @@ static void android_location_GpsLocationProvider_wait_for_event(JNIEnv* env, job
        memcpy(&sAGpsStatusCopy, &sAGpsStatus, sizeof(sAGpsStatusCopy));
    if (pendingCallbacks & kNmeaAvailable)
        memcpy(&sNmeaBufferCopy, &sNmeaBuffer, nmeaSentenceCount * sizeof(sNmeaBuffer[0]));
    if (pendingCallbacks & kNiNotification)
        memcpy(&sGpsNiNotificationCopy, &sGpsNiNotification, sizeof(sGpsNiNotificationCopy));
    pthread_mutex_unlock(&sEventMutex);   

    if (pendingCallbacks & kLocation) {
@@ -283,6 +317,24 @@ static void android_location_GpsLocationProvider_wait_for_event(JNIEnv* env, job
    if (pendingCallbacks & kDisableRequest) {
        // 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,
@@ -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[] = {
     /* name, signature, funcPtr */
    {"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_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_send_ni_response", "(II)V", (void*)android_location_GpsLocationProvider_send_ni_response},
};

int register_android_location_GpsLocationProvider(JNIEnv* env)
+4 −0
Original line number Diff line number Diff line
@@ -1163,6 +1163,10 @@
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </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"
                android:exported="true" />
+3 −0
Original line number Diff line number Diff line
@@ -83,4 +83,7 @@ interface ILocationManager
    /* for installing external Location Providers */
    void installLocationProvider(String name, ILocationProvider provider);
    void installGeocodeProvider(IGeocodeProvider provider);

    // for NI support
    boolean sendNiResponse(int notifId, int userResponse);
}
Loading