Android Location switch process analysis

Android Location switch process analysis

A colleague found that the current location of the car is flashing (after the wire flashing), and the initial value of the location (seen in the settings) is inconsistent each time. I have never touched this before, so I took it out for research today. Put together a blog.

Three working modes of location?

From the settings->location interface, location mainly has three working modes:

high_accuracy battery_saving sensors_only

Corresponding code:

//packages/apps/Settings/src/com/android/settings/location/LocationMode.java
int mode = Settings.Secure.LOCATION_MODE_OFF;//其实还有一种off模式
        if (emiter == mHighAccuracy) {
            mode = Settings.Secure.LOCATION_MODE_HIGH_ACCURACY;
        } else if (emiter == mBatterySaving) {
            mode = Settings.Secure.LOCATION_MODE_BATTERY_SAVING;
        } else if (emiter == mSensorsOnly) {
            mode = Settings.Secure.LOCATION_MODE_SENSORS_ONLY;
        }
setLocationMode(mode);

Quickly find setLocationMode

//packages/apps/Settings/src/com/android/settings/location/LocationSettingsBase.java
public void setLocationMode(int mode) {
        if (isRestricted()) {
            // Location toggling disabled by user restriction. Read the current location mode to
            // update the location master switch.
            if (Log.isLoggable(TAG, Log.INFO)) {
                Log.i(TAG, "Restricted user, not setting location mode");
            }
            mode = Settings.Secure.getInt(getContentResolver(), Settings.Secure.LOCATION_MODE,
                    Settings.Secure.LOCATION_MODE_OFF);
            if (mActive) {
                onModeChanged(mode, true);
            }
            return;
        }
        Intent intent = new Intent(MODE_CHANGING_ACTION);
        intent.putExtra(CURRENT_MODE_KEY, mCurrentMode);
        intent.putExtra(NEW_MODE_KEY, mode);
        getActivity().sendBroadcast(intent, android.Manifest.permission.WRITE_SECURE_SETTINGS);
        Settings.Secure.putInt(getContentResolver(), Settings.Secure.LOCATION_MODE, mode);
        refreshLocationMode();
    }

It seems to be operating the Settings.Secure database. Go find it directly:

private static final boolean setLocationModeForUser(ContentResolver cr, int mode,
                                                    int userId) {
  ...
    switch (mode) {
                    case LOCATION_MODE_OFF:
                        break;
                    case LOCATION_MODE_SENSORS_ONLY:
                        gps = true;
                        break;
                    case LOCATION_MODE_BATTERY_SAVING:
                        network = true;
                        break;
                    case LOCATION_MODE_HIGH_ACCURACY:
                        gps = true;
                        network = true;
                        break;
                    default:
                        throw new IllegalArgumentException("Invalid location mode: " + mode);
                }
          // Note it's important that we set the NLP mode first. The Google implementation
                // of NLP clears its NLP consent setting any time it receives a
                // LocationManager.PROVIDERS_CHANGED_ACTION broadcast and NLP is disabled. Also,
                // it shows an NLP consent dialog any time it receives the broadcast, NLP is
                // enabled, and the NLP consent is not set. If 1) we were to enable GPS first,
                // 2) a setup wizard has its own NLP consent UI that sets the NLP consent setting,
                // and 3) the receiver happened to complete before we enabled NLP, then the Google
                // NLP would detect the attempt to enable NLP and show a redundant NLP consent
                // dialog. Then the people who wrote the setup wizard would be sad.
                boolean nlpSuccess = Settings.Secure.setLocationProviderEnabledForUser(
                        cr, LocationManager.NETWORK_PROVIDER, network, userId);
                boolean gpsSuccess = Settings.Secure.setLocationProviderEnabledForUser(
                        cr, LocationManager.GPS_PROVIDER, gps, userId);
                return gpsSuccess && nlpSuccess;
}

public static final boolean setLocationProviderEnabledForUser(ContentResolver cr,
                String provider, boolean enabled, int userId) {
            synchronized (mLocationSettingsLock) {
                // to ensure thread safety, we write the provider name with a '+' or '-'
                // and let the SettingsProvider handle it rather than reading and modifying
                // the list of enabled providers.
                if (enabled) {
                    provider = "+" + provider;
                } else {
                    provider = "-" + provider;
                }
                return putStringForUser(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider,
                        userId);
            }
        }

Yes, the field is what it is: Settings.Secure.LOCATION_PROVIDERS_ALLOWED

Look at the actual machine test:

old rules, one order to get it done

adb shell settings get secure location_providers_allowed

1. Close location:

The result is empty

2. Open location, high_accuracy mode

network,gps

3. Open location, battery_saving mode

network

4. Open location, sensors_only mode

gps

That's it. It can be regarded as popular science learning!

Guess you like

Origin blog.csdn.net/bberdong/article/details/78921124