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 #include "chre/core/settings.h"
18
19 #include <cstddef>
20
21 #include "chre/core/event_loop_manager.h"
22 #include "chre/platform/log.h"
23 #include "chre/util/macros.h"
24 #include "chre/util/nested_data_ptr.h"
25
26 #include "chre_api/chre/user_settings.h"
27
28 namespace chre {
29
30 namespace {
31
32 /**
33 * @param setting The setting to get the index for.
34 * @param index A non-null pointer to store the index.
35 *
36 * @return false if the setting was invalid.
37 */
getIndexForSetting(Setting setting,size_t * index)38 bool getIndexForSetting(Setting setting, size_t *index) {
39 if (setting < Setting::SETTING_MAX) {
40 *index = static_cast<size_t>(setting);
41 return true;
42 }
43
44 return false;
45 }
46
sendSettingChangedNotification(Setting setting,bool enabled)47 void sendSettingChangedNotification(Setting setting, bool enabled) {
48 auto *eventData = memoryAlloc<struct chreUserSettingChangedEvent>();
49 auto settingAsInt = static_cast<uint8_t>(setting);
50 uint16_t eventType = CHRE_EVENT_SETTING_CHANGED_FIRST_EVENT + settingAsInt;
51
52 if (eventData != nullptr) {
53 eventData->setting = settingAsInt;
54 eventData->settingState = enabled ? CHRE_USER_SETTING_STATE_ENABLED
55 : CHRE_USER_SETTING_STATE_DISABLED;
56
57 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
58 eventType, eventData, freeEventDataCallback, kBroadcastInstanceId);
59 } else {
60 LOG_OOM();
61 }
62 }
63
64 } // anonymous namespace
65
SettingManager()66 SettingManager::SettingManager() {
67 // Default most settings to true until the host tells us otherwise so
68 // nanoapps can begin work during boot which will get canceled if the user has
69 // disabled the feature.
70 for (size_t i = 0; i < ARRAY_SIZE(mSettingStateList); ++i) {
71 mSettingStateList[i] = true;
72 }
73
74 // Airplane mode should be disabled since it being enabled causes API usage
75 // restrictions.
76 auto airplaneIndex = static_cast<uint8_t>(Setting::AIRPLANE_MODE);
77 mSettingStateList[airplaneIndex] = false;
78 }
79
postSettingChange(Setting setting,bool enabled)80 void SettingManager::postSettingChange(Setting setting, bool enabled) {
81 LOGD("Posting setting change: setting type %" PRIu8 " enabled %d",
82 static_cast<uint8_t>(setting), enabled);
83
84 EventLoopManagerSingleton::get()->deferCallback(
85 SystemCallbackType::SettingChangeEvent, NestedDataPtr<Setting>(setting),
86 settingChangedCallback, NestedDataPtr<bool>(enabled));
87 }
88
getSettingEnabled(Setting setting)89 bool SettingManager::getSettingEnabled(Setting setting) {
90 size_t index;
91 if (getIndexForSetting(setting, &index)) {
92 return mSettingStateList[index];
93 }
94
95 LOGE("Unknown setting %" PRIu8, static_cast<uint8_t>(setting));
96 return false;
97 }
98
getSettingStateAsInt8(uint8_t setting)99 int8_t SettingManager::getSettingStateAsInt8(uint8_t setting) {
100 int8_t state = CHRE_USER_SETTING_STATE_UNKNOWN;
101 if (setting < static_cast<uint8_t>(Setting::SETTING_MAX)) {
102 auto settingEnum = static_cast<Setting>(setting);
103 state = static_cast<int8_t>(getSettingEnabled(settingEnum));
104 }
105 return state;
106 }
107
logStateToBuffer(DebugDumpWrapper & debugDump)108 void SettingManager::logStateToBuffer(DebugDumpWrapper &debugDump) {
109 debugDump.print("\nSettings:");
110 debugDump.print("\n Location %s", getSettingEnabledString(Setting::LOCATION));
111 debugDump.print("\n WiFi available %s",
112 getSettingEnabledString(Setting::WIFI_AVAILABLE));
113 debugDump.print("\n Airplane mode %s",
114 getSettingEnabledString(Setting::AIRPLANE_MODE));
115 debugDump.print("\n Microphone Access %s",
116 getSettingEnabledString(Setting::MICROPHONE));
117 debugDump.print("\n BLE available %s",
118 getSettingEnabledString(Setting::BLE_AVAILABLE));
119 }
120
settingChangedCallback(uint16_t,void * data,void * extraData)121 void SettingManager::settingChangedCallback(uint16_t /* type */, void *data,
122 void *extraData) {
123 Setting setting = NestedDataPtr<Setting>(data);
124 bool settingEnabled = NestedDataPtr<bool>(extraData);
125
126 EventLoopManagerSingleton::get()->getSettingManager().setSettingState(
127 setting, settingEnabled);
128
129 LOGD("Setting changed callback called for setting %u enabled %d",
130 static_cast<uint8_t>(setting), settingEnabled);
131
132 #ifdef CHRE_GNSS_SUPPORT_ENABLED
133 EventLoopManagerSingleton::get()->getGnssManager().onSettingChanged(
134 setting, settingEnabled);
135 #endif // CHRE_GNSS_SUPPORT_ENABLED
136
137 #ifdef CHRE_AUDIO_SUPPORT_ENABLED
138 EventLoopManagerSingleton::get()->getAudioRequestManager().onSettingChanged(
139 setting, settingEnabled);
140 #endif // CHRE_AUDIO_SUPPORT_ENABLED
141
142 #ifdef CHRE_BLE_SUPPORT_ENABLED
143 EventLoopManagerSingleton::get()->getBleRequestManager().onSettingChanged(
144 setting, settingEnabled);
145 #endif // CHRE_BLE_SUPPORT_ENABLED
146
147 #ifdef CHRE_WIFI_SUPPORT_ENABLED
148 EventLoopManagerSingleton::get()->getWifiRequestManager().onSettingChanged(
149 setting, settingEnabled);
150 #endif // CHRE_WIFI_SUPPORT_ENABLED
151
152 sendSettingChangedNotification(setting, settingEnabled);
153 }
154
setSettingState(Setting setting,bool enabled)155 void SettingManager::setSettingState(Setting setting, bool enabled) {
156 size_t index;
157 if (!getIndexForSetting(setting, &index)) {
158 LOGE("Unknown setting %" PRId8, static_cast<int8_t>(setting));
159 } else {
160 mSettingStateList[index] = enabled;
161 }
162 }
163
getSettingEnabledString(Setting setting)164 const char *SettingManager::getSettingEnabledString(Setting setting) {
165 if (getSettingEnabled(setting)) {
166 return "enabled";
167 } else {
168 return "disabled";
169 }
170 }
171
172 } // namespace chre
173