1 /*
2  * Copyright (C) 2023 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.development.bluetooth;
18 
19 import android.content.Context;
20 import android.os.SystemProperties;
21 import android.util.Log;
22 
23 import androidx.annotation.NonNull;
24 import androidx.annotation.Nullable;
25 import androidx.annotation.VisibleForTesting;
26 import androidx.preference.ListPreference;
27 import androidx.preference.Preference;
28 
29 import com.android.settings.R;
30 import com.android.settings.core.PreferenceControllerMixin;
31 import com.android.settingslib.development.DeveloperOptionsPreferenceController;
32 
33 public class BluetoothStackLogPreferenceController extends DeveloperOptionsPreferenceController
34         implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
35 
36     /* Ensure that the indexes match with bt_stack_log_values and bt_stack_log_entries ordering */
37     private static final String PREFERENCE_KEY = "bt_stack_log_level";
38     @VisibleForTesting static final int BTSTACK_LOG_MODE_VERBOSE_INDEX = 0;
39     @VisibleForTesting static final int BTSTACK_LOG_MODE_DEBUG_INDEX = 1;
40     @VisibleForTesting static final int BTSTACK_LOG_MODE_INFO_INDEX = 2;
41     @VisibleForTesting static final int BTSTACK_LOG_MODE_WARN_INDEX = 3;
42     @VisibleForTesting static final int BTSTACK_LOG_MODE_ERROR_INDEX = 4;
43 
44     @VisibleForTesting
45     static final String BLUETOOTH_BTSTACK_LOG_MODE_PROPERTY_PERSIST = "persist.log.tag.bluetooth";
46     static final String BLUETOOTH_BTSTACK_LOG_MODE_PROPERTY = "log.tag.bluetooth";
47     static final String BLUETOOTH_STRING_NAME = "bluetooth";
48     static final int DEFAULT_MODE = BTSTACK_LOG_MODE_INFO_INDEX;
49 
50     private final String[] mListValues;
51     private final String[] mListEntries;
52 
53 
BluetoothStackLogPreferenceController(@onNull Context context)54     public BluetoothStackLogPreferenceController(@NonNull Context context) {
55         super(context);
56         mListValues = context.getResources().getStringArray(R.array.bt_stack_log_level_values);
57         mListEntries = context.getResources().getStringArray(R.array.bt_stack_log_level_entries);
58     }
59 
60     /** returns default log level index of INFO */
getDefaultModeIndex()61     public int getDefaultModeIndex() {
62         return DEFAULT_MODE;
63     }
64 
65     @Override
66     @Nullable
getPreferenceKey()67     public String getPreferenceKey() {
68         return PREFERENCE_KEY;
69     }
70 
71     @Override
onPreferenceChange(@onNull Preference preference, @NonNull Object newValue)72     public boolean onPreferenceChange(@NonNull Preference preference, @NonNull Object newValue) {
73         SystemProperties.set(BLUETOOTH_BTSTACK_LOG_MODE_PROPERTY_PERSIST, newValue.toString());
74         SystemProperties.set(BLUETOOTH_BTSTACK_LOG_MODE_PROPERTY, newValue.toString());
75         updateState(mPreference);
76         return true;
77     }
78 
79     @Override
updateState(@onNull Preference preference)80     public void updateState(@NonNull Preference preference) {
81         final ListPreference listPreference = (ListPreference) preference;
82         int index = getBluetoothLogLevelIndex();
83         listPreference.setValue(mListValues[index]);
84         listPreference.setSummary(mListEntries[index]);
85     }
86 
87     /**
88      *  Returns the current log level from Log.isLoggable().
89      */
90     @VisibleForTesting
getBluetoothLogLevelIndex()91     public int getBluetoothLogLevelIndex() {
92         if (Log.isLoggable(BLUETOOTH_STRING_NAME, Log.VERBOSE)) {
93             return BTSTACK_LOG_MODE_VERBOSE_INDEX;
94         } else if (Log.isLoggable(BLUETOOTH_STRING_NAME, Log.DEBUG)) {
95             return BTSTACK_LOG_MODE_DEBUG_INDEX;
96         } else if (Log.isLoggable(BLUETOOTH_STRING_NAME, Log.INFO)) {
97             return BTSTACK_LOG_MODE_INFO_INDEX;
98         } else if (Log.isLoggable(BLUETOOTH_STRING_NAME, Log.WARN)) {
99             return BTSTACK_LOG_MODE_WARN_INDEX;
100         } else if (Log.isLoggable(BLUETOOTH_STRING_NAME, Log.ERROR)) {
101             return BTSTACK_LOG_MODE_ERROR_INDEX;
102         }
103         return BTSTACK_LOG_MODE_INFO_INDEX;
104     }
105 
106     @Override
onDeveloperOptionsSwitchDisabled()107     protected void onDeveloperOptionsSwitchDisabled() {
108         super.onDeveloperOptionsSwitchDisabled();
109         SystemProperties.set(BLUETOOTH_BTSTACK_LOG_MODE_PROPERTY_PERSIST, null);
110         SystemProperties.set(BLUETOOTH_BTSTACK_LOG_MODE_PROPERTY, null);
111         ((ListPreference) mPreference).setValue(mListValues[getDefaultModeIndex()]);
112         ((ListPreference) mPreference).setSummary(mListEntries[getDefaultModeIndex()]);
113     }
114 }
115