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