/* * Copyright 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.bluetooth import android.content.ContentResolver import android.database.ContentObserver import android.os.Handler import android.os.Looper import android.provider.Settings private const val TAG = "BluetoothRadioModeListener" /** * Listen on radio mode and trigger the callback when it change * * @param radio: The radio to listen for, eg: Settings.Global.AIRPLANE_MODE_RADIOS * @param modeKey: The associated mode key, eg: Settings.Global.AIRPLANE_MODE_ON * @param callback: The callback to trigger when there is a mode change, pass new mode as parameter * @return The initial value of the radio */ internal fun initializeRadioModeListener( looper: Looper, resolver: ContentResolver, radio: String, modeKey: String, callback: (m: Boolean) -> Unit ): Boolean { val observer = object : ContentObserver(Handler(looper)) { override fun onChange(selfChange: Boolean) { callback(getRadioModeValue(resolver, radio, modeKey)) } } val notifyForDescendants = false resolver.registerContentObserver( Settings.Global.getUriFor(radio), notifyForDescendants, observer ) resolver.registerContentObserver( Settings.Global.getUriFor(modeKey), notifyForDescendants, observer ) return getRadioModeValue(resolver, radio, modeKey) } /** * Check if Bluetooth is impacted by the radio and fetch global mode status * * @return whether Bluetooth should consider this radio or not */ private fun getRadioModeValue(resolver: ContentResolver, radio: String, modeKey: String): Boolean { return if (isSensitive(resolver, radio)) { isGlobalModeOn(resolver, modeKey) } else { Log.d(TAG, "Not sensitive to " + radio + " change. Forced to false") false } } /** * *Do not use outside of this file to avoid async issues* * * @return false if Bluetooth should not listen for mode change related to the {@code radio} */ private fun isSensitive(resolver: ContentResolver, radio: String): Boolean { val radios = Settings.Global.getString(resolver, radio) return radios != null && radios.contains(Settings.Global.RADIO_BLUETOOTH) } /** * *Do not use outside of this file to avoid async issues* * * @return whether mode {@code modeKey} is on or off in Global settings */ private fun isGlobalModeOn(resolver: ContentResolver, modeKey: String): Boolean { return Settings.Global.getInt(resolver, modeKey, 0) == 1 }