Android LocationManagerService启动(三)

接着上一篇文章
Android LocationManagerService启动(二)

GnssLocationProvider 是Java层的逻辑,大部分逻辑是Framework层的JNI代码完成的。

GnssProvider和HAL层交互的接口是native jni方法。在GnssProvider中,对应的是native_xxx的这些方法。但是,大家看源码就会发现,这些native方法的注册不在这个类里面。

GnssLocationProvider的静态代码块只有一个操作

static {
    class_init_native();
}

我们知道,jni方法的注册有两种方式,一种是静态注册,就是通过java native函数签名,生成一个包含报名的c++函数名;另一种是动态注册,通过重写JNI_OnLoad方法来实现。

Android Framework中,将核心service的jni方法,都放到了一起统一加载。

入口文件:services/core/jni/onload.cpp

using namespace android;

extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
{
    JNIEnv* env = NULL;
    jint result = -1;

    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
        ALOGE("GetEnv failed!");
        return result;
    }
    ALOG_ASSERT(env, "Could not retrieve the env!");

    register_android_server_broadcastradio_BroadcastRadioService(env);
    register_android_server_broadcastradio_Tuner(vm, env);
    register_android_server_PowerManagerService(env);
    register_android_server_SerialService(env);
    register_android_server_InputApplicationHandle(env);
    register_android_server_InputWindowHandle(env);
    register_android_server_InputManager(env);
    register_android_server_LightsService(env);
    register_android_server_AlarmManagerService(env);
    register_android_server_UsbDeviceManager(env);
    register_android_server_UsbMidiDevice(env);
    register_android_server_UsbAlsaJackDetector(env);
    register_android_server_UsbHostManager(env);
    register_android_server_vr_VrManagerService(env);
    register_android_server_VibratorService(env);
    register_android_server_SystemServer(env);
    register_android_server_location_GnssLocationProvider(env);
    register_android_server_connectivity_Vpn(env);
    register_android_server_connectivity_tethering_OffloadHardwareInterface(env);
    register_android_server_devicepolicy_CryptoTestHelper(env);
    register_android_server_ConsumerIrService(env);
    register_android_server_BatteryStatsService(env);
    register_android_server_hdmi_HdmiCecController(env);
    register_android_server_tv_TvUinputBridge(env);
    register_android_server_tv_TvInputHal(env);
    register_android_server_PersistentDataBlockService(env);
    register_android_server_HardwarePropertiesManagerService(env);
    register_android_server_storage_AppFuse(env);
    register_android_server_SyntheticPasswordManager(env);
    register_android_server_GraphicsStatsService(env);
    register_android_hardware_display_DisplayViewport(env);
    register_android_server_net_NetworkStatsService(env);
#ifdef USE_ARC
    register_android_server_ArcVideoService();
#endif
    return JNI_VERSION_1_4;
}

从上面的代码可以看出,所有android server的jni方法,都是在这里注册的,GnssLocatoinProvider的jni方法,就是通过register_android_server_location_GnssLocationProvider(env);方法注册的。

找到这个函数的文件:services/core/jni/com_android_server_location_GnssLocationProvider.cpp
实现代码如下:

int register_android_server_location_GnssLocationProvider(JNIEnv* env) {
    jniRegisterNativeMethods(
            env,
            "com/android/server/location/GnssBatchingProvider",
            sMethodsBatching,
            NELEM(sMethodsBatching));
    jniRegisterNativeMethods(
            env,
            "com/android/server/location/GnssGeofenceProvider",
            sGeofenceMethods,
            NELEM(sGeofenceMethods));
    jniRegisterNativeMethods(
            env,
            "com/android/server/location/GnssMeasurementsProvider",
            sMeasurementMethods,
            NELEM(sMeasurementMethods));
    jniRegisterNativeMethods(
            env,
            "com/android/server/location/GnssNavigationMessageProvider",
            sNavigationMessageMethods,
            NELEM(sNavigationMessageMethods));
    return jniRegisterNativeMethods(
            env,
            "com/android/server/location/GnssLocationProvider",
            sMethods,
            NELEM(sMethods));
}

上面的代码,就是jni放的注册入口了。

还记得上面提到的静态代码块里面的class_init_native方法吗?
具体的实现如下:

static void android_location_GnssLocationProvider_class_init_native(JNIEnv* env, jclass clazz) {
    gnssHal_V1_1 = IGnss_V1_1::getService();
    if (gnssHal_V1_1 == nullptr) {
        ALOGD("gnssHal 1.1 was null, trying 1.0");
        gnssHal = IGnss_V1_0::getService();
    } else {
        gnssHal = gnssHal_V1_1;
    }
}

这里我们看到了非常重要的操作:获取绑定HAL层的service
这里为了兼容,会先去获取V1_1版本的服务,如果找不到,就去获取V1_0的服务。

完成了上面的这个操作,才会有下面的init等操作。这里有两个init函数
一个是native_init_once();一个是native_init();从名字可以看出,第一个是只执行一次,第二个是可能多次执行的。

native_init_once(): 服务启动时候会调用一次,有两种情况:1. 系统启动时候会调用一次;2. HAL层服务重启了,会调用一次
分别是在

private void handleInitialize() {
    native_init_once();
    /////...../////
}

private void reportGnssServiceDied() {
    if (DEBUG) Log.d(TAG, "reportGnssServiceDied");
    mHandler.post(() -> {
        class_init_native();
        native_init_once();
        if (isEnabled()) {
            // re-calls native_init() and other setup.
            handleEnable();
            // resend configuration into the restarted HAL service.
            reloadGpsProperties(mContext, mProperties);
        }
    });
}

native_init():除了native_init_once()函数之后会执行,enable时候也会执行。

private void handleEnable() {
    if (DEBUG) Log.d(TAG, "handleEnable");
    boolean enabled = native_init();
    //////......////////
}

native_init_once() 做了什么事情呢?主要有以下几个部分:

  1. 通过jni env,获取到相关的java函数指针(reportxxx)
  2. 保存一个静态jvm变量
  3. 向hal服务注册一个DeathRecipient Observer,用于监听HAL服务的状态,如果服务异常了,jni/java层会做出相应的处理。
  4. gnss相关feature的配置,比如agps,debug,navigation等等
static void android_location_GnssLocationProvider_init_once(JNIEnv* env, jclass clazz) {
    method_reportLocation = env->GetMethodID(clazz, "reportLocation",
            "(ZLandroid/location/Location;)V");
    method_reportStatus = env->GetMethodID(clazz, "reportStatus", "(I)V");
    ////// .... 省略 ..... ///////

    /*
     * Save a pointer to JVM.
     */
    jint jvmStatus = env->GetJavaVM(&sJvm);
    if (jvmStatus != JNI_OK) {
        LOG_ALWAYS_FATAL("Unable to get Java VM. Error: %d", jvmStatus);
    }

    if (gnssHal != nullptr) {
      gnssHalDeathRecipient = new GnssDeathRecipient();
      hardware::Return<bool> linked = gnssHal->linkToDeath(
          gnssHalDeathRecipient, /*cookie*/ 0);
        if (!linked.isOk()) {
            ALOGE("Transaction error in linking to GnssHAL death: %s",
                    linked.description().c_str());
        } else if (!linked) {
            ALOGW("Unable to link to GnssHal death notifications");
        } else {
            ALOGD("Link to death notification successful");
        }

        auto gnssXtra = gnssHal->getExtensionXtra();
        if (!gnssXtra.isOk()) {
            ALOGD("Unable to get a handle to Xtra");
        } else {
            gnssXtraIface = gnssXtra;
        }

        /////....省略 ...///////
    } else {
      ALOGE("Unable to get GPS service\n");
    }
}

native_init() 做了哪些事情呢?主要包括:

  1. 保存一个java实例的对象指针mCallbacksObj,用于后面回掉Java层的接口。
  2. 创建GnssCallback并给HAL层注册
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;
    }

    ///// .... 省略 .... //////

    return JNI_TRUE;
}

做完上面两部分,基本的初始化工作就完成了,剩下的就是业务逻辑了。

这里就要注意一点,我们在实现HAL层Service的时候,如果发现GNSSProvider没有启用,那么很可能是初始化异常

posted @ 2021-01-30 16:23  hlhuang  阅读(717)  评论(0)    收藏  举报