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) {