FileDocCategorySizeDatePackage
GpsNetInitiatedHandler.javaAPI DocAndroid 5.1 API23445Thu Mar 12 22:22:30 GMT 2015com.android.internal.location

GpsNetInitiatedHandler

public class GpsNetInitiatedHandler extends Object
A GPS Network-initiated Handler class used by LocationManager. {@hide}

Fields Summary
private static final String
TAG
private static final boolean
DEBUG
private static final boolean
VERBOSE
public static final String
ACTION_NI_VERIFY
public static final String
NI_INTENT_KEY_NOTIF_ID
public static final String
NI_INTENT_KEY_TITLE
public static final String
NI_INTENT_KEY_MESSAGE
public static final String
NI_INTENT_KEY_TIMEOUT
public static final String
NI_INTENT_KEY_DEFAULT_RESPONSE
public static final String
NI_RESPONSE_EXTRA_CMD
public static final String
NI_EXTRA_CMD_NOTIF_ID
public static final String
NI_EXTRA_CMD_RESPONSE
public static final int
GPS_NI_TYPE_VOICE
public static final int
GPS_NI_TYPE_UMTS_SUPL
public static final int
GPS_NI_TYPE_UMTS_CTRL_PLANE
public static final int
GPS_NI_TYPE_EMERGENCY_SUPL
public static final int
GPS_NI_RESPONSE_ACCEPT
public static final int
GPS_NI_RESPONSE_DENY
public static final int
GPS_NI_RESPONSE_NORESP
public static final int
GPS_NI_RESPONSE_IGNORE
public static final int
GPS_NI_NEED_NOTIFY
public static final int
GPS_NI_NEED_VERIFY
public static final int
GPS_NI_PRIVACY_OVERRIDE
public static final int
GPS_ENC_NONE
public static final int
GPS_ENC_SUPL_GSM_DEFAULT
public static final int
GPS_ENC_SUPL_UTF8
public static final int
GPS_ENC_SUPL_UCS2
public static final int
GPS_ENC_UNKNOWN
private final android.content.Context
mContext
private final android.telephony.TelephonyManager
mTelephonyManager
private final android.telephony.PhoneStateListener
mPhoneStateListener
private final android.location.LocationManager
mLocationManager
private boolean
mPlaySounds
private boolean
mPopupImmediately
private volatile boolean
mIsSuplEsEnabled
private volatile boolean
mIsInEmergency
private volatile boolean
mIsLocationEnabled
private final android.location.INetInitiatedListener
mNetInitiatedListener
private static boolean
mIsHexInput
private final android.content.BroadcastReceiver
mBroadcastReciever
private android.app.Notification
mNiNotification
The notification that is shown when a network-initiated notification (and verification) event is received.

This is lazily created, so use {@link #setNINotification()}.

Constructors Summary
public GpsNetInitiatedHandler(android.content.Context context, android.location.INetInitiatedListener netInitiatedListener, boolean isSuplEsEnabled)


      
                                   
                                    
        mContext = context;

        if (netInitiatedListener == null) {
            throw new IllegalArgumentException("netInitiatedListener is null");
        } else {
            mNetInitiatedListener = netInitiatedListener;
        }

        setSuplEsEnabled(isSuplEsEnabled);
        mLocationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
        updateLocationMode();
        mTelephonyManager =
            (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);

        mPhoneStateListener = new PhoneStateListener() {
            @Override
            public void onCallStateChanged(int state, String incomingNumber) {
                if (DEBUG) Log.d(TAG, "onCallStateChanged(): state is "+ state);
                // listening for emergency call ends
                if (state == TelephonyManager.CALL_STATE_IDLE) {
                    setInEmergency(false);
                }
            }
        };
        mTelephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);

        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_NEW_OUTGOING_CALL);
        intentFilter.addAction(LocationManager.MODE_CHANGED_ACTION);
        mContext.registerReceiver(mBroadcastReciever, intentFilter);
    
Methods Summary
static java.lang.StringdecodeGSMPackedString(byte[] input)
Unpacks an byte array containing 7-bit packed characters into a String.

param
input a 7-bit packed char array
return
the unpacked String

        final char PADDING_CHAR = 0x00;
        int lengthBytes = input.length;
        int lengthSeptets = (lengthBytes * 8) / 7;
        String decoded;

        /* Special case where the last 7 bits in the last byte could hold a valid
         * 7-bit character or a padding character. Drop the last 7-bit character
         * if it is a padding character.
         */
        if (lengthBytes % 7 == 0) {
            if (lengthBytes > 0) {
                if ((input[lengthBytes - 1] >> 1) == PADDING_CHAR) {
                    lengthSeptets = lengthSeptets - 1;
                }
            }
        }

        decoded = GsmAlphabet.gsm7BitPackedToString(input, 0, lengthSeptets);

        // Return "" if decoding of GSM packed string fails
        if (null == decoded) {
            Log.e(TAG, "Decoding of GSM packed string failed");
            decoded = "";
        }

        return decoded;
    
private static java.lang.StringdecodeString(java.lang.String original, boolean isHex, int coding)
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 coding , after a Hex string is decoded. Generally, if the notification strings don't need further decoding, coding encoding can be set to -1, and isHex can be false.
return
the decoded string

        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;
    
static java.lang.StringdecodeUCS2String(byte[] input)

        String decoded = "";
        try {
            decoded = new String(input, "UTF-16");
        }
        catch (UnsupportedEncodingException e)
        {
            throw new AssertionError();
        }
        return decoded;
    
static java.lang.StringdecodeUTF8String(byte[] input)

        String decoded = "";
        try {
            decoded = new String(input, "UTF-8");
        }
        catch (UnsupportedEncodingException e)
        {
            throw new AssertionError();
        }
        return decoded;
    
private static java.lang.StringgetDialogMessage(com.android.internal.location.GpsNetInitiatedHandler$GpsNiNotification notif, android.content.Context context)

        return getNotifMessage(notif, context);
    
public static java.lang.StringgetDialogTitle(com.android.internal.location.GpsNetInitiatedHandler$GpsNiNotification notif, android.content.Context context)

        return getNotifTitle(notif, context);
    
private android.content.IntentgetDlgIntent(com.android.internal.location.GpsNetInitiatedHandler$GpsNiNotification notif)

        Intent intent = new Intent();
        String title = getDialogTitle(notif, mContext);
        String message = getDialogMessage(notif, mContext);

        // directly bring up the NI activity
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_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;
    
public booleangetInEmergency()

        boolean isInEmergencyCallback = Boolean.parseBoolean(
                SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE));
        return mIsInEmergency || isInEmergencyCallback;
    
public booleangetLocationEnabled()
Checks if user agreed to use location.

        return mIsLocationEnabled;
    
private static java.lang.StringgetNotifMessage(com.android.internal.location.GpsNetInitiatedHandler$GpsNiNotification notif, android.content.Context context)

        String message = String.format(context.getString(R.string.gpsNotifMessage),
                decodeString(notif.requestorId, mIsHexInput, notif.requestorIdEncoding),
                decodeString(notif.text, mIsHexInput, notif.textEncoding));
        return message;
    
private static java.lang.StringgetNotifTicker(com.android.internal.location.GpsNetInitiatedHandler$GpsNiNotification notif, android.content.Context context)

        String ticker = String.format(context.getString(R.string.gpsNotifTicker),
                decodeString(notif.requestorId, mIsHexInput, notif.requestorIdEncoding),
                decodeString(notif.text, mIsHexInput, notif.textEncoding));
        return ticker;
    
private static java.lang.StringgetNotifTitle(com.android.internal.location.GpsNetInitiatedHandler$GpsNiNotification notif, android.content.Context context)

        String title = String.format(context.getString(R.string.gpsNotifTitle));
        return title;
    
public booleangetSuplEsEnabled()

        return mIsSuplEsEnabled;
    
private voidhandleNi(com.android.internal.location.GpsNetInitiatedHandler$GpsNiNotification notif)

        if (DEBUG) Log.d(TAG, "in handleNi () :"
                        + " needNotify: " + notif.needNotify
                        + " needVerify: " + notif.needVerify
                        + " privacyOverride: " + notif.privacyOverride
                        + " mPopupImmediately: " + mPopupImmediately
                        + " mInEmergency: " + getInEmergency());

        if (!getLocationEnabled() && !getInEmergency()) {
            // Location is currently disabled, ignore all NI requests.
            try {
                mNetInitiatedListener.sendNiResponse(notif.notificationId,
                                                     GPS_NI_RESPONSE_IGNORE);
            } catch (RemoteException e) {
                Log.e(TAG, "RemoteException in sendNiResponse");
            }
        }
        if (notif.needNotify) {
        // If NI does not need verify or the dialog is not requested
        // to pop up immediately, the dialog box will not pop up.
            if (notif.needVerify && mPopupImmediately) {
                // Popup the dialog box now
                openNiDialog(notif);
            } else {
                // Show the notification
                setNiNotification(notif);
            }
        }
        // ACCEPT cases: 1. Notify, no verify; 2. no notify, no verify;
        // 3. privacy override.
        if (!notif.needVerify || notif.privacyOverride) {
            try {
                mNetInitiatedListener.sendNiResponse(notif.notificationId,
                                                     GPS_NI_RESPONSE_ACCEPT);
            } catch (RemoteException e) {
                Log.e(TAG, "RemoteException in sendNiResponse");
            }
        }
    
private voidhandleNiInEs(com.android.internal.location.GpsNetInitiatedHandler$GpsNiNotification notif)


        if (DEBUG) Log.d(TAG, "in handleNiInEs () :"
                    + " niType: " + notif.niType
                    + " notificationId: " + notif.notificationId);

        // UE is in emergency mode when in emergency call mode or in emergency call back mode
        /*
           1. When SUPL ES bit is off and UE is not in emergency mode:
                  Call handleNi() to do legacy behaviour.
           2. When SUPL ES bit is on and UE is in emergency mode:
                  Call handleNi() to do acceptance behaviour.
           3. When SUPL ES bit is off but UE is in emergency mode:
                  Ignore the emergency SUPL INIT.
           4. When SUPL ES bit is on but UE is not in emergency mode:
                  Ignore the emergency SUPL INIT.
        */
        boolean isNiTypeES = (notif.niType == GPS_NI_TYPE_EMERGENCY_SUPL);
        if (isNiTypeES != getInEmergency()) {
            try {
                mNetInitiatedListener.sendNiResponse(notif.notificationId,
                                                     GPS_NI_RESPONSE_IGNORE);
            } catch (RemoteException e) {
                Log.e(TAG, "RemoteException in sendNiResponse");
            }
        } else {
            handleNi(notif);
        }
    
public voidhandleNiNotification(com.android.internal.location.GpsNetInitiatedHandler$GpsNiNotification notif)

        if (DEBUG) Log.d(TAG, "in handleNiNotification () :"
                        + " notificationId: " + notif.notificationId
                        + " requestorId: " + notif.requestorId
                        + " text: " + notif.text
                        + " mIsSuplEsEnabled" + getSuplEsEnabled()
                        + " mIsLocationEnabled" + getLocationEnabled());

        if (getSuplEsEnabled()) {
            handleNiInEs(notif);
        } else {
            handleNi(notif);
        }

        //////////////////////////////////////////////////////////////////////////
        //   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.
        //
    
private voidopenNiDialog(com.android.internal.location.GpsNetInitiatedHandler$GpsNiNotification notif)

        Intent intent = getDlgIntent(notif);

        if (DEBUG) Log.d(TAG, "openNiDialog, notifyId: " + notif.notificationId +
                ", requestorId: " + notif.requestorId +
                ", text: " + notif.text);

        mContext.startActivity(intent);
    
public voidsetInEmergency(boolean isInEmergency)

        mIsInEmergency = isInEmergency;
    
private synchronized voidsetNiNotification(com.android.internal.location.GpsNetInitiatedHandler$GpsNiNotification notif)

        NotificationManager notificationManager = (NotificationManager) mContext
                .getSystemService(Context.NOTIFICATION_SERVICE);
        if (notificationManager == null) {
            return;
        }

        String title = getNotifTitle(notif, mContext);
        String message = getNotifMessage(notif, mContext);

        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 | Notification.FLAG_AUTO_CANCEL;
        mNiNotification.tickerText = getNotifTicker(notif, mContext);

        // 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.color = mContext.getResources().getColor(
                com.android.internal.R.color.system_notification_accent_color);
        mNiNotification.setLatestEventInfo(mContext, title, message, pi);

        notificationManager.notifyAsUser(null, notif.notificationId, mNiNotification,
                UserHandle.ALL);
    
public voidsetSuplEsEnabled(boolean isEnabled)

        mIsSuplEsEnabled = isEnabled;
    
static byte[]stringToByteArray(java.lang.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;
    
public voidupdateLocationMode()
Updates Location enabler based on location setting.

        mIsLocationEnabled = mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);