1 /*
2  * Copyright (C) 2020 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.tv.settings.accessories;
18 
19 import static android.content.Intent.FLAG_INCLUDE_STOPPED_PACKAGES;
20 import static android.content.Intent.FLAG_RECEIVER_FOREGROUND;
21 import static android.content.Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND;
22 
23 import static com.android.tv.settings.accessories.ConnectedDevicesSliceProvider.KEY_EXTRAS_DEVICE;
24 import static com.android.tv.settings.accessories.ConnectedDevicesSliceUtils.DIRECTION_BACK;
25 import static com.android.tv.settings.accessories.ConnectedDevicesSliceUtils.EXTRAS_DIRECTION;
26 import static com.android.tv.settings.accessories.ConnectedDevicesSliceUtils.EXTRAS_SLICE_URI;
27 import static com.android.tv.settings.accessories.ConnectedDevicesSliceUtils.FIND_MY_REMOTE_PHYSICAL_BUTTON_ENABLED_SETTING;
28 import static com.android.tv.settings.accessories.ConnectedDevicesSliceUtils.notifyDeviceChanged;
29 import static com.android.tv.settings.accessories.ConnectedDevicesSliceUtils.notifyToGoBack;
30 import static com.android.tv.settings.accessories.ConnectedDevicesSliceUtils.setFindMyRemoteButtonEnabled;
31 
32 import android.bluetooth.BluetoothDevice;
33 import android.content.BroadcastReceiver;
34 import android.content.Context;
35 import android.content.Intent;
36 import android.net.Uri;
37 
38 /**
39  * This broadcast receiver handles these cases:
40  * (a) Bluetooth toggle on.
41  * (b) The followup pending intent for "rename"/"forget" preference to notify TvSettings UI flow to
42  * go back.
43  */
44 public class ConnectedDevicesSliceBroadcastReceiver extends BroadcastReceiver {
45 
46     private static final String TAG = "ConnectedSliceReceiver";
47 
48     static final String ACTION_FIND_MY_REMOTE = "com.google.android.tv.FIND_MY_REMOTE";
49     static final String ACTION_TOGGLE_CHANGED =
50             "com.android.tv.settings.accessories.TOGGLE_CHANGED";
51     // The extra to specify toggle type.
52     static final String EXTRA_TOGGLE_TYPE = "TOGGLE_TYPE";
53     static final String EXTRA_TOGGLE_STATE = "TOGGLE_STATE";
54     // Bluetooth off is handled differently by ResponseActivity with confirmation dialog.
55     static final String BLUETOOTH_ON = "BLUETOOTH_ON";
56     static final String ACTIVE_AUDIO_OUTPUT = "ACTIVE_AUDIO_OUTPUT";
57 
58     @Override
onReceive(Context context, Intent intent)59     public void onReceive(Context context, Intent intent) {
60         // Handle CEC control toggle.
61         final String action = intent.getAction();
62         if (ACTION_TOGGLE_CHANGED.equals(action)) {
63             final boolean isChecked = intent.getBooleanExtra(EXTRA_TOGGLE_STATE, false);
64             final String toggleType = intent.getStringExtra(EXTRA_TOGGLE_TYPE);
65             if (toggleType != null) {
66                 switch (toggleType) {
67                     case BLUETOOTH_ON -> {
68                         if (AccessoryUtils.getDefaultBluetoothAdapter() != null) {
69                             AccessoryUtils.getDefaultBluetoothAdapter().enable();
70                         }
71                         return;
72                     }
73                     case ACTIVE_AUDIO_OUTPUT -> {
74                         boolean enable = intent.getBooleanExtra(EXTRA_TOGGLE_STATE, false);
75                         BluetoothDevice device = intent.getParcelableExtra(KEY_EXTRAS_DEVICE,
76                                 BluetoothDevice.class);
77                         AccessoryUtils.setActiveAudioOutput(enable ? device : null);
78                         // refresh device
79                         notifyDeviceChanged(context, device);
80                     }
81                     case FIND_MY_REMOTE_PHYSICAL_BUTTON_ENABLED_SETTING -> {
82                         setFindMyRemoteButtonEnabled(context, isChecked);
83                         context.getContentResolver().notifyChange(
84                                 ConnectedDevicesSliceUtils.FIND_MY_REMOTE_SLICE_URI, null);
85                     }
86                 }
87             }
88         } else if (ACTION_FIND_MY_REMOTE.equals(action)) {
89             context.sendBroadcast(
90                     new Intent(ACTION_FIND_MY_REMOTE)
91                             .putExtra("reason", "SETTINGS")
92                             .setFlags(FLAG_INCLUDE_STOPPED_PACKAGES | FLAG_RECEIVER_FOREGROUND
93                                     | FLAG_RECEIVER_INCLUDE_BACKGROUND),
94                     "com.google.android.tv.permission.FIND_MY_REMOTE");
95         }
96 
97         // Notify TvSettings to go back to the previous level.
98         String direction = intent.getStringExtra(EXTRAS_DIRECTION);
99         if (DIRECTION_BACK.equals(direction)) {
100             notifyToGoBack(context, Uri.parse(intent.getStringExtra(EXTRAS_SLICE_URI)));
101         }
102     }
103 }
104