void BluetoothServiceBluedroid::AdapterStateChangedNotification(bool aState) { MOZ_ASSERT(NS_IsMainThread()); BT_LOGR("BT_STATE: %d", aState); sAdapterEnabled = aState; if (!sAdapterEnabled) { static void (* const sDeinitManager[])(BluetoothProfileResultHandler*) = { BluetoothHfpManager::DeinitHfpInterface, BluetoothA2dpManager::DeinitA2dpInterface, BluetoothGattManager::DeinitGattInterface }; // Return error if BluetoothService is unavailable BluetoothService* bs = BluetoothService::Get(); NS_ENSURE_TRUE_VOID(bs); // Cleanup static adapter properties and notify adapter. sAdapterBdAddress.Truncate(); sAdapterBdName.Truncate(); InfallibleTArray<BluetoothNamedValue> props; BT_APPEND_NAMED_VALUE(props, "Name", sAdapterBdName); BT_APPEND_NAMED_VALUE(props, "Address", sAdapterBdAddress); if (sAdapterDiscoverable) { sAdapterDiscoverable = false; BT_APPEND_NAMED_VALUE(props, "Discoverable", false); } if (sAdapterDiscovering) { sAdapterDiscovering = false; BT_APPEND_NAMED_VALUE(props, "Discovering", false); } bs->DistributeSignal(NS_LITERAL_STRING("PropertyChanged"), NS_LITERAL_STRING(KEY_ADAPTER), BluetoothValue(props)); // Cleanup bluetooth interfaces after BT state becomes BT_STATE_OFF. nsRefPtr<ProfileDeinitResultHandler> res = new ProfileDeinitResultHandler(MOZ_ARRAY_LENGTH(sDeinitManager)); for (size_t i = 0; i < MOZ_ARRAY_LENGTH(sDeinitManager); ++i) { sDeinitManager[i](res); } } BluetoothService::AcknowledgeToggleBt(sAdapterEnabled); if (sAdapterEnabled) { // Bluetooth just enabled, clear profile controllers and runnable arrays. sControllerArray.Clear(); sChangeDiscoveryRunnableArray.Clear(); sSetPropertyRunnableArray.Clear(); sGetDeviceRunnableArray.Clear(); sFetchUuidsRunnableArray.Clear(); sBondingRunnableArray.Clear(); sUnbondingRunnableArray.Clear(); sPairingNameTable.Clear(); // Bluetooth scan mode is SCAN_MODE_CONNECTABLE by default, i.e., it should // be connectable and non-discoverable. NS_ENSURE_TRUE_VOID(sBtInterface); sBtInterface->SetAdapterProperty( BluetoothNamedValue(NS_ConvertUTF8toUTF16("Discoverable"), false), new SetAdapterPropertyDiscoverableResultHandler()); // Trigger BluetoothOppManager to listen BluetoothOppManager* opp = BluetoothOppManager::Get(); if (!opp || !opp->Listen()) { BT_LOGR("Fail to start BluetoothOppManager listening"); } } // Resolve promise if existed if (!sChangeAdapterStateRunnableArray.IsEmpty()) { DispatchReplySuccess(sChangeAdapterStateRunnableArray[0]); sChangeAdapterStateRunnableArray.RemoveElementAt(0); } }
void DottedCornerFinder::FindBestOverlap(Float aMinR, Float aMinBorderRadius, Float aMaxBorderRadius) { // If overlap is not calculateable, find it with binary search, // such that there exists i that C_i == C_n with the given overlap. FourFloats key(aMinR, mMaxR, aMinBorderRadius, aMaxBorderRadius); BestOverlap best; if (DottedCornerCache.Get(key, &best)) { mCount = best.count; mBestOverlap = best.overlap; return; } Float lower = 0.0f; Float upper = 0.5f; // Start from lower bound to find the minimum number of circles. Float overlap = 0.0f; mBestOverlap = overlap; size_t targetCount = 0; const Float OVERLAP_MARGIN = 0.1f; for (size_t j = 0; j < MAX_LOOP; j++) { Reset(); size_t count; Float actualOverlap; if (!GetCountAndLastOverlap(overlap, &count, &actualOverlap)) { if (j == 0) { mCount = mMaxCount; break; } } if (j == 0) { if (count < 3 || (count == 3 && actualOverlap > 0.5f)) { // |count == 3 && actualOverlap > 0.5f| means there could be // a circle but it is too near from both ends. // // if actualOverlap == 0.0 // 1 2 3 // +-------+-------+-------+-------+ // | ##### | ***** | ##### | ##### | // |#######|*******|#######|#######| // |###+###|***+***|###+###|###+###| // |# C_0 #|* C_1 *|# C_2 #|# C_n #| // | ##### | ***** | ##### | ##### | // +-------+-------+-------+-------+ // | // V // +-------+---+-------+---+-------+ // | ##### | | ##### | | ##### | // |#######| |#######| |#######| // |###+###| |###+###| |###+###| Find the best overlap to place // |# C_0 #| |# C_1 #| |# C_n #| C_1 at the middle of them // | ##### | | ##### | | ##### | // +-------+---+-------+---|-------+ // // if actualOverlap == 0.5 // 1 2 3 // +-------+-------+-------+---+ // | ##### | ***** | ##### |## | // |#######|*******|##### C_n #| // |###+###|***+***|###+###+###| // |# C_0 #|* C_1 *|# C_2 #|###| // | ##### | ***** | ##### |## | // +-------+-------+-------+---+ // | // V // +-------+-+-------+-+-------+ // | ##### | | ##### | | ##### | // |#######| |#######| |#######| // |###+###| |###+###| |###+###| Even if we place C_1 at the middle // |# C_0 #| |# C_1 #| |# C_n #| of them, it's too near from them // | ##### | | ##### | | ##### | // +-------+-+-------+-|-------+ // | // V // +-------+-----------+-------+ // | ##### | | ##### | // |#######| |#######| // |###+###| |###+###| Do not draw any circle // |# C_0 #| |# C_n #| // | ##### | | ##### | // +-------+-----------+-------+ mCount = 0; break; } // targetCount should be 2n, as we're searching C_1 to C_n. // // targetCount = 4 // mCount = 1 // 1 2 3 4 // +-------+-------+-------+-------+-------+ // | ##### | ***** | ##### | ***** | ##### | // |#######|*******|#######|*******|#######| // |###+###|***+***|###+###|***+***|###+###| // |# C_0 #|* C_1 *|# C_2 #|* C_3 *|# C_n #| // | ##### | ***** | ##### | ***** | ##### | // +-------+-------+-------+-------+-------+ // 1 // // targetCount = 6 // mCount = 2 // 1 2 3 4 5 6 // +-------+-------+-------+-------+-------+-------+-------+ // | ##### | ***** | ##### | ***** | ##### | ***** | ##### | // |#######|*******|#######|*******|#######|*******|#######| // |###+###|***+***|###+###|***+***|###+###|***+***|###+###| // |# C_0 #|* C_1 *|# C_2 #|* C_3 *|# C_4 #|* C_5 *|# C_n #| // | ##### | ***** | ##### | ***** | ##### | ***** | ##### | // +-------+-------+-------+-------+-------+-------+-------+ // 1 2 if (count % 2) { targetCount = count + 1; } else { targetCount = count; } mCount = targetCount / 2 - 1; } if (count == targetCount) { mBestOverlap = overlap; if (fabs(actualOverlap - overlap) < OVERLAP_MARGIN) { break; } // We started from upper bound, no need to update range when j == 0. if (j > 0) { if (actualOverlap > overlap) { lower = overlap; } else { upper = overlap; } } } else { // |j == 0 && count != targetCount| means that |targetCount = count + 1|, // and we started from upper bound, no need to update range when j == 0. if (j > 0) { if (count > targetCount) { upper = overlap; } else { lower = overlap; } } } overlap = (upper + lower) / 2.0f; } if (DottedCornerCache.Count() > DottedCornerCacheSize) { DottedCornerCache.Clear(); } DottedCornerCache.Put(key, BestOverlap(mBestOverlap, mCount)); }