Android GPS learning (1): GPS startup process

Scan code to follow, learn together
Insert picture description here

One, Settings

Open the GPS method to write the value to the database, and then the framework layer reads the value and then processes it accordingly.

packages/apps/Settings/src/com/android/settings/location/LocationSwitchBarController.java

public void onSwitchChanged(Switch switchView, boolean isChecked) {
    
    
    mLocationEnabler.setLocationEnabled(isChecked);
}

/packages/apps/Settings/src/com/android/settings/location/LocationEnabler.java

void setLocationMode(int mode) {
    
    
    final int currentMode = Settings.Secure.getInt(mContext.getContentResolver(),
            Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
    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");
        }
        if (mListener != null) {
    
    
            mListener.onLocationModeChanged(currentMode, true);
        }
        return;
    }

    updateLocationMode(mContext, currentMode, mode, ActivityManager.getCurrentUser(),
            Settings.Secure.LOCATION_CHANGER_SYSTEM_SETTINGS);
    refreshLocationMode();
}

二、framework

The location_providers_allowed field value changes in the setting database will be monitored in the systemRunning method of LocationManagerService.

/frameworks/base/services/core/java/com/android/server/LocationManagerService.java

// listen for settings changes
mContext.getContentResolver().registerContentObserver(
        Settings.Secure.getUriFor(Settings.Secure.LOCATION_PROVIDERS_ALLOWED), true,
        new ContentObserver(mLocationHandler) {
    
    
            @Override
            public void onChange(boolean selfChange) {
    
    
                synchronized (mLock) {
    
    
                    updateProvidersLocked();
                }
            }
        }, UserHandle.USER_ALL);

If the value changes, call the updateProvidersLocked method.

private void updateProvidersLocked() {
    
    
    boolean changesMade = false;
    for (int i = mProviders.size() - 1; i >= 0; i--) {
    
    
        LocationProviderInterface p = mProviders.get(i);
        boolean isEnabled = p.isEnabled();
        String name = p.getName();
        boolean shouldBeEnabled = isAllowedByCurrentUserSettingsLocked(name);
        if (isEnabled && !shouldBeEnabled) {
    
    
            updateProviderListenersLocked(name, false);
            mLastLocation.clear();
            mLastLocationCoarseInterval.clear();
            changesMade = true;
        } else if (!isEnabled && shouldBeEnabled) {
    
    
            updateProviderListenersLocked(name, true);
            changesMade = true;
        }
    }
    if (changesMade) {
    
    
        mContext.sendBroadcastAsUser(new Intent(LocationManager.PROVIDERS_CHANGED_ACTION),
                UserHandle.ALL);
        mContext.sendBroadcastAsUser(new Intent(LocationManager.MODE_CHANGED_ACTION),
                UserHandle.ALL);
    }
}

In the updateProvidersLocked method, if gps is supported, call the updateProviderListenersLocked method.

private void updateProviderListenersLocked(String provider, boolean enabled) {
    
    
    int listeners = 0;

    LocationProviderInterface p = mProvidersByName.get(provider);
    if (p == null) return;

    ArrayList<Receiver> deadReceivers = null;

    ArrayList<UpdateRecord> records = mRecordsByProvider.get(provider);
    if (records != null) {
    
    
        for (UpdateRecord record : records) {
    
    
            if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mIdentity.mUid))) {
    
    
                // Sends a notification message to the receiver
                if (!record.mReceiver.callProviderEnabledLocked(provider, enabled)) {
    
    
                    if (deadReceivers == null) {
    
    
                        deadReceivers = new ArrayList<>();
                    }
                    deadReceivers.add(record.mReceiver);
                }
                listeners++;
            }
        }
    }

    if (deadReceivers != null) {
    
    
        for (int i = deadReceivers.size() - 1; i >= 0; i--) {
    
    
            removeUpdatesLocked(deadReceivers.get(i));
        }
    }

    if (enabled) {
    
    
        p.enable();
        if (listeners > 0) {
    
    
            applyRequirementsLocked(provider);
        }
    } else {
    
    
        p.disable();
    }
}

The enable method of GnssLocationProvider is as follows:

/frameworks/base/services/core/java/com/android/server/location/GnssLocationProvider.java

The enable method of GnssLocationProvider is as follows:

public void enable() {
    
    
    synchronized (mLock) {
    
    
        if (mEnabled) return;
        mEnabled = true;
    }

    sendMessage(ENABLE, 1, null);
}

handlenable is the message processing function of ENABLE:

private void handleEnable() {
    
    
    if (DEBUG) Log.d(TAG, "handleEnable");

    boolean enabled = native_init();

    if (enabled) {
    
    
        mSupportsXtra = native_supports_xtra();

        // TODO: remove the following native calls if we can make sure they are redundant.
        if (mSuplServerHost != null) {
    
    
            native_set_agps_server(AGPS_TYPE_SUPL, mSuplServerHost, mSuplServerPort);
        }
        if (mC2KServerHost != null) {
    
    
            native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
        }

        mGnssMeasurementsProvider.onGpsEnabledChanged();
        mGnssNavigationMessageProvider.onGpsEnabledChanged();
        mGnssBatchingProvider.enable();
    } else {
    
    
        synchronized (mLock) {
    
    
            mEnabled = false;
        }
        Log.w(TAG, "Failed to enable location provider");
    }
}

Three, HAL

native_init corresponds to the android_location_GpsLocationProvider_init function in jni, in which
sGpsInterface->init(&sGpsCallbacks) is called ,

frameworks/base/services/core/jni/com_android_server_location_GnssLocationProvider.cpp

{
    
    "native_init", "()Z", reinterpret_cast<void *>(android_location_GnssLocationProvider_init)},
static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject obj) {
    
    
    /*
     * This must be set before calling into the HAL library.
     */
    if (!mCallbacksObj)
        mCallbacksObj = env->NewGlobalRef(obj);

    /*
     * Fail if the main interface fails to initialize
     */
    if (gnssHal == nullptr) {
    
    
        ALOGE("Unable to Initialize GNSS HAL\n");
        return JNI_FALSE;
    }

    sp<IGnssCallback> gnssCbIface = new GnssCallback();

    Return<bool> result = false;
    if (gnssHal_V1_1 != nullptr) {
    
    
        result = gnssHal_V1_1->setCallback_1_1(gnssCbIface);
    } else {
    
    
        result = gnssHal->setCallback(gnssCbIface);
    }
    if (!result.isOk() || !result) {
    
    
        ALOGE("SetCallback for Gnss Interface fails\n");
        return JNI_FALSE;
    }

    sp<IGnssXtraCallback> gnssXtraCbIface = new GnssXtraCallback();
    if (gnssXtraIface == nullptr) {
    
    
        ALOGE("Unable to initialize GNSS Xtra interface\n");
    } else {
    
    
        result = gnssXtraIface->setCallback(gnssXtraCbIface);
        if (!result.isOk() || !result) {
    
    
            gnssXtraIface = nullptr;
            ALOGI("SetCallback for Gnss Xtra Interface fails\n");
        }
    }

    sp<IAGnssCallback> aGnssCbIface = new AGnssCallback();
    if (agnssIface != nullptr) {
    
    
        agnssIface->setCallback(aGnssCbIface);
    } else {
    
    
        ALOGI("Unable to Initialize AGnss interface\n");
    }

    sp<IGnssGeofenceCallback> gnssGeofencingCbIface = new GnssGeofenceCallback();
    if (gnssGeofencingIface != nullptr) {
    
    
      gnssGeofencingIface->setCallback(gnssGeofencingCbIface);
    } else {
    
    
        ALOGI("Unable to initialize GNSS Geofencing interface\n");
    }

    sp<IGnssNiCallback> gnssNiCbIface = new GnssNiCallback();
    if (gnssNiIface != nullptr) {
    
    
        gnssNiIface->setCallback(gnssNiCbIface);
    } else {
    
    
        ALOGI("Unable to initialize GNSS NI interface\n");
    }

    sp<IAGnssRilCallback> aGnssRilCbIface = new AGnssRilCallback();
    if (agnssRilIface != nullptr) {
    
    
        agnssRilIface->setCallback(aGnssRilCbIface);
    } else {
    
    
        ALOGI("Unable to Initialize AGnss Ril interface\n");
    }

    return JNI_TRUE;
}

This is to pass some functions of jni as parameters to the native c space, so that if there is available data in native c, the functions in jni will be called by callback. Simply look at the definition of location_callback:

struct GnssCallback : public IGnssCallback {
    
    
    Return<void> gnssLocationCb(const GnssLocation& location) override;
    Return<void> gnssStatusCb(const IGnssCallback::GnssStatusValue status) override;
    Return<void> gnssSvStatusCb(const IGnssCallback::GnssSvStatus& svStatus) override;
    Return<void> gnssNmeaCb(int64_t timestamp, const android::hardware::hidl_string& nmea) override;
    Return<void> gnssSetCapabilitesCb(uint32_t capabilities) override;
    Return<void> gnssAcquireWakelockCb() override;
    Return<void> gnssReleaseWakelockCb() override;
    Return<void> gnssRequestTimeCb() override;
    Return<void> gnssRequestLocationCb(const bool independentFromGnss) override;
    Return<void> gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) override;

    // New in 1.1
    Return<void> gnssNameCb(const android::hardware::hidl_string& name) override;

    // TODO(b/73306084): Reconsider allocation cost vs threadsafety on these statics
    static const char* sNmeaString;
    static size_t sNmeaStringLength;
};

Guess you like

Origin blog.csdn.net/qq_43804080/article/details/106146444