Disable GNSS HAL when location is off

Bug: 118883298
Bug: 121176514
Test: manually
Change-Id: Iedf4427d30b317fd9d2d26469b5b4a58eb477b1f
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index b18110e..082b15a 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -24,6 +24,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.database.ContentObserver;
 import android.hardware.location.GeofenceHardware;
 import android.hardware.location.GeofenceHardwareImpl;
 import android.location.Criteria;
@@ -168,21 +169,13 @@
     private static final int AGPS_SUPL_MODE_MSA = 0x02;
     private static final int AGPS_SUPL_MODE_MSB = 0x01;
 
-    // Handler messages
-    private static final int CHECK_LOCATION = 1;
-    private static final int ENABLE = 2;
     private static final int SET_REQUEST = 3;
-    private static final int UPDATE_NETWORK_STATE = 4;
     private static final int INJECT_NTP_TIME = 5;
     private static final int DOWNLOAD_XTRA_DATA = 6;
     private static final int UPDATE_LOCATION = 7;  // Handle external location from network listener
-    private static final int ADD_LISTENER = 8;
-    private static final int REMOVE_LISTENER = 9;
     private static final int DOWNLOAD_XTRA_DATA_FINISHED = 11;
     private static final int SUBSCRIPTION_OR_CARRIER_CONFIG_CHANGED = 12;
     private static final int INITIALIZE_HANDLER = 13;
-    private static final int REQUEST_SUPL_CONNECTION = 14;
-    private static final int RELEASE_SUPL_CONNECTION = 15;
     private static final int REQUEST_LOCATION = 16;
     private static final int REPORT_LOCATION = 17; // HAL reports location
     private static final int REPORT_SV_STATUS = 18; // HAL reports SV status
@@ -311,6 +304,8 @@
     // true if we are enabled, protected by this
     private boolean mEnabled = true;
 
+    private boolean mShutdown;
+
     // states for injecting ntp and downloading xtra data
     private static final int STATE_PENDING_NETWORK = 0;
     private static final int STATE_DOWNLOADING = 1;
@@ -349,7 +344,7 @@
     private GnssPositionMode mLastPositionMode;
 
     // Current request from underlying location clients.
-    private ProviderRequest mProviderRequest = null;
+    private ProviderRequest mProviderRequest;
     // The WorkSource associated with the most recent client request (i.e, most recent call to
     // setRequest).
     private WorkSource mWorkSource = null;
@@ -371,7 +366,6 @@
     private final Looper mLooper;
     private final LocationExtras mLocationExtras = new LocationExtras();
     private final GnssStatusListenerHelper mGnssStatusListenerHelper;
-    private final GnssSatelliteBlacklistHelper mGnssSatelliteBlacklistHelper;
     private final GnssMeasurementsProvider mGnssMeasurementsProvider;
     private final GnssNavigationMessageProvider mGnssNavigationMessageProvider;
     private final LocationChangeListener mNetworkLocationListener = new NetworkLocationListener();
@@ -538,6 +532,7 @@
         }
         if (disableGps != mDisableGps) {
             mDisableGps = disableGps;
+            updateEnabled();
             updateRequirements();
         }
     }
@@ -635,23 +630,32 @@
 
         mGnssMetrics = new GnssMetrics(mBatteryStats);
         mNtpTimeHelper = new NtpTimeHelper(mContext, looper, this);
-        mGnssSatelliteBlacklistHelper = new GnssSatelliteBlacklistHelper(mContext,
-                looper, this);
-        mHandler.post(mGnssSatelliteBlacklistHelper::updateSatelliteBlacklist);
+        GnssSatelliteBlacklistHelper gnssSatelliteBlacklistHelper =
+                new GnssSatelliteBlacklistHelper(mContext,
+                        looper, this);
+        mHandler.post(gnssSatelliteBlacklistHelper::updateSatelliteBlacklist);
         mGnssBatchingProvider = new GnssBatchingProvider();
         mGnssGeofenceProvider = new GnssGeofenceProvider();
 
-        IntentFilter intentFilter = new IntentFilter();
-        intentFilter.addAction(Intent.ACTION_SHUTDOWN);
         mContext.registerReceiverAsUser(new BroadcastReceiver() {
             @Override
             public void onReceive(Context context, Intent intent) {
                 if (getSendingUserId() == UserHandle.USER_ALL) {
-                    mEnabled = false;
-                    handleDisable();
+                    mShutdown = true;
+                    updateEnabled();
                 }
             }
-        }, UserHandle.ALL, intentFilter, null, mHandler);
+        }, UserHandle.ALL, new IntentFilter(Intent.ACTION_SHUTDOWN), null, mHandler);
+
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.LOCATION_MODE),
+                true,
+                new ContentObserver(mHandler) {
+                    @Override
+                    public void onChange(boolean selfChange) {
+                        updateEnabled();
+                    }
+                }, UserHandle.USER_ALL);
 
         setProperties(PROPERTIES);
         setEnabled(true);
@@ -865,12 +869,12 @@
         return GPS_POSITION_MODE_STANDALONE;
     }
 
-    private void handleEnable() {
+    private boolean handleEnable() {
         if (DEBUG) Log.d(TAG, "handleEnable");
 
-        boolean enabled = native_init();
+        boolean inited = native_init();
 
-        if (enabled) {
+        if (inited) {
             mSupportsXtra = native_supports_xtra();
 
             // TODO: remove the following native calls if we can make sure they are redundant.
@@ -887,11 +891,10 @@
             mGnssNavigationMessageProvider.onGpsEnabledChanged();
             mGnssBatchingProvider.enable();
         } else {
-            synchronized (mLock) {
-                mEnabled = false;
-            }
             Log.w(TAG, "Failed to enable location provider");
         }
+
+        return inited;
     }
 
     private void handleDisable() {
@@ -910,6 +913,26 @@
         mGnssNavigationMessageProvider.onGpsEnabledChanged();
     }
 
+    private void updateEnabled() {
+        synchronized (mLock) {
+            boolean enabled =
+                    ((mProviderRequest != null && mProviderRequest.reportLocation
+                            && mProviderRequest.forceLocation) || (
+                            mContext.getSystemService(LocationManager.class).isLocationEnabled()
+                                    && !mDisableGps)) && !mShutdown;
+            if (enabled == mEnabled) {
+                return;
+            }
+
+            if (enabled) {
+                mEnabled = handleEnable();
+            } else {
+                mEnabled = false;
+                handleDisable();
+            }
+        }
+    }
+
     public boolean isEnabled() {
         synchronized (mLock) {
             return mEnabled;
@@ -942,6 +965,7 @@
     private void handleSetRequest(ProviderRequest request, WorkSource source) {
         mProviderRequest = request;
         mWorkSource = source;
+        updateEnabled();
         updateRequirements();
     }
 
@@ -1490,8 +1514,11 @@
             class_init_native();
             native_init_once();
             if (isEnabled()) {
-                // re-calls native_init() and other setup.
-                handleEnable();
+                synchronized (mLock) {
+                    mEnabled = false;
+                }
+                updateEnabled();
+
                 // resend configuration into the restarted HAL service.
                 reloadGpsProperties();
             }
@@ -1690,7 +1717,7 @@
                     /* requestorIdEncoding= */ 0,
                     /* textEncoding= */ 0,
                     mSuplEsEnabled,
-                    mEnabled,
+                    isEnabled(),
                     userResponse);
 
             return true;
@@ -1756,7 +1783,7 @@
                 notification.requestorIdEncoding,
                 notification.textEncoding,
                 mSuplEsEnabled,
-                mEnabled,
+                isEnabled(),
                 /* userResponse= */ 0);
     }
 
@@ -1881,9 +1908,6 @@
         public void handleMessage(Message msg) {
             int message = msg.what;
             switch (message) {
-                case ENABLE:
-                    handleEnable();
-                    break;
                 case SET_REQUEST:
                     GpsRequest gpsRequest = (GpsRequest) msg.obj;
                     handleSetRequest(gpsRequest.request, gpsRequest.source);
@@ -1998,8 +2022,7 @@
                     new NetworkLocationListener(),
                     getLooper());
 
-            // enable gps provider, it will never be disabled (legacy behavior)
-            sendEmptyMessage(ENABLE);
+            updateEnabled();
         }
     }
 
@@ -2043,8 +2066,6 @@
      */
     private String messageIdAsString(int message) {
         switch (message) {
-            case ENABLE:
-                return "ENABLE";
             case SET_REQUEST:
                 return "SET_REQUEST";
             case INJECT_NTP_TIME: