android4.3 Bluetooth(le)分析之startLeScan分析

BluetoothAdapter.java中有low enery(le)的一些方法,android提供了这些方法,但源码中并未找到这些方法的调用之处。本文档主要分析这类方法的执行流程,来了解下le到底做了些什么。

本文主要就是分析下startLeScan方法(两个重载方法)。

    public boolean startLeScan(LeScanCallback callback) {
        return startLeScan(null, callback);
    }

    public boolean startLeScan(UUID[] serviceUuids, LeScanCallback callback) {
        if (DBG) Log.d(TAG, "startLeScan(): " + serviceUuids);                                                                                                           

        synchronized(mLeScanClients) {
            if (mLeScanClients.containsKey(callback)) {
                if (DBG) Log.e(TAG, "LE Scan has already started");
                return false;
            }

            try {
                //获取BluetoothGattBinder类的实例,该类的定义在GattService.java中
                IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
                if (iGatt == null) {
                    // BLE is not supported
                    return false;
                }

                UUID uuid = UUID.randomUUID();
                GattCallbackWrapper wrapper = new GattCallbackWrapper(this, callback, serviceUuids);
                //重点分析该方法。作用是为本地设备进行注册,以及启动扫描
                //wrapper是GattCallbackWrapper类的对象。该类注册了一些Gatt协议的回调方法
                iGatt.registerClient(new ParcelUuid(uuid), wrapper);
                if (wrapper.scanStarted()) {
                    mLeScanClients.put(callback, wrapper);
                    return true;
                }
            } catch (RemoteException e) {
                Log.e(TAG,"",e);
            }
        }
        return false;
    }

下面来分析下iGatt.registerClient(new ParcelUuid(uuid), wrapper)方法,路径如下:(packages/apps/Bluetooth/src/com/android/bluetooth/gatt/GattService.java::BluetoothGattBinder)

        public void registerClient(ParcelUuid uuid, IBluetoothGattCallback callback) {
            GattService service = getService();
            if (service == null) return;
            service.registerClient(uuid.getUuid(), callback);
        }

接着会调用GattService服务的同名方法

    void registerClient(UUID uuid, IBluetoothGattCallback callback) {
        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");

        if (DBG) Log.d(TAG, "registerClient() - UUID=" + uuid);
        mClientMap.add(uuid, callback);
        gattClientRegisterAppNative(uuid.getLeastSignificantBits(),
                                    uuid.getMostSignificantBits());
    }

接下来会调用jni层com_android_bluetooth_gatt.cpp文件中的gattClientRegisterAppNative方法。

static void gattClientRegisterAppNative(JNIEnv* env, jobject object,
                                        jlong app_uuid_lsb, jlong app_uuid_msb )
{
    bt_uuid_t uuid;

    if (!sGattIf) return;
    set_uuid(uuid.uu, app_uuid_msb, app_uuid_lsb);
    sGattIf->client->register_client(&uuid);
}

分析sGattIf->client->register_client(&uuid);语句

(1)sGattIf是一个静态变量,定义是static const btgatt_interface_t *sGattIf = NULL;

又是这种类型的变量。第一反应就是去找btgatt_interface_t结构体定义的头文件(一般在hardware目录),然后再搜索调用的c文件(一般在external/bluetooth/bluedroid,有时找到的c文件与头文件同名)。

btgatt_interface_t结构体的定义:hardware/libhardware/include/hardware/bt_gatt.h

/** Represents the standard Bluetooth GATT interface. */
typedef struct {
    /** Set to sizeof(btgatt_interface_t) */
    size_t          size;

    /**
     * Initializes the interface and provides callback routines
     */
    bt_status_t (*init)( const btgatt_callbacks_t* callbacks );

    /** Closes the interface */
    void (*cleanup)( void );

    /** Pointer to the GATT client interface methods.*/
    const btgatt_client_interface_t* client;

    /** Pointer to the GATT server interface methods.*/
    const btgatt_server_interface_t* server;
} btgatt_interface_t;

btgatt_interface_t结构体的对象:external/bluetooth/bluedroi/btif/src/btif_gatt.c

static const btgatt_interface_t btgattInterface = {
    sizeof(btgattInterface),

    btif_gatt_init,
    btif_gatt_cleanup,

    &btgattClientInterface,
    &btgattServerInterface,
};

回到sGattIf->client->register_client(&uuid);语句,它调用了sGattIf结构体对象中的client对象的register_client函数,那么就是btgattClientInterface对象的register_client函数。

由结构体的定义可知client对象的类型是btgatt_client_interface_t结构体。同理分析可得以下结果,

btgatt_client_interface_t结构体的定义:hardware/libhardware/include/hardware/ bt_gatt_client.h

typedef struct {
    /** Registers a GATT client application with the stack */
    bt_status_t (*register_client)( bt_uuid_t *uuid );

    /** Unregister a client application from the stack */
  bt_status_t (*unregister_client)(int client_if );
  ......
}

btgatt_client_interface_t结构体的对象:external/bluetooth/bluedroi/btif/src/btif_gatt_client.c

const btgatt_client_interface_t btgattClientInterface = {
    btif_gattc_register_app,
    btif_gattc_unregister_app,
    btif_gattc_scan,
  ......
};

因此client->register_client就是调用了btif_gattc_register_app方法[-->btif_gatt_client.c]。

static bt_status_t btif_gattc_register_app(bt_uuid_t *uuid)
{
    CHECK_BTGATT_INIT();
    btif_gattc_cb_t btif_cb;
    memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t));
    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_REGISTER_APP,
                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
}

分析btgattc_handle_event函数

static void btgattc_handle_event(uint16_t event, char* p_param)
{
    ......
    btif_gattc_cb_t* p_cb = (btif_gattc_cb_t*)p_param;
    if (!p_cb) return;

    switch (event)
    {
        case BTIF_GATTC_REGISTER_APP:
            btif_to_bta_uuid(&uuid, &p_cb->uuid);
            //为uuid注册回调函数
            BTA_GATTC_AppRegister(&uuid, bte_gattc_cback);
            break;
        .......
    }
}

分析BTA_GATTC_AppRegister函数

-------------------------------------------------------------------------------------------------------

void BTA_GATTC_AppRegister(tBT_UUID *p_app_uuid, tBTA_GATTC_CBACK *p_client_cb)
{
    tBTA_GATTC_API_REG  *p_buf;                                                                                                                                          

    /* register with BTA system manager */
  GKI_sched_lock();
  //注册Gatt客户端主事件处理函数bta_gattc_hdl_event,在bta_gatt_reg结构体中定义。
    bta_sys_register(BTA_ID_GATTC, &bta_gatt_reg);
    GKI_sched_unlock();

    if ((p_buf = (tBTA_GATTC_API_REG *) GKI_getbuf(sizeof(tBTA_GATTC_API_REG))) != NULL)
    {
        p_buf->hdr.event    = BTA_GATTC_API_REG_EVT;
        if (p_app_uuid != NULL)
            memcpy(&p_buf->app_uuid, p_app_uuid, sizeof(tBT_UUID));
        p_buf->p_cback      = p_client_cb;                                                                                                                               

        bta_sys_sendmsg(p_buf);
    }
    return;
}

(a)通过bta_sys_register函数注册了bta_gatt_reg结构体中定义的客户端主事件处理函数bta_gattc_hdl_event;然后设置event为BTA_GATTC_API_REG_EV,触发bta_gattc_hdl_event函数。

BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg)
{
    tBTA_GATTC_CB *p_cb = &bta_gattc_cb;
    tBTA_GATTC_CLCB *p_clcb = NULL;

#if BTA_GATT_DEBUG == TRUE
    APPL_TRACE_DEBUG1("bta_gattc_hdl_event: Event [%s]", gattc_evt_code(p_msg->event));
#endif
    switch (p_msg->event)
    {
        case BTA_GATTC_API_REG_EVT:
            bta_gattc_register(p_cb, (tBTA_GATTC_DATA *) p_msg);
            break;
        ......
  }
}

(b)调用bta_gattc_register函数。该函数用来注册一个客户端Gatt应用程序。

void bta_gattc_register(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data)
{
    ......
    /* callback with register event */
    if (p_data->api_reg.p_cback)
    {
        (*p_data->api_reg.p_cback)(BTA_GATTC_REG_EVT,  (tBTA_GATTC *)&cb_data);
    }
}

调用相关event(BTA_GATTC_REG_EVT)的回调函数。

到此,BTA_GATTC_AppRegister函数分析完毕,接下来分析BTA_GATTC_AppRegister(&uuid, bte_gattc_cback);中的参数部分。

ps:上述的回调函数就是这里的参数:bte_gattc_cback函数。那么BTA_GATTC_REG_EVT事件就调用该函数处理了。

-------------------------------------------------------------------------------------------------------

分析回调函数bte_gattc_cback

static void bte_gattc_cback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
{
    bt_status_t status = btif_transfer_context(btif_gattc_upstreams_evt,
                    (uint16_t) event, (void*)p_data, sizeof(tBTA_GATTC), NULL);
    ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status);
}

分析btif_gattc_upstreams_evt函数,在该函数中会处理BTA_GATTC_REG_EVT事件。

static void btif_gattc_upstreams_evt(uint16_t event, char* p_param)
{
    tBTA_GATTC *p_data = (tBTA_GATTC*)p_param;
    switch (event)
    {
        case BTA_GATTC_REG_EVT:
        {
            bt_uuid_t app_uuid;
            bta_to_btif_uuid(&app_uuid, &p_data->reg_oper.app_uuid);
            HAL_CBACK(bt_gatt_callbacks, client->register_client_cb
                , p_data->reg_oper.status
                , p_data->reg_oper.client_if
                , &app_uuid
            );
            break;
        }
    ......
  }
}

bt_gatt_callbacks对象的类型是btgatt_callbacks_t,其定义在hardware/libhardware/include/hardware/bt_gatt.h文件中。现在对bt_gatt_callbacks对象从头开始分析其来源。

在GattService.java::start()方法中,调用了initializeNative方法。继而调用JNI层initializeNative方法。贴出该方法。

static const btgatt_interface_t *sGattIf = NULL;
static const bt_interface_t* btIf;
......
static void initializeNative(JNIEnv *env, jobject object) {
    /* getBluetoothInterface 函数返回sBluetoothInterface对象,在android4.3 bt 扫描分析.docx中已说明该对象的来源*/
    if ( (btIf = getBluetoothInterface()) == NULL) {
        error("Bluetooth module is not loaded");
        return;
    }
  ......
  //(a)
  // BT_PROFILE_GATT_ID的值是”gatt”
    if ( (sGattIf = (btgatt_interface_t *)
          btIf->get_profile_interface(BT_PROFILE_GATT_ID)) == NULL) {
        error("Failed to get Bluetooth GATT Interface");
        return;
    } 

  bt_status_t status;
  //(b)
  /* sGattCallbacks的定义
  static const btgatt_callbacks_t sGattCallbacks = {
      sizeof(btgatt_callbacks_t),
      &sGattClientCallbacks,
      &sGattServerCallbacks
  };*/
    if ( (status = sGattIf->init(&sGattCallbacks)) != BT_STATUS_SUCCESS) {
        error("Failed to initialize Bluetooth GATT, status: %d", status);
        sGattIf = NULL;
        return;
    }  

    mCallbacksObj = env->NewGlobalRef(object);
}

(a) 分析

static const void* get_profile_interface (const char *profile_id)
{
    ......
#if BTA_GATT_INCLUDED == TRUE
    if (is_profile(profile_id, BT_PROFILE_GATT_ID))
        return btif_gatt_get_interface();
#endif
    return NULL;
}

分析btif_gatt_get_interface函数

const btgatt_interface_t *btif_gatt_get_interface()
{
    return &btgattInterface;
}

btgattInterface对象的类型是btgatt_interface_t结构体。再贴一遍该结构体的定义,如下:

typedef struct {
    /** Set to sizeof(btgatt_interface_t) */
    size_t          size;

    /**
     * Initializes the interface and provides callback routines
     */
    bt_status_t (*init)( const btgatt_callbacks_t* callbacks );

    /** Closes the interface */
    void (*cleanup)( void );

    /** Pointer to the GATT client interface methods.*/
    const btgatt_client_interface_t* client;

    /** Pointer to the GATT server interface methods.*/
    const btgatt_server_interface_t* server;
} btgatt_interface_t;

另,btgattInterface对象定义如下:

static const btgatt_interface_t btgattInterface = {
    sizeof(btgattInterface),

    btif_gatt_init,
    btif_gatt_cleanup,

    &btgattClientInterface,
    &btgattServerInterface,
};

所以sGattIf 就是btgattInterface对象。

(b) 接下来调用sGattIf->init函数。由上可知,即为btif_gatt_init函数。

static bt_status_t btif_gatt_init( const btgatt_callbacks_t* callbacks )
{
  /*bt_gatt_callbacks由参数赋值,该参数是sGattCallbacks。
  sGattCallbacks的定义
  static const btgatt_callbacks_t sGattCallbacks = {
      sizeof(btgatt_callbacks_t),
      &sGattClientCallbacks,
      &sGattServerCallbacks
  };*/
    bt_gatt_callbacks = callbacks;

    BTA_GATTC_Init();
    BTA_GATTS_Init();

    return BT_STATUS_SUCCESS;
}

到此为止,调用语句中bt_gatt_callbacks对象我们已经清楚了,就是sGattCallbacks对象。现在分析client->register_client_cb。

HAL_CBACK(bt_gatt_callbacks, client->register_client_cb
                , p_data->reg_oper.status
                , p_data->reg_oper.client_if
                , &app_uuid
            );

client对象是在btgatt_callbacks_t结构体中定义的一个变量,其初始化是在bt_gatt_callbacks对象(即sGattCallbacks对象)中。

btgatt_callbacks_t结构体如下:

typedef struct {
    /** Set to sizeof(btgatt_callbacks_t) */
    size_t size;

    /** GATT Client callbacks */
    const btgatt_client_callbacks_t* client;

    /** GATT Server callbacks */
    const btgatt_server_callbacks_t* server;
} btgatt_callbacks_t;

因此client对应的就是sGattCallbacks对象中的sGattClientCallbacks对象。sGattClientCallbacks对象定义如下(在JNI层的com_android_bluetooth_gatt.cpp文件中定义):

static const btgatt_client_callbacks_t sGattClientCallbacks = {
    btgattc_register_app_cb,
    btgattc_scan_result_cb,
    ......
};

而sGattClientCallbacks对象的类型是btgatt_client_callbacks_t结构体,如下

typedef struct {
    register_client_callback            register_client_cb;
    scan_result_callback                scan_result_cb;
    connect_callback                    open_cb;
    disconnect_callback                 close_cb;
    ......
} btgatt_client_callbacks_t;

因此,client->register_client_cb就是调用了sGattClientCallbacks 对象中的btgattc_register_app_cb函数。

void btgattc_register_app_cb(int status, int clientIf, bt_uuid_t *app_uuid)
{
    CHECK_CALLBACK_ENV
    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onClientRegistered, status,
        clientIf, UUID_PARAMS(app_uuid));
    checkAndClearExceptionFromCallback(sCallbackEnv, __FUNCTION__);
}

JNI层的method_onClientRegistered 函数对应java层的onClientRegistered方法[-->GattService.java]。

    void onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb)
            throws RemoteException {
        UUID uuid = new UUID(uuidMsb, uuidLsb);
        if (DBG) Log.d(TAG, "onClientRegistered() - UUID=" + uuid + ", clientIf=" + clientIf);
        ClientMap.App app = mClientMap.getByUuid(uuid);
        if (app != null) {
            app.id = clientIf;
            app.linkToDeath(new ClientDeathRecipient(clientIf));
            app.callback.onClientRegistered(status, clientIf);
        }
    }

此callback其实是GattCallbackWrapper类的对象。

分析mClientMap对象,在registerClient方法中调用了ClientMap的父类ContextMap::add方法,将GattCallbackWrapper类对象wrapper作为callback参数添加到mClientMap对象中。

接下来重新分析:

onClientRegistered方法[--->BluetoothAdapter::GattCallbackWrapper类]

        public void onClientRegistered(int status, int clientIf) {
            if (DBG) Log.d(TAG, "onClientRegistered() - status=" + status +
                           " clientIf=" + clientIf);
            synchronized(this) {
                if (mLeHandle == -1) {
                    if (DBG) Log.d(TAG, "onClientRegistered LE scan canceled");
                }

                if (status == BluetoothGatt.GATT_SUCCESS) {
                    mLeHandle = clientIf;
                    IBluetoothGatt iGatt = null;
                    try {
                        BluetoothAdapter adapter = mBluetoothAdapter.get();
                        if (adapter != null) {
                            iGatt = adapter.getBluetoothManager().getBluetoothGatt();
                            //调用startLeScan方法时,传递过来的参数为null,执行此处
                            if (mScanFilter == null) {
                                iGatt.startScan(mLeHandle, false);
                            } else {
                                ParcelUuid[] uuids = new ParcelUuid[mScanFilter.length];
                                for(int i = 0; i != uuids.length; ++i) {
                                    uuids[i] = new ParcelUuid(mScanFilter[i]);
                                }
                                iGatt.startScanWithUuids(mLeHandle, false, uuids);
                            }
                        } else {
                            Log.e(TAG, "onClientRegistered, BluetoothAdapter null");
                            mLeHandle = -1;
                        }
                    } catch (RemoteException e) {
                        Log.e(TAG, "fail to start le scan: " + e);
                        mLeHandle = -1;
                    }
            ......
        }

接下来分析startScan方法,在GattService.java中。

    void startScan(int appIf, boolean isServer) {
        ......
        if (getScanClient(appIf, isServer) == null) {
            if (DBG) Log.d(TAG, "startScan() - adding client=" + appIf);
            mScanQueue.add(new ScanClient(appIf, isServer));
        }

        gattClientScanNative(appIf, true);
    }

JNI层gattClientScanNative函数

static void gattClientScanNative(JNIEnv* env, jobject object, jint clientIf, jboolean start)
{
    if (!sGattIf) return;
    sGattIf->client->scan(clientIf, start);
}

同之前分析register_client的步骤,分析的scan函数对应btif_gattc_scan函数。

static bt_status_t btif_gattc_scan( int client_if, bool start )
{
    CHECK_BTGATT_INIT();
    btif_gattc_cb_t btif_cb;
    btif_cb.client_if = (uint8_t) client_if;
    return btif_transfer_context(btgattc_handle_event, start ? BTIF_GATTC_SCAN_START : BTIF_GATTC_SCAN_STOP,
                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
}

在btgattc_handle_event函数中处理BTIF_GATTC_SCAN_START事件

        case BTIF_GATTC_SCAN_START:
            btif_gattc_init_dev_cb();
            // BTA_DmBleObserve发出消息,包含BTA_DM_API_BLE_OBSERVE_EVT事件
            BTA_DmBleObserve(TRUE, 0, bte_scan_results_cb);
            break;

调用bte_scan_results_cb函数,

static void bte_scan_results_cb (tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data)
{
    btif_gattc_cb_t btif_cb;
    uint8_t len;

    switch (event)
    {
        case BTA_DM_INQ_RES_EVT:
            ......

        case BTA_DM_INQ_CMPL_EVT:
            ......
    btif_transfer_context(btif_gattc_upstreams_evt, BTIF_GATT_OBSERVE_EVT,
                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
}

在btif_gattc_upstreams_evt函数中处理BTIF_GATT_OBSERVE_EVT事件。

        case BTIF_GATT_OBSERVE_EVT:
        {
            btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*)p_param;
            if (!btif_gattc_find_bdaddr(p_btif_cb->bd_addr.address))
            {
                btif_gattc_add_remote_bdaddr(p_btif_cb->bd_addr.address, p_btif_cb->addr_type);
                btif_gattc_update_properties(p_btif_cb);
            }
            HAL_CBACK(bt_gatt_callbacks, client->scan_result_cb,
                      &p_btif_cb->bd_addr, p_btif_cb->rssi, p_btif_cb->value);
            break;
        }

同分析register_client_cb函数,在JNI层com_android_bluetooth_gatt.cpp文件中定义,分析得scan_result_cb对应函数btgattc_scan_result_cb。

void btgattc_scan_result_cb(bt_bdaddr_t* bda, int rssi, uint8_t* adv_data)
{
    ......
    sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onScanResult
        , address, rssi, jb);
    ......
}

对应java层文件GattService类onScanResult方法。

    void onScanResult(String address, int rssi, byte[] adv_data) {
        for (ScanClient client : mScanQueue) {
            ......
            if (!client.isServer) {
                ClientMap.App app = mClientMap.getById(client.appIf);
                if (app != null) {
                    try {
                        app.callback.onScanResult(address, rssi, adv_data);
                    } catch (RemoteException e) {
                        Log.e(TAG, "Exception: " + e);
                        mClientMap.remove(client.appIf);
                        mScanQueue.remove(client);
                    }
                }
            }
        ......
        }
  }

callback为GattCallbackWrapper类的对象,因此调用GattCallbackWrapper类中的onScanResult方法。

        public void onScanResult(String address, int rssi, byte[] advData) {
            ......
            try {
                BluetoothAdapter adapter = mBluetoothAdapter.get();
                if (adapter == null) {
                    Log.d(TAG, "onScanResult, BluetoothAdapter null");
                    return;
                }
                mLeScanCb.onLeScan(adapter.getRemoteDevice(address), rssi, advData);
            } catch (Exception ex) {
                Log.w(TAG, "Unhandled exception: " + ex);
            }
        }

mLeScanCb对象为LeScanCallback接口的对象,不过源码中并没有类来实现该接口,故只能分析到这里了。扫描到此结束,over~~

-------------------------------------------------------------------------------------------------------------

贴出流程图,see see,5个步骤:

1.startLeScan(JAVA-->JNI)

-------------------------------------------------------------------------------------------------------------

2.startLeScan(蓝牙栈)

-------------------------------------------------------------------------------------------------------------

3.startLeScan(JNI-->JAVA)

-------------------------------------------------------------------------------------------------------------

4.startLeScan(蓝牙栈)

-------------------------------------------------------------------------------------------------------------

5.startLeScan(JNI-->JAVA)

时间: 2024-10-12 20:04:23

android4.3 Bluetooth(le)分析之startLeScan分析的相关文章

Android 上千实例源码分析以及开源分析

Android 上千实例源码分析以及开源分析(百度云分享) 要下载的直接翻到最后吧,项目实例有点多. 首先 介绍几本书籍(下载包中)吧. 01_Android系统概述 02_Android系统的开发综述 03_Android的Linux内核与驱动程序 04_Android的底层库和程序 05_Android的JAVA虚拟机和JAVA环境 06_Android的GUI系统 07_Android的Audio系统 08_Android的Video 输入输出系统 09_Android的多媒体系统 10_

Bluetooth LE(低功耗蓝牙) - 第三部分

回顾 在本系列的前两篇文章中,我们已经了解了一些关于Bluetooth LE的背景并建立一个简单的Activity / Service框架.   在这篇文章中,我们将探讨Bluetooth LE的细节以及蓝牙设备查找的一些问题. 扫描并发现蓝牙设备 蓝牙设备的发现是十分简单的,它是一个在蓝牙可见范围内查找设备的过程.首先我们要做的就是在Manifest中添加必要的权限,否则我们将在一开始就碰壁.我们需要的权限是android.permission.BLUETOOTH(一般蓝牙使用)和androi

常用 Java 静态代码分析工具的分析与比较

转载自: http://www.oschina.net/question/129540_23043 简介: 本文首先介绍了静态代码分析的基本概念及主要技术,随后分别介绍了现有 4 种主流 Java 静态代码分析工具 (Checkstyle,FindBugs,PMD,Jtest),最后从功能.特性等方面对它们进行分析和比较,希望能够帮助 Java 软件开发人员了解静态代码分析工具,并选择合适的工具应用到软件开发中. 引言 在 Java 软件开发过程中,开发团队往往要花费大量的时间和精力发现并修改代

Android的Framework分析---5 ActivityManager分析

ActivityManager是android框架的一个重要部分,它负责一新ActivityThread进程创建,Activity生命周期的维护,管理系统中的Acitvity的状态切换. 这边内容还有更多内容,详细请参看ActivityManager.java ,ActivityMangaerNative.java 和SystemServcer.java 文件. 这几个的类的关系如下: 上图很清楚地描述了ActivityManager框架的几个主要类之间的关系,我们做应用开发接触很多的其实就是A

mysql 分析3使用分析sql 性能 show profiles ;

show variables like '%profiling%';    查看状态  查看时间去哪了``` set  profiling=1;// 打开 show profiles;  查看执行过的sql 语句 show profile for query 2;   找到第二条为id为2的sql生成查询计划  分析查询状态 分析sql依据 时间花费在那些地方了 时间浪费在了数据传输. 通过 show profile for query 2;找到问题所在.

Bluetooth LE(低功耗蓝牙) - 第二部分

回顾 在前面的文章中我们介绍了Bluetooth LE的背景也说明了我们在本系列文章中将要开发什么,但是还没有实际的代码.我们将在这篇文章中纠正这一点,我们将通过定义 Service/Activity 架构来确保蓝牙操作从UI中解耦. Service 与 Activity 通信 在我们继续之前,我应该指出的是,我们不打算在这篇文章中去探究BLE的细节.起初,我们打算建立一个Activity并绑定Service,它将使我们能够把所有的蓝牙操作从UI中解耦,同时让我们从BLE接收到数据后更新UI.

Bluetooth LE(低功耗蓝牙) - 第一部分

前言 在写这篇文章的时候,谷歌刚刚发布了Android Wear ,摩托罗拉也发布了 Moto 360 智能手表.Android Wear的API还是相当基本的,是很好的文档材料,而且还会不断的更新,所以我不打算写一个关于他们的教程(至少现在还没有).有趣的是 Moto 360 支持 Android 4.3及之后的版本.这明显是Bluetooth LE只有在Android 4.3及以后才被支持的原因,这也意味着 Moto 360 支持Bluetooth LE.Bluetooth LE 将不仅是可

Tomcat7.0源码分析——请求原理分析(中)

前言 在<TOMCAT7.0源码分析--请求原理分析(上)>一文中已经介绍了关于Tomcat7.0处理请求前作的初始化和准备工作,请读者在阅读本文前确保掌握<TOMCAT7.0源码分析--请求原理分析(上)>一文中的相关知识以及HTTP协议和TCP协议的一些内容.本文重点讲解Tomcat7.0在准备好接受请求后,请求过程的原理分析. 请求处理架构 在正式开始之前,我们先来看看图1中的Tomcat请求处理架构. 图1 Tomcat请求处理架构 图1列出了Tomcat请求处理架构中的主

x264源代码简单分析:宏块分析(Analysis)部分-帧间宏块(Inter)

本文记录x264的 x264_slice_write()函数中调用的x264_macroblock_analyse()的源代码.x264_macroblock_analyse()对应着x264中的分析模块.分析模块主要完成了下面2个方面的功能: (1)对于帧内宏块,分析帧内预测模式(2)对于帧间宏块,进行运动估计,分析帧间预测模式 上一篇文章记录了帧内宏块预测模式的分析,本文继续记录帧间宏块预测模式的分析. 函数调用关系图 宏块分析(Analysis)部分的源代码在整个x264中的位置如下图所示