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,SettingState state)47 void sendSettingChangedNotification(Setting setting, SettingState state) {
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 = static_cast<int8_t>(state);
55
56 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
57 eventType, eventData, freeEventDataCallback, kBroadcastInstanceId);
58 } else {
59 LOG_OOM();
60 }
61 }
62
63 } // anonymous namespace
64
SettingManager()65 SettingManager::SettingManager() {
66 // Default most settings to true until the host tells us otherwise so
67 // nanoapps can begin work during boot which will get canceled if the user has
68 // disabled the feature.
69 for (size_t i = 0; i < ARRAY_SIZE(mSettingStateList); ++i) {
70 mSettingStateList[i] = SettingState::ENABLED;
71 }
72
73 // Airplane mode should be disabled since it being enabled causes API usage
74 // restrictions.
75 auto airplaneIndex = static_cast<uint8_t>(Setting::AIRPLANE_MODE);
76 mSettingStateList[airplaneIndex] = SettingState::DISABLED;
77 }
78
postSettingChange(Setting setting,SettingState state)79 void SettingManager::postSettingChange(Setting setting, SettingState state) {
80 LOGD("Posting setting change: setting type %" PRIu8 " state %" PRIu8,
81 static_cast<uint8_t>(setting), static_cast<uint8_t>(state));
82
83 EventLoopManagerSingleton::get()->deferCallback(
84 SystemCallbackType::SettingChangeEvent, NestedDataPtr<Setting>(setting),
85 settingChangedCallback, NestedDataPtr<SettingState>(state));
86 }
87
getSettingState(Setting setting)88 SettingState SettingManager::getSettingState(Setting setting) {
89 size_t index;
90 if (getIndexForSetting(setting, &index)) {
91 return mSettingStateList[index];
92 }
93
94 LOGE("Unknown setting %" PRIu8, static_cast<uint8_t>(setting));
95 return SettingState::UNKNOWN;
96 }
97
getSettingStateAsInt8(uint8_t setting)98 int8_t SettingManager::getSettingStateAsInt8(uint8_t setting) {
99 int8_t state = CHRE_USER_SETTING_STATE_UNKNOWN;
100 if (setting < static_cast<uint8_t>(Setting::SETTING_MAX)) {
101 auto settingEnum = static_cast<Setting>(setting);
102 state = static_cast<int8_t>(getSettingState(settingEnum));
103 }
104 return state;
105 }
106
logStateToBuffer(DebugDumpWrapper & debugDump)107 void SettingManager::logStateToBuffer(DebugDumpWrapper &debugDump) {
108 debugDump.print("\nSettings:");
109 debugDump.print("\n Location %s", getSettingStateString(Setting::LOCATION));
110 debugDump.print("\n WiFi available %s",
111 getSettingStateString(Setting::WIFI_AVAILABLE));
112 debugDump.print("\n Airplane mode %s",
113 getSettingStateString(Setting::AIRPLANE_MODE));
114 debugDump.print("\n Microphone Access %s",
115 getSettingStateString(Setting::MICROPHONE));
116 }
117
settingChangedCallback(uint16_t,void * data,void * extraData)118 void SettingManager::settingChangedCallback(uint16_t /* type */, void *data,
119 void *extraData) {
120 Setting setting = NestedDataPtr<Setting>(data);
121 SettingState settingState = NestedDataPtr<SettingState>(extraData);
122
123 EventLoopManagerSingleton::get()->getSettingManager().setSettingState(
124 setting, settingState);
125
126 LOGD("Setting changed callback called for setting %u state %u",
127 static_cast<uint8_t>(setting), static_cast<uint8_t>(settingState));
128
129 #ifdef CHRE_GNSS_SUPPORT_ENABLED
130 EventLoopManagerSingleton::get()->getGnssManager().onSettingChanged(
131 setting, settingState);
132 #endif // CHRE_GNSS_SUPPORT_ENABLED
133
134 #ifdef CHRE_AUDIO_SUPPORT_ENABLED
135 EventLoopManagerSingleton::get()->getAudioRequestManager().onSettingChanged(
136 setting, settingState);
137 #endif // CHRE_AUDIO_SUPPORT_ENABLED
138
139 sendSettingChangedNotification(setting, settingState);
140 }
141
setSettingState(Setting setting,SettingState state)142 void SettingManager::setSettingState(Setting setting, SettingState state) {
143 size_t index;
144 if (!getIndexForSetting(setting, &index)) {
145 LOGE("Unknown setting %" PRId8, static_cast<int8_t>(setting));
146 } else {
147 mSettingStateList[index] = state;
148 }
149 }
150
getSettingStateString(Setting setting)151 const char *SettingManager::getSettingStateString(Setting setting) {
152 switch (getSettingState(setting)) {
153 case SettingState::ENABLED:
154 return "enabled";
155 break;
156 case SettingState::DISABLED:
157 return "disabled";
158 break;
159 default:
160 break;
161 }
162
163 return "unknown";
164 }
165
166 } // namespace chre
167