opp分析(ACTION_DEVICE_SELECTED)

选择设备之后就是发送了一个BluetoothDevicePicker.ACTION_DEVICE_SELECTEDbroadcast来通知我们选择了某个设备进行文件的传输。对这个broadcast的监听就只有一个,就是BluetoothOppReceiver.cpp


设备点击之后,会发送一个ACTION_DEVICE_SELECTEDbroadcast,BluetoothOppReceiver收到这个broadcast后,会启动insertThread来把需要分享的文件内容加入到对应的数据库中并引起后续的发送操作,同时在ui上显示“正在向**发送文件”的toast


  else if (action->equals(BluetoothDevicePicker::ACTION_DEVICE_SELECTED())) {

        sp<BluetoothOppManager> mOppManager = BluetoothOppManager::getInstance(context);
//得到选中的设备
        sp<BluetoothDevice> remoteDevice = safe_cast<BluetoothDevice *>(intent->getParcelableExtra(BluetoothDevice::EXTRA_DEVICE()));

        GLOGV("Received BT device selected intent, bt device: %s", SP_TOSTRING_STR(remoteDevice));

        // Insert transfer session record to database
         mOppManager->startTransfer(remoteDevice);

   

//显示正在向。。。传输文件的信息

        sp<String> deviceName = mOppManager->getDeviceName(remoteDevice);
        int32_t batchSize = mOppManager->getBatchSize();
        
        if (mOppManager->mMultipleFlag) {
            mToastText = context->getString(R::string::bt_toast_5, Integer::toString(batchSize)->string(),deviceName->string());
        } else {
            mToastText = context->getString(R::string::bt_toast_4, deviceName->string());
        }

        Toast::makeText(context,mToastText, Toast::LENGTH_SHORT)->show();

    }




void BluetoothOppManager::startTransfer(const sp<BluetoothDevice>& device) {
    GLOGENTRY();
    GLOGI("Active InsertShareThread number is : %d", mInsertShareThreadNum);
        sp<InsertShareInfoThread> insertThread;
        {
            RecursiveMutex::Autolock _l(mBluetoothOppManagerMutex);
            if (mInsertShareThreadNum > ALLOWED_INSERT_SHARE_THREAD_NUMBER) {
                LOGE("Too many shares user triggered concurrently!");
                return;
            /*
                // Notice user
                // TODO TODO TODO
                // check due to different translation
                // sp<Intent> in = new Intent(mContext, BluetoothOppBtErrorActivity.class);
                sp<Intent> in = new Intent();
                sp<ComponentName> component = new ComponentName(sp<String>(new String("BluetoothOppPbapService")), sp<String>(new String("BluetoothOppBtErrorActivity")));
                in->setComponent(component);

                in->setFlags(Intent::FLAG_ACTIVITY_NEW_TASK);
                // TODO TODO TODO
                // check due to different translation
                // in->putExtra(new String("title"), mContext->getString(R.string.enabling_progress_title));
                // in->putExtra(new String("content"), mContext->getString(R.string.ErrorTooManyRequests));
                in->putExtra(new String("title"), mContext->getString(R::string::enabling_progress_title));
                in->putExtra(new String("content"), mContext->getString(R::string::ErrorTooManyRequests));
                mContext->startActivity(in);

                return;
            */
            }
            insertThread = new InsertShareInfoThread(device, mMultipleFlag, mMimeTypeOfSendingFile,
                    mUriOfSendingFile, mMimeTypeOfSendingFiles, mUrisOfSendingFiles,

                    mIsHandoverInitiated, this);
            if (mMultipleFlag) {
                mfileNumInBatch = mUrisOfSendingFiles->size();
            }
        }

        insertThread->run("Insert ShareInfo Thread");
}


BluetoothOppManager::InsertShareInfoThread::InsertShareInfoThread(const sp<BluetoothDevice>& device, bool multiple,
        const sp<String>& typeOfSingleFile, const sp<String>& uri, const sp<String>& typeOfMultipleFiles,
        const sp<GArrayList<Uri> >& uris, bool handoverInitiated,  const wp<BluetoothOppManager>& bluetoothoppmanager)
    : PREINIT_DYNAMIC()
    , mRemoteDevice(device)
    , mTypeOfSingleFile(typeOfSingleFile)
    , mUri(uri)
    , mTypeOfMultipleFiles(typeOfMultipleFiles)
    , mUris(uris)
    , mIsMultiple(multiple)
    , mIsHandoverInitiated(handoverInitiated)
    , condition(false)
    , mwpbtom(bluetoothoppmanager) {
    GLOGENTRY();
    sp<BluetoothOppManager> mspbtom = mwpbtom.promote();
    CHECK_NULL_POINTER_RETURN(mspbtom);

    {
        RecursiveMutex::Autolock _l(mspbtom->mBluetoothOppManagerMutex);
        mspbtom->mInsertShareThreadNum++;
    }
    GLOGV("Thread id is: %d", this->getTid());
}


bool BluetoothOppManager::InsertShareInfoThread::threadLoop() {
    GLOGENTRY();
    sp<BluetoothOppManager> mspbtom = mwpbtom.promote();
    CHECK_NULL_POINTER_RETURN_FALSE(mspbtom);

    Process::setThreadPriority(Process::THREAD_PRIORITY_BACKGROUND);

    Looper::prepare();

    if (mRemoteDevice == NULL) {
        LOGE("Target bt device is null!");
        return false;
    }
    if (mIsMultiple) {
        insertMultipleShare();
    } else {
        insertSingleShare();
    }
    {
        RecursiveMutex::Autolock _l(mspbtom->mBluetoothOppManagerMutex);
        mspbtom->mInsertShareThreadNum--;
    }

    mConLock.lock();
    condition = true;
    mThreadStartCondition.broadcast();
    mConLock.unlock();

    Looper::loop();
    return false;
}



void BluetoothOppManager::InsertShareInfoThread::insertSingleShare() {
    GLOGENTRY();
    sp<BluetoothOppManager> mspbtom = mwpbtom.promote();
    CHECK_NULL_POINTER_RETURN(mspbtom);

    sp<ContentValues> values = new ContentValues();
    values->put(BluetoothShare::URI(), mUri);
    values->put(BluetoothShare::MIMETYPE(), mTypeOfSingleFile);
    values->put(BluetoothShare::DESTINATION(), mRemoteDevice->getAddress());
    if (mIsHandoverInitiated) {
        values->put(BluetoothShare::USER_CONFIRMATION(), BluetoothShare::USER_CONFIRMATION_HANDOVER_CONFIRMED);
    }
    sp<Uri> contentUri = mspbtom->mContext->getContentResolver()->insert(BluetoothShare::CONTENT_URI(), values);
    GLOGI("Insert contentUri: %s  to device: %s", SP_TOSTRING_STR(contentUri), SP_STRING_STR(mspbtom->getDeviceName(mRemoteDevice)));
}

insert的处理有以下几个比较重要的操作:

1)创建一个可读/可写的database

2)启动了BluetoothOppService

3)通知database的改变,调用对应的onChange函数



sp<Uri> BluetoothOppProvider::insert(const sp<Uri>& uri, const sp<ContentValues>& values) {
    GLOGENTRY();
    GLOGI("BluetoothOppProvider insert");

//创建一个可读可写的数据
    sp<SQLiteDatabase> db = mOpenHelper->getWritableDatabase();

    sp<UriMatcher> urimatcher = sURIMatcher();
    CHECK_NULL_POINTER_RETURN_NULL(urimatcher);

    GLOGI("BluetoothOppProvider::insert 1");
    int32_t match = urimatcher->match(uri);
    GLOGI("BluetoothOppProvider::insert 2");

    if (match != SHARES) {
        GLOGD("calling insert on an unknown/invalid URI: %s" , SP_TOSTRING_STR(uri));
    }

    sp<ContentValues> filteredValues = new ContentValues();
//得到对应values中的信息
    copyString(BluetoothShare::URI(), values, filteredValues);
    copyString(BluetoothShare::FILENAME_HINT(), values, filteredValues);
    copyString(BluetoothShare::MIMETYPE(), values, filteredValues);
    copyString(BluetoothShare::DESTINATION(), values, filteredValues);

    copyInteger(BluetoothShare::VISIBILITY(), values, filteredValues);
    copyInteger(BluetoothShare::TOTAL_BYTES(), values, filteredValues);

    // if (values->getAsInteger(BluetoothShare::VISIBILITY()) == NULL) {
    filteredValues->put(BluetoothShare::VISIBILITY(), BluetoothShare::VISIBILITY_VISIBLE);
    // }
    int32_t dir = values->getAsInteger(BluetoothShare::DIRECTION());
    int32_t con = values->getAsInteger(BluetoothShare::USER_CONFIRMATION());
    sp<String> address = values->getAsString(BluetoothShare::DESTINATION());

    if (values->getAsInteger(BluetoothShare::DIRECTION()) == 0) {
        dir = BluetoothShare::DIRECTION_OUTBOUND;
    }
    if (dir == BluetoothShare::DIRECTION_OUTBOUND && con == 0) {
        con = BluetoothShare::USER_CONFIRMATION_AUTO_CONFIRMED;
    }
    if (dir == BluetoothShare::DIRECTION_INBOUND && con == 0) {
        con = BluetoothShare::USER_CONFIRMATION_PENDING;
    }
    filteredValues->put(BluetoothShare::USER_CONFIRMATION(), con);
    filteredValues->put(BluetoothShare::DIRECTION(), dir);

    filteredValues->put(BluetoothShare::STATUS(), BluetoothShare::STATUS_PENDING);
    filteredValues->put(Constants::MEDIA_SCANNED(), 0);

    int64_t ts = values->getAsLong(BluetoothShare::TIMESTAMP());
    if (ts == 0) {
        ts = System::currentTimeMillis();
    }
    filteredValues->put(BluetoothShare::TIMESTAMP(), ts);

    GLOGI("start BluetoothOppService");

    sp<Context> context = getContext();

    sp<Intent> intent = new Intent();
    sp<ComponentName> component = new ComponentName(sp<String>(new String("BluetoothOppPbapService")), sp<String>(new String("BluetoothOppService")));
    intent->setComponent(component);
//启动BluetoothOppService这个服务
    context->startService(intent);
    // context->startService(new Intent(context, Class::forName(new String("BluetoothOppService"))));

    int64_t rowID = db->insert(DB_TABLE(), NULL, filteredValues);

    sp<Uri> ret = NULL;

    if (rowID != -1) {
        GLOGI("rowID is not -1");

//再次启动这个服务
        context->startService(intent);
        // context->startService(new Intent(context, Class::forName(new String("BluetoothOppService"))));
        ret = Uri::parse(BluetoothShare::CONTENT_URI()->toString() + String("/") + String(rowID));

//通知数据库的变化
        context->getContentResolver()->notifyChange(uri, NULL);
    } else {
        GLOGD("couldn't insert into btopp database");
    }

    return ret;
}


监听数据库变化的:
mObserver = new BluetoothShareContentObserver();
        getContentResolver().registerContentObserver(BluetoothShare.CONTENT_URI, true, mObserver);
注:将文件加入数据库后,在BluetoothOppService的内部类BluetoothShareContentObserver会收到数据改变的事件,调用onChange()-----updateFromProvider()---updatethread;
updatethread里调用insertShare,这函数里面用到BluetoothOppTransfer,然后启动了BluetoothOppTransfer(mTransfer.start();)。


void BluetoothOppService::BluetoothShareContentObserver::onChange(bool selfChange) {
    GLOGENTRY();
    sp<BluetoothOppService> mspbtoppser = mBtOppService.promote();
    GLOGD("BluetoothOppService:: ContentObserver received notification");
    mspbtoppser->updateFromProvider();
}

void BluetoothOppService::updateFromProvider() {
    GLOGENTRY();
    GLOGI("updateFromProvider");
    RecursiveMutex::Autolock _l(mBluetoothOppServiceMutex);

    mPendingUpdate = true;
    if (mUpdateThread == NULL) {
        GLOGD("BluetoothOppService:: UpdateThread count %d", getStrongCount());
        mUpdateThread = new UpdateThread(this);
        GLOGD("BluetoothOppService:: UpdateThread count %d", getStrongCount());
        mUpdateThread->run("Bluetooth Share Service");
    }
}

void BluetoothOppService::insertShare(const sp<Cursor>& cursor, int32_t arrayPos) {
    GLOGENTRY();
    GLOGI("insertShare");
    sp<BluetoothOppShareInfo> info = new BluetoothOppShareInfo(
            cursor->getInt(cursor->getColumnIndexOrThrow(BluetoothShare::_ID)),
            cursor->getString(cursor->getColumnIndexOrThrow(BluetoothShare::URI())),
            cursor->getString(cursor->getColumnIndexOrThrow(BluetoothShare::FILENAME_HINT())),
            cursor->getString(cursor->getColumnIndexOrThrow(BluetoothShare::_DATA())),
            cursor->getString(cursor->getColumnIndexOrThrow(BluetoothShare::MIMETYPE())),
            cursor->getInt(cursor->getColumnIndexOrThrow(BluetoothShare::DIRECTION())),
            cursor->getString(cursor->getColumnIndexOrThrow(BluetoothShare::DESTINATION())),
            cursor->getInt(cursor->getColumnIndexOrThrow(BluetoothShare::VISIBILITY())),
            cursor->getInt(cursor->getColumnIndexOrThrow(BluetoothShare::USER_CONFIRMATION())),
            cursor->getInt(cursor->getColumnIndexOrThrow(BluetoothShare::STATUS())),
            cursor->getInt(cursor->getColumnIndexOrThrow(BluetoothShare::TOTAL_BYTES())),
            cursor->getInt(cursor->getColumnIndexOrThrow(BluetoothShare::CURRENT_BYTES())),
            cursor->getInt(cursor->getColumnIndexOrThrow(BluetoothShare::TIMESTAMP())),
            cursor->getInt(cursor->getColumnIndexOrThrow(Constants::MEDIA_SCANNED())) != Constants::MEDIA_SCANNED_NOT_SCANNED);

    GLOGI("Service adding new entry");
    GLOGV("ID      : %d", info->mId);
    // Log.v(TAG, "URI     : " + ((info.mUri != null) ? "yes" : "no"));
    GLOGV("URI     : %s", SP_STRING_STR(info->mUri));
    GLOGI("HINT    : %s", SP_STRING_STR(info->mHint));
    GLOGI("FILENAME: %s", SP_STRING_STR(info->mFilename));
    GLOGV("MIMETYPE: %s", SP_STRING_STR(info->mMimetype));
    GLOGV("DIRECTION: %d", info->mDirection);
    GLOGV("DESTINAT: %s", SP_STRING_STR(info->mDestination));
    GLOGV("VISIBILI: %d", info->mVisibility);
    GLOGI("CONFIRM : %d", info->mConfirm);
    GLOGI("STATUS  : %d", info->mStatus);
    GLOGV("TOTAL   : %d", info->mTotalBytes);
    GLOGV("CURRENT : %d", info->mCurrentBytes);
    GLOGV("TIMESTAMP : %lld", info->mTimestamp);
    GLOGV("SCANNED : %d", info->mMediaScanned);

    mShares->add(arrayPos, info);

    /* Mark the info as failed if it's in invalid status */
    if (info->isObsolete()) {
        Constants::updateShareStatus(this, info->mId, BluetoothShare::STATUS_UNKNOWN_ERROR);
        GLOGD("BluetoothOppService:: Constants::updateShareStatus count %d", getStrongCount());
    }
    /*
     * Add info into a batch. The logic is
     * 1) Only add valid and readyToStart info
     * 2) If there is no batch, create a batch and insert this transfer into batch,
     * then run the batch
     * 3) If there is existing batch and timestamp match, insert transfer into batch
     * 4) If there is existing batch and timestamp does not match, create a new batch and
     * put in queue
     */

    if (info->isReadyToStart()) {
        if (info->mDirection == BluetoothShare::DIRECTION_OUTBOUND) {
            /* check if the file exists */
            sp<InputStream> i;
#if 0
            try {
                i = getContentResolver()->openInputStream(Uri::parse(info->mUri));
            } catch(FileNotFoundException e) {
                Log.e(TAG, "Can't open file for OUTBOUND info " + info.mId);
                Constants.updateShareStatus(this, info.mId, BluetoothShare.STATUS_BAD_REQUEST);
                return;
            } catch(SecurityException e) {
                Log.e(TAG, "Exception:" + e.toString() + " for OUTBOUND info " + info.mId);
                Constants.updateShareStatus(this, info.mId, BluetoothShare.STATUS_BAD_REQUEST);
                return;
            }
#endif  // mark
            // TODO TODO TODO
            // check due to different translation
            i = getContentResolver()->openInputStream(Uri::parse(info->mUri));
            if (i == NULL) {
                LOGE("Can't open file for OUTBOUND info %d", info->mId);
                Constants::updateShareStatus(this, info->mId, BluetoothShare::STATUS_BAD_REQUEST);
                GLOGD("BluetoothOppService:: Constants::updateShareStatus count %d", getStrongCount());
                return;
            }
            // try {
                i->close();
            // } catch(IOException ex) {
            //    LOGE("IO error when close file for OUTBOUND info %d", info->mId);
            //    return;
            // }
        }
        if (mBatchs->size() == 0) {
            sp<BluetoothOppBatch> newBatch = new BluetoothOppBatch(this, info);
            newBatch->mId = mBatchId;
            mBatchId++;
            mBatchs->add(newBatch);
            if (info->mDirection == BluetoothShare::DIRECTION_OUTBOUND) {
                GLOGI("Service create new Batch %d for OUTBOUND info %d", newBatch->mId, info->mId);
                mTransfer = new BluetoothOppTransfer(this, mPowerManager, newBatch);
                GLOGD("BluetoothOppService:: BluetoothOppTransfer count %d", getStrongCount());
            } else if (info->mDirection == BluetoothShare::DIRECTION_INBOUND) {
                GLOGI("Service create new Batch %d for INBOUND info %d", newBatch->mId, info->mId);
                mServerTransfer = new BluetoothOppTransfer(this, mPowerManager, newBatch, mServerSession);
                GLOGD("BluetoothOppService:: BluetoothOppTransfer count %d", getStrongCount());
            }

            if (info->mDirection == BluetoothShare::DIRECTION_OUTBOUND && mTransfer != NULL) {
                GLOGI("Service start transfer new Batch %d for info %d", newBatch->mId, info->mId);
                mTransfer->start();
            } else if (info->mDirection == BluetoothShare::DIRECTION_INBOUND && mServerTransfer != NULL) {
                GLOGI("Service start server transfer new Batch %d for info %d", newBatch->mId, info->mId);
                mServerTransfer->start();
            }

        } else {
            int32_t i = findBatchWithTimeStamp(info->mTimestamp);
            if (i != -1) {
                GLOGI("Service add info %d to existing batch %d", info->mId, mBatchs->get(i)->mId);
                mBatchs->get(i)->addShare(info);
            } else {
                // There is ongoing batch
                sp<BluetoothOppBatch> newBatch = new BluetoothOppBatch(this, info);
                GLOGD("BluetoothOppService:: BluetoothOppBatch count %d", getStrongCount());
                newBatch->mId = mBatchId;
                mBatchId++;
                mBatchs->add(newBatch);
                GLOGI("Service add new Batch %d for info %d", newBatch->mId, info->mId);
                if (Constants::USE_TCP_DEBUG && !Constants::USE_TCP_SIMPLE_SERVER) {
                    // only allow  concurrent serverTransfer in debug mode
                    if (info->mDirection == BluetoothShare::DIRECTION_INBOUND) {
                        GLOGV("TCP_DEBUG start server transfer new Batch %d for info %d", newBatch->mId, info->mId);
                        mServerTransfer = new BluetoothOppTransfer(this, mPowerManager, newBatch, mServerSession);
                        GLOGD("BluetoothOppService:: BluetoothOppTransfer count %d", getStrongCount());
                        mServerTransfer->start();
                    }
                }
            }
        }
    }
}


void BluetoothOppTransfer::start() {
    GLOGENTRY();
    /* check Bluetooth enable status */
    /*
     * normally it's impossible to reach here if BT is disabled. Just check
     * for safety
     */
    if (!mAdapter->isEnabled()) {
        LOGE("Can't start transfer when Bluetooth is disabled for %d", mBatch->mId);
        markBatchFailed();
        mBatch->mStatus = Constants::BATCH_STATUS_FAILED;
        return;
    }

    if (mHandlerThread == NULL) {
        GLOGI("Create handler thread for batch %d", mBatch->mId);
        mHandlerThread = new HandlerThread(new String("BtOpp Transfer Handler"), Process::THREAD_PRIORITY_BACKGROUND);
        mHandlerThread->run();
        mSessionHandler = new EventHandler(mHandlerThread->getLooper(), this);

        GLOGI("mBatch->mDirection = %lld", mBatch->mDirection);

        if (mBatch->mDirection == BluetoothShare::DIRECTION_OUTBOUND) {
            /* for outbound transfer, we do connect first */
            startConnectSession();
        } else if (mBatch->mDirection == BluetoothShare::DIRECTION_INBOUND) {
            /*
             * for inbound transfer, it's already connected, so we start
             * OBEX session directly
             */
            startObexSession();
        }
    }
}

void BluetoothOppTransfer::startConnectSession() {
    GLOGENTRY();
    sp<Context> mspContext = mContext.promote();
    CHECK_NULL_POINTER_RETURN(mspContext);

    if (Constants::USE_TCP_DEBUG) {
        mConnectThread = new SocketConnectThread(new String("localhost"), Constants::TCP_DEBUG_PORT, 0, this);
        mConnectThread->run();
    } else {
        int32_t channel = BluetoothOppPreference::getInstance(mspContext)->getChannel(mBatch->mDestination, OPUSH_UUID16);
        if (channel != -1) {

            GLOGI("Get OPUSH channel %d from cache for %s", channel, SP_TOSTRING_STR(mBatch->mDestination));
            mTimestamp = System::currentTimeMillis();
            mSessionHandler->obtainMessage(SDP_RESULT, channel, -1, mBatch->mDestination)->sendToTarget();
        } else {
            doOpushSdp();
        }
    }
}



void BluetoothOppTransfer::doOpushSdp() {
    GLOGENTRY();
    GLOGI("Do Opush SDP request for address %s", SP_TOSTRING_STR(mBatch->mDestination));

    sp<Context> mspContext = mContext.promote();
    CHECK_NULL_POINTER_RETURN(mspContext);

    mTimestamp = System::currentTimeMillis();

    int32_t channel;
    channel = mBatch->mDestination->getServiceChannel(BluetoothUuid::ObexObjectPush());
    if (channel != -1) {
        GLOGD("Get OPUSH channel %d from SDP for %s", channel, SP_TOSTRING_STR(mBatch->mDestination));
        mSessionHandler->obtainMessage(SDP_RESULT, channel, -1, mBatch->mDestination)->sendToTarget();
        return;
    } else {
        GLOGI("Remote Service channel not in cache");

        if (!mBatch->mDestination->fetchUuidsWithSdp()) {
            LOGE("Start SDP query failed");
        } else {
            // we expect framework send us Intent ACTION_UUID. otherwise we will fail
            GLOGV("Start new SDP, wait for result");
            sp<IntentFilter> intentFilter = new IntentFilter(BluetoothDevice::ACTION_UUID());
            mspContext->registerReceiver(mReceiver, intentFilter);
            return;
        }
    }
    sp<Message> msg = mSessionHandler->obtainMessage(SDP_RESULT, channel, -1, mBatch->mDestination);
    mSessionHandler->sendMessageDelayed(msg, 2000);
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值