1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.connecteddevice
18 
19 import android.bluetooth.BluetoothAdapter
20 import android.content.BroadcastReceiver
21 import android.content.Context
22 import android.content.Intent
23 import android.content.IntentFilter
24 import com.android.settings.R
25 import com.android.settings.widget.MainSwitchBarMetadata
26 import com.android.settingslib.datastore.KeyValueStore
27 import com.android.settingslib.datastore.NoOpKeyedObservable
28 import com.android.settingslib.metadata.PreferenceLifecycleContext
29 import com.android.settingslib.metadata.PreferenceLifecycleProvider
30 import com.android.settingslib.metadata.ReadWritePermit
31 
32 class BluetoothMainSwitchPreference(private val bluetoothAdapter: BluetoothAdapter?) :
33     MainSwitchBarMetadata, PreferenceLifecycleProvider {
34 
35     private lateinit var broadcastReceiver: BroadcastReceiver
36 
37     override val key
38         get() = "use_bluetooth"
39 
40     override val title
41         get() = R.string.bluetooth_main_switch_title
42 
getReadPermitnull43     override fun getReadPermit(context: Context, myUid: Int, callingUid: Int) =
44         ReadWritePermit.ALLOW
45 
46     override fun getWritePermit(context: Context, value: Boolean?, myUid: Int, callingUid: Int) =
47         ReadWritePermit.ALLOW
48 
49     override fun storage(context: Context) = BluetoothStateStore(bluetoothAdapter)
50 
51     override fun onStart(context: PreferenceLifecycleContext) {
52         broadcastReceiver =
53             object : BroadcastReceiver() {
54                 override fun onReceive(receiverContext: Context, intent: Intent) {
55                     context.notifyPreferenceChange(key)
56                 }
57             }
58         context.registerReceiver(
59             broadcastReceiver,
60             IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED),
61             Context.RECEIVER_EXPORTED_UNAUDITED
62         )
63     }
64 
onStopnull65     override fun onStop(context: PreferenceLifecycleContext) {
66         if (::broadcastReceiver.isInitialized) {
67             context.unregisterReceiver(broadcastReceiver)
68         }
69     }
70 
isEnablednull71     override fun isEnabled(context: Context): Boolean {
72         return bluetoothAdapter?.state.let {
73             it == BluetoothAdapter.STATE_ON || it == BluetoothAdapter.STATE_OFF
74         }
75     }
76 
77     @Suppress("UNCHECKED_CAST")
78     class BluetoothStateStore(private val bluetoothAdapter: BluetoothAdapter?) :
79         NoOpKeyedObservable<String>(), KeyValueStore {
80 
containsnull81         override fun contains(key: String) = true
82 
83         override fun <T : Any> getValue(key: String, valueType: Class<T>): T? {
84             return (bluetoothAdapter?.state.let {
85                 it == BluetoothAdapter.STATE_ON || it == BluetoothAdapter.STATE_TURNING_ON
86             }) as T
87         }
88 
setValuenull89         override fun <T : Any> setValue(key: String, valueType: Class<T>, value: T?) {
90             if (value is Boolean) {
91                 if (value) {
92                     bluetoothAdapter?.enable()
93                 } else {
94                     bluetoothAdapter?.disable()
95                 }
96             }
97         }
98     }
99 }
100