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/nested_data_ptr.h"
24
25 #include "chre_api/chre/user_settings.h"
26
27 namespace chre {
28
29 namespace {
30
31 constexpr size_t kNumSettings = static_cast<size_t>(Setting::SETTING_MAX);
32
33 //! The current state for each setting.
34 SettingState gSettingStateList[kNumSettings];
35
36 /**
37 * @param setting The setting to get the index for.
38 * @param index A non-null pointer to store the index.
39 *
40 * @return false if the setting was invalid.
41 */
getIndexForSetting(Setting setting,size_t * index)42 bool getIndexForSetting(Setting setting, size_t *index) {
43 if (setting < Setting::SETTING_MAX) {
44 *index = static_cast<size_t>(setting);
45 return true;
46 }
47
48 return false;
49 }
50
setSettingState(Setting setting,SettingState state)51 void setSettingState(Setting setting, SettingState state) {
52 size_t index;
53 if (!getIndexForSetting(setting, &index)) {
54 LOGE("Unknown setting %" PRId8, static_cast<int8_t>(setting));
55 } else {
56 gSettingStateList[index] = state;
57 }
58 }
59
getSettingStateString(Setting setting)60 const char *getSettingStateString(Setting setting) {
61 switch (getSettingState(setting)) {
62 case SettingState::ENABLED:
63 return "enabled";
64 break;
65 case SettingState::DISABLED:
66 return "disabled";
67 break;
68 default:
69 break;
70 }
71
72 return "unknown";
73 }
74
sendSettingChangedNotification(Setting setting,SettingState state)75 void sendSettingChangedNotification(Setting setting, SettingState state) {
76 auto *eventData = memoryAlloc<struct chreUserSettingChangedEvent>();
77 auto settingAsInt = static_cast<uint8_t>(setting);
78 uint16_t eventType = CHRE_EVENT_SETTING_CHANGED_FIRST_EVENT + settingAsInt;
79
80 if (eventData != nullptr) {
81 eventData->setting = settingAsInt;
82 eventData->settingState = static_cast<int8_t>(state);
83
84 EventLoopManagerSingleton::get()->getEventLoop().postEventOrDie(
85 eventType, eventData, freeEventDataCallback, kBroadcastInstanceId);
86 } else {
87 LOG_OOM();
88 }
89 }
90
settingChangedCallback(uint16_t,void * data,void * extraData)91 void settingChangedCallback(uint16_t /* type */, void *data, void *extraData) {
92 Setting setting = NestedDataPtr<Setting>(data);
93 SettingState settingState = NestedDataPtr<SettingState>(extraData);
94
95 setSettingState(setting, settingState);
96
97 LOGD("Setting changed callback called for setting %u state %u",
98 static_cast<uint8_t>(setting), static_cast<uint8_t>(settingState));
99
100 #ifdef CHRE_GNSS_SUPPORT_ENABLED
101 EventLoopManagerSingleton::get()->getGnssManager().onSettingChanged(
102 setting, settingState);
103 #endif // CHRE_GNSS_SUPPORT_ENABLED
104
105 #ifdef CHRE_AUDIO_SUPPORT_ENABLED
106 EventLoopManagerSingleton::get()->getAudioRequestManager().onSettingChanged(
107 setting, settingState);
108 #endif // CHRE_AUDIO_SUPPORT_ENABLED
109
110 sendSettingChangedNotification(setting, settingState);
111 }
112
113 } // anonymous namespace
114
postSettingChange(Setting setting,SettingState state)115 void postSettingChange(Setting setting, SettingState state) {
116 LOGD("Posting setting change: setting type %" PRIu8 " state %" PRIu8,
117 static_cast<uint8_t>(setting), static_cast<uint8_t>(state));
118
119 EventLoopManagerSingleton::get()->deferCallback(
120 SystemCallbackType::SettingChangeEvent, NestedDataPtr<Setting>(setting),
121 settingChangedCallback, NestedDataPtr<SettingState>(state));
122 }
123
getSettingState(Setting setting)124 SettingState getSettingState(Setting setting) {
125 size_t index;
126 if (getIndexForSetting(setting, &index)) {
127 return gSettingStateList[index];
128 }
129
130 LOGE("Unknown setting %" PRIu8, static_cast<uint8_t>(setting));
131 return SettingState::UNKNOWN;
132 }
133
getSettingStateAsInt8(uint8_t setting)134 int8_t getSettingStateAsInt8(uint8_t setting) {
135 int8_t state = CHRE_USER_SETTING_STATE_UNKNOWN;
136 if (setting < static_cast<uint8_t>(Setting::SETTING_MAX)) {
137 auto settingEnum = static_cast<Setting>(setting);
138 state = static_cast<int8_t>(getSettingState(settingEnum));
139 }
140 return state;
141 }
142
logSettingStateToBuffer(DebugDumpWrapper & debugDump)143 void logSettingStateToBuffer(DebugDumpWrapper &debugDump) {
144 debugDump.print("\nSettings:");
145 debugDump.print("\n Location %s", getSettingStateString(Setting::LOCATION));
146 debugDump.print("\n WiFi available %s",
147 getSettingStateString(Setting::WIFI_AVAILABLE));
148 debugDump.print("\n Airplane mode %s",
149 getSettingStateString(Setting::AIRPLANE_MODE));
150 debugDump.print("\n Microphone Access %s",
151 getSettingStateString(Setting::MICROPHONE));
152 }
153
154 } // namespace chre
155