546 void BluetoothOppService::BluetoothShareContentObserver::onChange(bool selfChange) { 547 GLOGENTRY(); 548 sp<BluetoothOppService> mspbtoppser = mBtOppService.promote(); 549 GLOGD("BluetoothOppService:: ContentObserver received notification"); 550 mspbtoppser->updateFromProvider(); 551}
768 void BluetoothOppService::updateFromProvider() {
769 GLOGENTRY();
770 GLOGI("updateFromProvider");
771 RecursiveMutex::Autolock _l(mBluetoothOppServiceMutex);
772
773 mPendingUpdate = true;
774 if (mUpdateThread == NULL) {
775 GLOGD("BluetoothOppService:: UpdateThread count %d", getStrongCount());
776 mUpdateThread = new UpdateThread(this);
777 GLOGD("BluetoothOppService:: UpdateThread count %d", getStrongCount());
778 mUpdateThread->run("Bluetooth Share Service");
779 }
780}
391 bool BluetoothOppService::UpdateThread::threadLoop() {
392 GLOGENTRY();
393 sp<BluetoothOppService> mspbtoppser = mwpbtoppserice.promote();
394 CHECK_NULL_POINTER_RETURN_FALSE(mspbtoppser);
395
396 Process::setThreadPriority(Process::THREAD_PRIORITY_BACKGROUND);
397
398 bool keepService = false;
399 for (;;) {
400 {
401 RecursiveMutex::Autolock _l(mspbtoppser->mBluetoothOppServiceMutex);
402 if (mspbtoppser->mUpdateThread != this) {
403 // throw new IllegalStateException("multiple UpdateThreads in BluetoothOppService");
404 GLOGW("multiple UpdateThreads in BluetoothOppService");
405 return false;
406 }
407 GLOGI("pendingUpdate is %d keepUpdateThread is %d sListenStarted is %d", mspbtoppser->mPendingUpdate, keepService, mspbtoppser->mListenStarted);
408 if (!mspbtoppser->mPendingUpdate) {
409 mspbtoppser->mUpdateThread = NULL;
410 if (!keepService && !mspbtoppser->mListenStarted) {
411 mspbtoppser->stopSelf();
412 break;
413 }
414 GLOGW("Exit BluetoothOppService::UpdateThread::threadLoop()");
415 return false;
416 }
417 mspbtoppser->mPendingUpdate = false;
418 }
419 sp<Cursor> cursor = mspbtoppser->getContentResolver()->query(BluetoothShare::CONTENT_URI(), NULL, NULL, NULL, BluetoothShare::_ID);
420
421 if (cursor == NULL) {
422 GLOGW("cursor is NULL");
423 return false;
424 }
425
426 cursor->moveToFirst();
427
428 int32_t arrayPos = 0;
429
430 keepService = false;
431 bool isAfterLast = cursor->isAfterLast();
432
433 int32_t idColumn = cursor->getColumnIndexOrThrow(BluetoothShare::_ID);
434 /*
435 * Walk the cursor and the local array to keep them in sync. The
436 * key to the algorithm is that the ids are unique and sorted
437 * both in the cursor and in the array, so that they can be
438 * processed in order in both sources at the same time: at each
439 * step, both sources point to the lowest id that hasn't been
440 * processed from that source, and the algorithm processes the
441 * lowest id from those two possibilities. At each step: -If the
442 * array contains an entry that's not in the
443 * entry, move to next entry in the array. -If the array
444 * contains an entry that's in the cursor, nothing to do, move
445 * to next cursor row and next array entry. -If the cursor
446 * contains an entry that's not in the array, insert a new entry
447 * in the array, move to next cursor row and next array entry.
448 */
449 while (!isAfterLast || arrayPos < mspbtoppser->mShares->size()) {
450 if (isAfterLast) {
451 // We're beyond the end of the cursor but there's still
452 // some
453 // stuff in the local array, which can only be junk
454 GLOGI("Array update: trimming %d @ %d", mspbtoppser->mShares->get(arrayPos)->mId, arrayPos);
455
456 if (mspbtoppser->shouldScanFile(arrayPos)) {
457 mspbtoppser->scanFile(NULL, arrayPos);
458 }
459 mspbtoppser->deleteShare(arrayPos); // this advances in the array
460 } else {
461 int32_t id = cursor->getInt(idColumn);
462
463 if (arrayPos == mspbtoppser->mShares->size()) {
464 mspbtoppser->insertShare(cursor, arrayPos);
465 GLOGI("Array update: inserting %d @ %d", id, arrayPos);
466 if (mspbtoppser->shouldScanFile(arrayPos) && (!mspbtoppser->scanFile(cursor, arrayPos))) {
467 keepService = true;
468 }
469 if (mspbtoppser->visibleNotification(arrayPos)) {
470 keepService = true;
471 }
472 if (mspbtoppser->needAction(arrayPos)) {
473 keepService = true;
474 }
475
476 ++arrayPos;
477 cursor->moveToNext();
478 isAfterLast = cursor->isAfterLast();
479 } else {
480 int32_t arrayId = mspbtoppser->mShares->get(arrayPos)->mId;
481
482 if (arrayId < id) {
483 GLOGI("Array update: removing %d @ %d", arrayId, arrayPos);
484 if (mspbtoppser->shouldScanFile(arrayPos)) {
485 mspbtoppser->scanFile(NULL, arrayPos);
486 }
487 mspbtoppser->deleteShare(arrayPos);
488 } else if (arrayId == id) {
489 // This cursor row already exists in the stored
490 // array
491 mspbtoppser->updateShare(cursor, arrayPos, mspbtoppser->userAccepted);
492 if (mspbtoppser->shouldScanFile(arrayPos) && (!mspbtoppser->scanFile(cursor, arrayPos))) {
493 keepService = true;
494 }
495 if (mspbtoppser->visibleNotification(arrayPos)) {
496 keepService = true;
497 }
498 if (mspbtoppser->needAction(arrayPos)) {
499 keepService = true;
500 }
501
502 ++arrayPos;
503 cursor->moveToNext();
504 isAfterLast = cursor->isAfterLast();
505 } else {
506 // This cursor entry didn't exist in the stored
507 // array
508 GLOGI("Array update: appending %d @ %d", id, arrayPos);
509 mspbtoppser->insertShare(cursor, arrayPos);
510
511 if (mspbtoppser->shouldScanFile(arrayPos) && (!mspbtoppser->scanFile(cursor, arrayPos))) {
512 keepService = true;
513 }
514 if (mspbtoppser->visibleNotification(arrayPos)) {
515 keepService = true;
516 }
517 if (mspbtoppser->needAction(arrayPos)) {
518 keepService = true;
519 }
520 ++arrayPos;
521 cursor->moveToNext();
522 isAfterLast = cursor->isAfterLast();
523 }
524 }
525 }
526 }
527 mspbtoppser->mNotifier->updateNotification();
528 cursor->close();
529 GLOGD("BluetoothOppService::UpdateThread::threadLoop End");
530 }
531
532 return false;
533}
534
211 void BluetoothOppNotification::updateNotification() {
212 GLOGENTRY();213 Mutex::Autolock autoLock(mOppNotificationMutex);
214
215 mPendingUpdate++;
216 if (mPendingUpdate > 1) {
217 GLOGI("update too frequent, put in queue");
218 return;
219 }
220 if (!mHandler->hasMessages(NOTIFY)) {
221 GLOGI("send message");
222 mHandler->sendMessage(mHandler->obtainMessage(NOTIFY));
223 }
224}
83 void OppNotificationHandler::handleMessage(const sp<Message>& msg) {
84 GLOGENTRY();85 sp<BluetoothOppNotification> btOppNotif = mOppNotificationHandler.promote();
86 CHECK_NULL_POINTER_RETURN(btOppNotif);
87
88 switch (msg->what) {
89 case BluetoothOppNotification::NOTIFY:
90 Mutex::Autolock autoLock(btOppNotif->mOppNotificationMutex);
91
92 if (btOppNotif->mPendingUpdate > 0 && btOppNotif->mUpdateNotificationThread == NULL) {
93 GLOGI("new notify threadi!");
94 btOppNotif->mUpdateNotificationThread = new BluetoothOppNotification::NotificationUpdateThread(btOppNotif);
95 btOppNotif->mUpdateNotificationThread->run();
96 GLOGI("send delay message");
97 btOppNotif->mHandler->sendMessageDelayed(btOppNotif->mHandler->obtainMessage(BluetoothOppNotification::NOTIFY), 1000);
98 } else if (btOppNotif->mPendingUpdate > 0) {
99 GLOGI("previous thread is not finished yet");
100 btOppNotif->mHandler->sendMessageDelayed(btOppNotif->mHandler->obtainMessage(BluetoothOppNotification::NOTIFY), 1000);
101 }
102 break;
103 }
104}
237 bool BluetoothOppNotification::NotificationUpdateThread::threadLoop() {
238 GLOGENTRY();
239 sp<BluetoothOppNotification> oppNotif = mOppNotificationUpdateThread.promote();
240 CHECK_NULL_POINTER_RETURN_FALSE(oppNotif);
241
242 Process::setThreadPriority(Process::THREAD_PRIORITY_BACKGROUND);
243
244 {
245 RecursiveMutex::Autolock _l(oppNotif->mOppNotificationMutex);
246
247 if (oppNotif->mUpdateNotificationThread != this) {
248 // throw new IllegalStateException(
249 // "multiple UpdateThreads in BluetoothOppNotification");
250 LOGE("multiple UpdateThreads in BluetoothOppNotification");
251 return false;
252 }
253 oppNotif->mPendingUpdate = 0;
254 }
255
256 oppNotif->updateActiveNotification();
257 oppNotif->updateCompletedNotification();
258 oppNotif->updateIncomingFileConfirmNotification();
259
260 {
261 RecursiveMutex::Autolock _l(oppNotif->mOppNotificationMutex);
262 oppNotif->mUpdateNotificationThread = NULL;
263 }
264
265 return false;
266}
557 void BluetoothOppNotification::updateIncomingFileConfirmNotification() {
558 GLOGENTRY();
559 sp<Context> mspContext = mContext.promote();
560 CHECK_NULL_POINTER_RETURN(mspContext);
561
562 sp<Cursor> cursor = mspContext->getContentResolver()->query(BluetoothShare::CONTENT_URI(), NULL, WHERE_CONFIRM_PENDING(), NULL, BluetoothShare::_ID);
563
564 if (cursor == NULL) {
565 GLOGW("updateIncomingFileConfirmNotification, cursor == NULL");
566 return;
567 }
568 GLOGD("count %d columncount %d, position %d", cursor->getCount(), cursor->getColumnCount(), cursor->getPosition());
569
570 for (cursor->moveToFirst(); !cursor->isAfterLast(); cursor->moveToNext()) {
571 GLOGD("cursor->moveToFirst()");
572 sp<CharSequence> title = mspContext->getText(R::string::incoming_file_confirm_Notification_title);
573 sp<CharSequence> caption = mspContext->getText(R::string::incoming_file_confirm_Notification_caption);
574 int32_t id = cursor->getInt(cursor->getColumnIndexOrThrow(BluetoothShare::_ID));
575 int64_t timeStamp = cursor->getLong(cursor->getColumnIndexOrThrow(BluetoothShare::TIMESTAMP()));
576 sp<String> str = String::format("%s/%d", BluetoothShare::CONTENT_URI()->toString()->string(), id);
577 GLOGI("updateIncomingFileConfirmNotification, contentUri:%s", SP_STRING_STR(str));
578 sp<Uri> contentUri = Uri::parse(str);
579
580 sp<Notification> n = new Notification();
581 n->icon = R::drawable::stat_notify_incomming_file_notification;
582 n->flags |= Notification::FLAG_ONLY_ALERT_ONCE;
583 n->flags |= Notification::FLAG_ONGOING_EVENT;
584 n->defaults = Notification::DEFAULT_SOUND;
585 n->tickerText = title;
586
587 sp<String> strpkgname = new String("BluetoothOppPbapService");
588 sp<String> strclassname = new String("BluetoothOppReceiver");
589
590 sp<Intent> intent = new Intent(Constants::ACTION_INCOMING_FILE_CONFIRM());
591 intent->setClassName(strpkgname, strclassname);
592 intent->setData(contentUri);
593 n->when = timeStamp;
594 n->setLatestEventInfo(mspContext, title, caption, PendingIntent::getBroadcast(mspContext, 0, intent, 0));
595
596 GLOGI("updateIncomingFileConfirmNotification, icon %d, tickerText %s, when %lld", n->icon, SP_TOSTRING_STR(n->tickerText), n->when);
597
598 intent = new Intent(Constants::ACTION_HIDE());
599 intent->setClassName(strpkgname, strclassname);
600 intent->setData(contentUri);
601 n->deleteIntent = PendingIntent::getBroadcast(mspContext, 0, intent, 0);
602 mNotificationMgr->notify(id, n);
603#if 0
604 // pokai 20130411 Simluate user click confirm
605 sp<ContentValues> mUpdateValues = new ContentValues();
606 mUpdateValues->put(BluetoothShare::USER_CONFIRMATION(), BluetoothShare::USER_CONFIRMATION_CONFIRMED);
607 mspContext->getContentResolver()->update(contentUri, mUpdateValues, NULL, NULL);
608#endif // mark
609 }
610 cursor->close();
611}
} else if (action->equals(Constants::ACTION_INCOMING_FILE_CONFIRM())) {
GLOGV("Receiver ACTION_INCOMING_FILE_CONFIRM");
sp<Uri> uri = intent->getData();
// TODO: Don't need the activity
#if 1
sp<Intent> in = new Intent();
sp<ComponentName> component = new ComponentName(sp<String>(new String("BluetoothOppPbapService")), sp<String>(new String("BluetoothOppIncomingFileConfirmActivity")));
in->setComponent(component);
in->setFlags(Intent::FLAG_ACTIVITY_NEW_TASK);
in->setData(uri);
context->startActivity(in);
#endif // TODO: Don't need the activity
#if 1
sp<NotificationManager> notMgr = safe_cast<NotificationManager *>(context->getSystemService(Context::NOTIFICATION_SERVICE()).get());
if (notMgr != NULL) {
notMgr->cancel(static_cast<int32_t>(ContentUris::parseId(intent->getData())));
GLOGV("notMgr.cancel called");
}
#endif // mark
}