Support SMS/WAP initiated SUPL

Support SMS/WAP NI SUPL message injection, this feature can be
enabled by setting ENABLE_NI_SUPL_MESSAGE_INJECTION=true
in gps.conf.

Test: 1. Set ENABLE_NI_SUPL_MESSAGE_INJECTION to true in gps_debug.conf
      2. Enable NFW lock
      3. atest SmsNiSuplTest
      4. Confirm the SUPL message is injected to HAL
Bug: 242105192

Change-Id: I97c59cd2d1e6e7d698cca458cf18bc2666608bf8
This commit is contained in:
Shinru Han
2022-10-12 16:24:20 +08:00
parent 3ef0cc3062
commit baeb11bcf1
8 changed files with 170 additions and 18 deletions

View File

@@ -76,6 +76,8 @@ public class GnssConfiguration {
"ENABLE_PSDS_PERIODIC_DOWNLOAD";
private static final String CONFIG_ENABLE_ACTIVE_SIM_EMERGENCY_SUPL =
"ENABLE_ACTIVE_SIM_EMERGENCY_SUPL";
private static final String CONFIG_ENABLE_NI_SUPL_MESSAGE_INJECTION =
"ENABLE_NI_SUPL_MESSAGE_INJECTION";
static final String CONFIG_LONGTERM_PSDS_SERVER_1 = "LONGTERM_PSDS_SERVER_1";
static final String CONFIG_LONGTERM_PSDS_SERVER_2 = "LONGTERM_PSDS_SERVER_2";
static final String CONFIG_LONGTERM_PSDS_SERVER_3 = "LONGTERM_PSDS_SERVER_3";
@@ -217,6 +219,14 @@ public class GnssConfiguration {
return getBooleanConfig(CONFIG_ENABLE_ACTIVE_SIM_EMERGENCY_SUPL, false);
}
/**
* Returns true if NI SUPL message injection is enabled; Returns false otherwise.
* Default false if not set.
*/
boolean isNiSuplMessageInjectionEnabled() {
return getBooleanConfig(CONFIG_ENABLE_NI_SUPL_MESSAGE_INJECTION, false);
}
/**
* Returns true if a long-term PSDS server is configured.
*/

View File

@@ -84,6 +84,7 @@ import android.os.UserHandle;
import android.os.WorkSource;
import android.os.WorkSource.WorkChain;
import android.provider.Settings;
import android.provider.Telephony.Sms.Intents;
import android.telephony.CarrierConfigManager;
import android.telephony.CellIdentity;
import android.telephony.CellIdentityGsm;
@@ -95,6 +96,7 @@ import android.telephony.CellInfoGsm;
import android.telephony.CellInfoLte;
import android.telephony.CellInfoNr;
import android.telephony.CellInfoWcdma;
import android.telephony.SmsMessage;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -107,6 +109,7 @@ import com.android.internal.app.IBatteryStats;
import com.android.internal.location.GpsNetInitiatedHandler;
import com.android.internal.location.GpsNetInitiatedHandler.GpsNiNotification;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.HexDump;
import com.android.server.FgThread;
import com.android.server.location.gnss.GnssSatelliteBlocklistHelper.GnssSatelliteBlocklistCallback;
import com.android.server.location.gnss.NtpTimeHelper.InjectNtpTimeCallback;
@@ -523,23 +526,31 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
intentFilter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DEBUG) Log.d(TAG, "receive broadcast intent, action: " + action);
if (action == null) {
return;
}
mContext.registerReceiver(mIntentReceiver, intentFilter, null, mHandler);
switch (action) {
case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED:
case TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED:
subscriptionOrCarrierConfigChanged();
break;
}
if (mNetworkConnectivityHandler.isNativeAgpsRilSupported()
&& mGnssConfiguration.isNiSuplMessageInjectionEnabled()) {
// Listen to WAP PUSH NI SUPL message.
// See User Plane Location Protocol Candidate Version 3.0,
// OMA-TS-ULP-V3_0-20110920-C, Section 8.3 OMA Push.
intentFilter = new IntentFilter();
intentFilter.addAction(Intents.WAP_PUSH_RECEIVED_ACTION);
try {
intentFilter.addDataType("application/vnd.omaloc-supl-init");
} catch (IntentFilter.MalformedMimeTypeException e) {
Log.w(TAG, "Malformed SUPL init mime type");
}
}, intentFilter, null, mHandler);
mContext.registerReceiver(mIntentReceiver, intentFilter, null, mHandler);
// Listen to MT SMS NI SUPL message.
// See User Plane Location Protocol Candidate Version 3.0,
// OMA-TS-ULP-V3_0-20110920-C, Section 8.4 MT SMS.
intentFilter = new IntentFilter();
intentFilter.addAction(Intents.DATA_SMS_RECEIVED_ACTION);
intentFilter.addDataScheme("sms");
intentFilter.addDataAuthority("localhost", "7275");
mContext.registerReceiver(mIntentReceiver, intentFilter, null, mHandler);
}
mNetworkConnectivityHandler.registerNetworkCallbacks();
@@ -560,6 +571,80 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
updateEnabled();
}
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (DEBUG) Log.d(TAG, "receive broadcast intent, action: " + action);
if (action == null) {
return;
}
switch (action) {
case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED:
case TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED:
subscriptionOrCarrierConfigChanged();
break;
case Intents.WAP_PUSH_RECEIVED_ACTION:
case Intents.DATA_SMS_RECEIVED_ACTION:
injectSuplInit(intent);
break;
}
}
};
private void injectSuplInit(Intent intent) {
if (!isNfwLocationAccessAllowed()) {
Log.w(TAG, "Reject SUPL INIT as no NFW location access");
return;
}
int slotIndex = intent.getIntExtra(SubscriptionManager.EXTRA_SLOT_INDEX,
SubscriptionManager.INVALID_SIM_SLOT_INDEX);
if (slotIndex == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
Log.e(TAG, "Invalid slot index");
return;
}
byte[] suplInit = null;
String action = intent.getAction();
if (action.equals(Intents.DATA_SMS_RECEIVED_ACTION)) {
SmsMessage[] messages = Intents.getMessagesFromIntent(intent);
if (messages == null) {
Log.e(TAG, "Message does not exist in the intent");
return;
}
for (SmsMessage message : messages) {
suplInit = message.getUserData();
injectSuplInit(suplInit, slotIndex);
}
} else if (action.equals(Intents.WAP_PUSH_RECEIVED_ACTION)) {
suplInit = intent.getByteArrayExtra("data");
injectSuplInit(suplInit, slotIndex);
}
}
private void injectSuplInit(byte[] suplInit, int slotIndex) {
if (suplInit != null) {
if (DEBUG) {
Log.d(TAG, "suplInit = "
+ HexDump.toHexString(suplInit) + " slotIndex = " + slotIndex);
}
mGnssNative.injectNiSuplMessageData(suplInit, suplInit.length , slotIndex);
}
}
private boolean isNfwLocationAccessAllowed() {
if (mGnssNative.isInEmergencySession()) {
return true;
}
if (mGnssVisibilityControl != null
&& mGnssVisibilityControl.hasLocationPermissionEnabledProxyApps()) {
return true;
}
return false;
}
/**
* Implements {@link InjectNtpTimeCallback#injectTime}
*/

View File

@@ -762,6 +762,10 @@ class GnssNetworkConnectivityHandler {
return APN_INVALID;
}
protected boolean isNativeAgpsRilSupported() {
return native_is_agps_ril_supported();
}
// AGPS support
private native void native_agps_data_conn_open(long networkHandle, String apn, int apnIpType);

View File

@@ -437,6 +437,10 @@ class GnssVisibilityControl {
return locationPermissionEnabledProxyApps;
}
public boolean hasLocationPermissionEnabledProxyApps() {
return getLocationPermissionEnabledProxyApps().length > 0;
}
private void handleNfwNotification(NfwNotification nfwNotification) {
if (DEBUG) Log.d(TAG, "Non-framework location access notification: " + nfwNotification);

View File

@@ -989,6 +989,14 @@ public class GnssNative {
mGnssHal.injectPsdsData(data, length, psdsType);
}
/**
* Injects NI SUPL message data into the GNSS HAL.
*/
public void injectNiSuplMessageData(byte[] data, int length, int slotIndex) {
Preconditions.checkState(mRegistered);
mGnssHal.injectNiSuplMessageData(data, length, slotIndex);
}
@NativeEntryPoint
void reportGnssServiceDied() {
// Not necessary to clear (and restore) binder identity since it runs on another thread.
@@ -1278,7 +1286,7 @@ public class GnssNative {
}
@NativeEntryPoint
boolean isInEmergencySession() {
public boolean isInEmergencySession() {
return Binder.withCleanCallingIdentity(
() -> mEmergencyHelper.isInEmergency(
TimeUnit.SECONDS.toMillis(mConfiguration.getEsExtensionSec())));
@@ -1507,6 +1515,10 @@ public class GnssNative {
protected void injectPsdsData(byte[] data, int length, int psdsType) {
native_inject_psds_data(data, length, psdsType);
}
protected void injectNiSuplMessageData(byte[] data, int length, int slotIndex) {
native_inject_ni_supl_message_data(data, length, slotIndex);
}
}
// basic APIs
@@ -1650,6 +1662,9 @@ public class GnssNative {
private static native void native_agps_set_ref_location_cellid(int type, int mcc, int mnc,
int lac, long cid, int tac, int pcid, int arfcn);
private static native void native_inject_ni_supl_message_data(byte[] data, int length,
int slotIndex);
// PSDS APIs
private static native boolean native_supports_psds();

View File

@@ -482,6 +482,17 @@ static void android_location_gnss_hal_GnssNative_agps_set_id(JNIEnv* env, jclass
agnssRilIface->setSetId(type, setid_string);
}
static void android_location_gnss_hal_GnssNative_inject_ni_supl_message_data(JNIEnv* env, jclass,
jbyteArray data,
jint length,
jint slotIndex) {
if (agnssRilIface == nullptr) {
ALOGE("%s: IAGnssRil interface not available.", __func__);
return;
}
agnssRilIface->injectNiSuplMessageData(data, length, slotIndex);
}
static jint android_location_gnss_hal_GnssNative_read_nmea(JNIEnv* env, jclass,
jbyteArray nmeaArray, jint buffer_size) {
return gnssHal->readNmea(nmeaArray, buffer_size);
@@ -974,6 +985,8 @@ static const JNINativeMethod sLocationProviderMethods[] = {
android_location_gnss_hal_GnssNative_agps_set_reference_location_cellid)},
{"native_set_agps_server", "(ILjava/lang/String;I)V",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_set_agps_server)},
{"native_inject_ni_supl_message_data", "([BII)V",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_inject_ni_supl_message_data)},
{"native_send_ni_response", "(II)V",
reinterpret_cast<void*>(android_location_gnss_hal_GnssNative_send_ni_response)},
{"native_get_internal_state", "()Ljava/lang/String;",

View File

@@ -84,8 +84,19 @@ jboolean AGnssRil::updateNetworkState(jboolean connected, jint type, jboolean ro
networkAttributes.capabilities = static_cast<int32_t>(capabilities),
networkAttributes.apn = jniApn.c_str();
auto result = mIAGnssRil->updateNetworkState(networkAttributes);
return checkAidlStatus(result, "IAGnssRilAidl updateNetworkState() failed.");
auto status = mIAGnssRil->updateNetworkState(networkAttributes);
return checkAidlStatus(status, "IAGnssRilAidl updateNetworkState() failed.");
}
jboolean AGnssRil::injectNiSuplMessageData(const jbyteArray& msgData, jint length, jint slotIndex) {
JNIEnv* env = getJniEnv();
jbyte* bytes = reinterpret_cast<jbyte*>(env->GetPrimitiveArrayCritical(msgData, 0));
auto status = mIAGnssRil->injectNiSuplMessageData(std::vector<uint8_t>((const uint8_t*)bytes,
(const uint8_t*)bytes +
length),
static_cast<int>(slotIndex));
env->ReleasePrimitiveArrayCritical(msgData, bytes, JNI_ABORT);
return checkAidlStatus(status, "IAGnssRil injectNiSuplMessageData() failed.");
}
// Implementation of AGnssRil_V1_0
@@ -151,6 +162,11 @@ jboolean AGnssRil_V1_0::updateNetworkState(jboolean connected, jint type, jboole
return checkHidlReturn(result, "IAGnssRil_V1_0 updateNetworkState() failed.");
}
jboolean AGnssRil_V1_0::injectNiSuplMessageData(const jbyteArray&, jint, jint) {
ALOGI("IAGnssRil_V1_0 interface does not support injectNiSuplMessageData.");
return JNI_FALSE;
}
// Implementation of AGnssRil_V2_0
AGnssRil_V2_0::AGnssRil_V2_0(const sp<IAGnssRil_V2_0>& iAGnssRil)

View File

@@ -43,6 +43,8 @@ public:
virtual jboolean updateNetworkState(jboolean connected, jint type, jboolean roaming,
jboolean available, const jstring& apn, jlong networkHandle,
jshort capabilities) = 0;
virtual jboolean injectNiSuplMessageData(const jbyteArray& msgData, jint length,
jint slotIndex) = 0;
};
class AGnssRil : public AGnssRilInterface {
@@ -55,6 +57,8 @@ public:
jboolean updateNetworkState(jboolean connected, jint type, jboolean roaming, jboolean available,
const jstring& apn, jlong networkHandle,
jshort capabilities) override;
jboolean injectNiSuplMessageData(const jbyteArray& msgData, jint length,
jint slotIndex) override;
private:
const sp<android::hardware::gnss::IAGnssRil> mIAGnssRil;
@@ -70,6 +74,7 @@ public:
jboolean updateNetworkState(jboolean connected, jint type, jboolean roaming, jboolean available,
const jstring& apn, jlong networkHandle,
jshort capabilities) override;
jboolean injectNiSuplMessageData(const jbyteArray&, jint, jint) override;
private:
const sp<android::hardware::gnss::V1_0::IAGnssRil> mAGnssRil_V1_0;