diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index c9c498ed9b38f..0e40c988164a3 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3897,6 +3897,19 @@
information. -->
No
+
+ Emergency location accessed
+
+ Your device manufacturer accessed your location during a recent emergency session
+
+ Your carrier accessed your location during a recent emergency session
+
Delete limit exceeded
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 717f326d0378f..6178fda240037 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -740,6 +740,9 @@
+
+
+
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index 34d2b73ac2db3..7750e322d728b 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -256,6 +256,10 @@ message SystemMessage {
// Package: android
NOTE_ADB_WIFI_ACTIVE = 62;
+ // Notify user there was a non-framework gnss location access during an emergency
+ // Package: android
+ NOTE_GNSS_NFW_LOCATION_ACCESS = 63;
+
// ADD_NEW_IDS_ABOVE_THIS_LINE
// Legacy IDs with arbitrary values appear below
// Legacy IDs existed as stable non-conflicting constants prior to the O release
diff --git a/services/core/java/com/android/server/location/gnss/GnssVisibilityControl.java b/services/core/java/com/android/server/location/gnss/GnssVisibilityControl.java
index 06fa0ea7791da..75fd7dca2a910 100644
--- a/services/core/java/com/android/server/location/gnss/GnssVisibilityControl.java
+++ b/services/core/java/com/android/server/location/gnss/GnssVisibilityControl.java
@@ -21,13 +21,13 @@ import android.annotation.SuppressLint;
import android.app.AppOpsManager;
import android.app.Notification;
import android.app.NotificationManager;
-import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.hardware.gnss.visibility_control.V1_0.IGnssVisibilityControlCallback;
import android.location.LocationManager;
import android.os.Handler;
import android.os.Looper;
@@ -39,12 +39,14 @@ import android.util.Log;
import com.android.internal.R;
import com.android.internal.location.GpsNetInitiatedHandler;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.util.FrameworkStatsLog;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
/**
* Handles GNSS non-framework location access user visibility and control.
@@ -283,21 +285,22 @@ class GnssVisibilityControl {
// Represents NfwNotification structure in IGnssVisibilityControlCallback.hal
private static class NfwNotification {
- // These must match with NfwResponseType enum in IGnssVisibilityControlCallback.hal.
- private static final byte NFW_RESPONSE_TYPE_REJECTED = 0;
- private static final byte NFW_RESPONSE_TYPE_ACCEPTED_NO_LOCATION_PROVIDED = 1;
- private static final byte NFW_RESPONSE_TYPE_ACCEPTED_LOCATION_PROVIDED = 2;
- private final String mProxyAppPackageName;
- private final byte mProtocolStack;
- private final String mOtherProtocolStackName;
- private final byte mRequestor;
- private final String mRequestorId;
- private final byte mResponseType;
- private final boolean mInEmergencyMode;
- private final boolean mIsCachedLocation;
+ // These must match with NfwResponseType enum in IGnssVisibilityControlCallback.hal
+ static final byte NFW_RESPONSE_TYPE_REJECTED = 0;
+ static final byte NFW_RESPONSE_TYPE_ACCEPTED_NO_LOCATION_PROVIDED = 1;
+ static final byte NFW_RESPONSE_TYPE_ACCEPTED_LOCATION_PROVIDED = 2;
- private NfwNotification(String proxyAppPackageName, byte protocolStack,
+ final String mProxyAppPackageName;
+ final byte mProtocolStack;
+ final String mOtherProtocolStackName;
+ final byte mRequestor;
+ final String mRequestorId;
+ final byte mResponseType;
+ final boolean mInEmergencyMode;
+ final boolean mIsCachedLocation;
+
+ NfwNotification(String proxyAppPackageName, byte protocolStack,
String otherProtocolStackName, byte requestor, String requestorId,
byte responseType, boolean inEmergencyMode, boolean isCachedLocation) {
mProxyAppPackageName = proxyAppPackageName;
@@ -610,43 +613,38 @@ class GnssVisibilityControl {
logEvent(nfwNotification, isPermissionMismatched);
if (nfwNotification.isLocationProvided()) {
- postEmergencyLocationUserNotification(nfwNotification);
+ displayNfwNotification(nfwNotification);
}
}
- private void postEmergencyLocationUserNotification(NfwNotification nfwNotification) {
- // Emulate deprecated IGnssNi.hal user notification of emergency NI requests.
- NotificationManager notificationManager = (NotificationManager) mContext
- .getSystemService(Context.NOTIFICATION_SERVICE);
- if (notificationManager == null) {
- Log.w(TAG, "Could not notify user of emergency location request. Notification: "
- + nfwNotification);
- return;
+ private void displayNfwNotification(NfwNotification nfwNotification) {
+ NotificationManager notificationManager = Objects.requireNonNull(
+ mContext.getSystemService(NotificationManager.class));
+
+ String title = mContext.getString(R.string.gnss_nfw_notification_title);
+ String message;
+ if (nfwNotification.mRequestor == IGnssVisibilityControlCallback.NfwRequestor.CARRIER) {
+ message = mContext.getString(R.string.gnss_nfw_notification_message_carrier);
+ } else {
+ message = mContext.getString(R.string.gnss_nfw_notification_message_oem);
}
- notificationManager.notifyAsUser(/* tag= */ null, /* notificationId= */ 0,
- createEmergencyLocationUserNotification(mContext), UserHandle.ALL);
- }
-
- private static Notification createEmergencyLocationUserNotification(Context context) {
- // NOTE: Do not reuse the returned notification object as it will not reflect
- // changes to notification text when the system language is changed.
- final String firstLineText = context.getString(R.string.gpsNotifTitle);
- final String secondLineText = context.getString(R.string.global_action_emergency);
- final String accessibilityServicesText = firstLineText + " (" + secondLineText + ")";
- return new Notification.Builder(context, SystemNotificationChannels.NETWORK_ALERTS)
- .setSmallIcon(com.android.internal.R.drawable.stat_sys_gps_on)
- .setWhen(0)
- .setOngoing(false)
+ Notification.Builder builder = new Notification.Builder(mContext,
+ SystemNotificationChannels.NETWORK_ALERTS)
+ .setSmallIcon(R.drawable.stat_sys_gps_on)
+ .setCategory(Notification.CATEGORY_SYSTEM)
+ .setVisibility(Notification.VISIBILITY_SECRET)
+ .setContentTitle(title)
+ .setTicker(title)
+ .setContentText(message)
+ .setStyle(new Notification.BigTextStyle().bigText(message))
.setAutoCancel(true)
- .setColor(context.getColor(
- com.android.internal.R.color.system_notification_accent_color))
- .setDefaults(0)
- .setTicker(accessibilityServicesText)
- .setContentTitle(firstLineText)
- .setContentText(secondLineText)
- .setContentIntent(PendingIntent.getBroadcast(context, 0, new Intent(), 0))
- .build();
+ .setColor(mContext.getColor(R.color.system_notification_accent_color))
+ .setWhen(System.currentTimeMillis())
+ .setShowWhen(true)
+ .setDefaults(0);
+
+ notificationManager.notify(SystemMessage.NOTE_GNSS_NFW_LOCATION_ACCESS, builder.build());
}
private void logEvent(NfwNotification notification, boolean isPermissionMismatched) {