1 /*
2 * Copyright (C) 2012 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 /*
18 * Adjust the controller's power states.
19 */
20 #include "PowerSwitch.h"
21
22 #include <android-base/logging.h>
23 #include <android-base/stringprintf.h>
24
25 #include "NfcJniUtil.h"
26 #include "nfc_config.h"
27
28 using android::base::StringPrintf;
29
30 namespace android {
31 void doStartupConfig();
32 }
33
34 extern bool gActivated;
35
36 extern SyncEvent gDeactivatedEvent;
37
38 PowerSwitch PowerSwitch::sPowerSwitch;
39 const PowerSwitch::PowerActivity PowerSwitch::DISCOVERY = 0x01;
40 const PowerSwitch::PowerActivity PowerSwitch::SE_ROUTING = 0x02;
41 const PowerSwitch::PowerActivity PowerSwitch::SE_CONNECTED = 0x04;
42 const PowerSwitch::PowerActivity PowerSwitch::HOST_ROUTING = 0x08;
43
44 /*******************************************************************************
45 **
46 ** Function: PowerSwitch
47 **
48 ** Description: Initialize member variables.
49 **
50 ** Returns: None
51 **
52 *******************************************************************************/
PowerSwitch()53 PowerSwitch::PowerSwitch()
54 : mCurrLevel(UNKNOWN_LEVEL),
55 mCurrDeviceMgtPowerState(NFA_DM_PWR_STATE_UNKNOWN),
56 mExpectedDeviceMgtPowerState(NFA_DM_PWR_STATE_UNKNOWN),
57 mDesiredScreenOffPowerState(0),
58 mCurrActivity(0) {}
59
60 /*******************************************************************************
61 **
62 ** Function: ~PowerSwitch
63 **
64 ** Description: Release all resources.
65 **
66 ** Returns: None
67 **
68 *******************************************************************************/
~PowerSwitch()69 PowerSwitch::~PowerSwitch() {}
70
71 /*******************************************************************************
72 **
73 ** Function: getInstance
74 **
75 ** Description: Get the singleton of this object.
76 **
77 ** Returns: Reference to this object.
78 **
79 *******************************************************************************/
getInstance()80 PowerSwitch& PowerSwitch::getInstance() { return sPowerSwitch; }
81
82 /*******************************************************************************
83 **
84 ** Function: initialize
85 **
86 ** Description: Initialize member variables.
87 **
88 ** Returns: None
89 **
90 *******************************************************************************/
initialize(PowerLevel level)91 void PowerSwitch::initialize(PowerLevel level) {
92 static const char fn[] = "PowerSwitch::initialize";
93
94 mMutex.lock();
95
96 LOG(DEBUG) << StringPrintf("%s: level=%s (%u)", fn, powerLevelToString(level),
97 level);
98 if (NfcConfig::hasKey(NAME_SCREEN_OFF_POWER_STATE))
99 mDesiredScreenOffPowerState =
100 (int)NfcConfig::getUnsigned(NAME_SCREEN_OFF_POWER_STATE);
101 LOG(DEBUG) << StringPrintf("%s: desired screen-off state=%d", fn,
102 mDesiredScreenOffPowerState);
103
104 switch (level) {
105 case FULL_POWER:
106 mCurrDeviceMgtPowerState = NFA_DM_PWR_MODE_FULL;
107 mCurrLevel = level;
108 break;
109
110 case UNKNOWN_LEVEL:
111 mCurrDeviceMgtPowerState = NFA_DM_PWR_STATE_UNKNOWN;
112 mCurrLevel = level;
113 break;
114
115 default:
116 LOG(ERROR) << StringPrintf("%s: not handled", fn);
117 break;
118 }
119 mMutex.unlock();
120 }
121
122 /*******************************************************************************
123 **
124 ** Function: getLevel
125 **
126 ** Description: Get the current power level of the controller.
127 **
128 ** Returns: Power level.
129 **
130 *******************************************************************************/
getLevel()131 PowerSwitch::PowerLevel PowerSwitch::getLevel() {
132 PowerLevel level = UNKNOWN_LEVEL;
133 mMutex.lock();
134 level = mCurrLevel;
135 mMutex.unlock();
136 return level;
137 }
138
139 /*******************************************************************************
140 **
141 ** Function: setLevel
142 **
143 ** Description: Set the controller's power level.
144 ** level: power level.
145 **
146 ** Returns: True if ok.
147 **
148 *******************************************************************************/
setLevel(PowerLevel newLevel)149 bool PowerSwitch::setLevel(PowerLevel newLevel) {
150 static const char fn[] = "PowerSwitch::setLevel";
151 bool retval = false;
152
153 mMutex.lock();
154
155 LOG(DEBUG) << StringPrintf("%s: level=%s (%u)", fn,
156 powerLevelToString(newLevel), newLevel);
157 if (mCurrLevel == newLevel) {
158 retval = true;
159 goto TheEnd;
160 }
161
162 if (mCurrLevel == UNKNOWN_LEVEL) {
163 LOG(ERROR) << StringPrintf("%s: unknown power level", fn);
164 goto TheEnd;
165 }
166
167 if ((mCurrLevel == LOW_POWER && newLevel == FULL_POWER) ||
168 (mCurrLevel == FULL_POWER && newLevel == LOW_POWER)) {
169 mMutex.unlock();
170 SyncEventGuard g(gDeactivatedEvent);
171 if (gActivated) {
172 LOG(DEBUG) << StringPrintf("%s: wait for deactivation", fn);
173 gDeactivatedEvent.wait();
174 }
175 mMutex.lock();
176 }
177
178 switch (newLevel) {
179 case FULL_POWER:
180 if (mCurrDeviceMgtPowerState == NFA_DM_PWR_MODE_OFF_SLEEP)
181 retval = setPowerOffSleepState(false);
182 break;
183
184 case LOW_POWER:
185 case POWER_OFF:
186 if (isPowerOffSleepFeatureEnabled())
187 retval = setPowerOffSleepState(true);
188 else if (mDesiredScreenOffPowerState ==
189 1) //.conf file desires full-power
190 {
191 mCurrLevel = FULL_POWER;
192 retval = true;
193 }
194 break;
195
196 default:
197 LOG(ERROR) << StringPrintf("%s: not handled", fn);
198 break;
199 }
200
201 LOG(DEBUG) << StringPrintf("%s: actual power level=%s", fn,
202 powerLevelToString(mCurrLevel));
203
204 TheEnd:
205 mMutex.unlock();
206 return retval;
207 }
208
setScreenOffPowerState(ScreenOffPowerState newState)209 bool PowerSwitch::setScreenOffPowerState(ScreenOffPowerState newState) {
210 LOG(DEBUG) << StringPrintf(
211 "PowerSwitch::setScreenOffPowerState: level=%s (%u)",
212 screenOffPowerStateToString(newState), newState);
213
214 mMutex.lock();
215 mDesiredScreenOffPowerState = (int)newState;
216 mMutex.unlock();
217
218 return true;
219 }
220
221 /*******************************************************************************
222 **
223 ** Function: setModeOff
224 **
225 ** Description: Set a mode to be deactive.
226 **
227 ** Returns: True if any mode is still active.
228 **
229 *******************************************************************************/
setModeOff(PowerActivity deactivated)230 bool PowerSwitch::setModeOff(PowerActivity deactivated) {
231 bool retVal = false;
232
233 mMutex.lock();
234 mCurrActivity &= ~deactivated;
235 retVal = mCurrActivity != 0;
236 LOG(DEBUG) << StringPrintf(
237 "PowerSwitch::setModeOff(deactivated=0x%x) : mCurrActivity=0x%x",
238 deactivated, mCurrActivity);
239 mMutex.unlock();
240 return retVal;
241 }
242
243 /*******************************************************************************
244 **
245 ** Function: setModeOn
246 **
247 ** Description: Set a mode to be active.
248 **
249 ** Returns: True if any mode is active.
250 **
251 *******************************************************************************/
setModeOn(PowerActivity activated)252 bool PowerSwitch::setModeOn(PowerActivity activated) {
253 bool retVal = false;
254
255 mMutex.lock();
256 mCurrActivity |= activated;
257 retVal = mCurrActivity != 0;
258 LOG(DEBUG) << StringPrintf(
259 "PowerSwitch::setModeOn(activated=0x%x) : mCurrActivity=0x%x", activated,
260 mCurrActivity);
261 mMutex.unlock();
262 return retVal;
263 }
264
265 /*******************************************************************************
266 **
267 ** Function: setPowerOffSleepState
268 **
269 ** Description: Adjust controller's power-off-sleep state.
270 ** sleep: whether to enter sleep state.
271 **
272 ** Returns: True if ok.
273 **
274 *******************************************************************************/
setPowerOffSleepState(bool sleep)275 bool PowerSwitch::setPowerOffSleepState(bool sleep) {
276 static const char fn[] = "PowerSwitch::setPowerOffSleepState";
277 LOG(DEBUG) << StringPrintf("%s: enter; sleep=%u", fn, sleep);
278 tNFA_STATUS stat = NFA_STATUS_FAILED;
279 bool retval = false;
280
281 if (sleep) // enter power-off-sleep state
282 {
283 // make sure the current power state is ON
284 if (mCurrDeviceMgtPowerState != NFA_DM_PWR_MODE_OFF_SLEEP) {
285 SyncEventGuard guard(mPowerStateEvent);
286 mExpectedDeviceMgtPowerState =
287 NFA_DM_PWR_MODE_OFF_SLEEP; // if power adjustment is ok, then this is
288 // the expected state
289 LOG(DEBUG) << StringPrintf("%s: try power off", fn);
290 stat = NFA_PowerOffSleepMode(TRUE);
291 if (stat == NFA_STATUS_OK) {
292 mPowerStateEvent.wait();
293 mCurrLevel = LOW_POWER;
294 } else {
295 LOG(ERROR) << StringPrintf("%s: API fail; stat=0x%X", fn, stat);
296 goto TheEnd;
297 }
298 } else {
299 LOG(ERROR) << StringPrintf(
300 "%s: power is not ON; curr device mgt power state=%s (%u)", fn,
301 deviceMgtPowerStateToString(mCurrDeviceMgtPowerState),
302 mCurrDeviceMgtPowerState);
303 goto TheEnd;
304 }
305 } else // exit power-off-sleep state
306 {
307 // make sure the current power state is OFF
308 if (mCurrDeviceMgtPowerState != NFA_DM_PWR_MODE_FULL) {
309 SyncEventGuard guard(mPowerStateEvent);
310 mCurrDeviceMgtPowerState = NFA_DM_PWR_STATE_UNKNOWN;
311 mExpectedDeviceMgtPowerState =
312 NFA_DM_PWR_MODE_FULL; // if power adjustment is ok, then this is the
313 // expected state
314 LOG(DEBUG) << StringPrintf("%s: try full power", fn);
315 stat = NFA_PowerOffSleepMode(FALSE);
316 if (stat == NFA_STATUS_OK) {
317 mPowerStateEvent.wait();
318 if (mCurrDeviceMgtPowerState != NFA_DM_PWR_MODE_FULL) {
319 LOG(ERROR) << StringPrintf(
320 "%s: unable to full power; curr device mgt power stat=%s (%u)",
321 fn, deviceMgtPowerStateToString(mCurrDeviceMgtPowerState),
322 mCurrDeviceMgtPowerState);
323 goto TheEnd;
324 }
325 android::doStartupConfig();
326 mCurrLevel = FULL_POWER;
327 } else {
328 LOG(ERROR) << StringPrintf("%s: API fail; stat=0x%X", fn, stat);
329 goto TheEnd;
330 }
331 } else {
332 LOG(ERROR) << StringPrintf(
333 "%s: not in power-off state; curr device mgt power state=%s (%u)", fn,
334 deviceMgtPowerStateToString(mCurrDeviceMgtPowerState),
335 mCurrDeviceMgtPowerState);
336 goto TheEnd;
337 }
338 }
339
340 retval = true;
341 TheEnd:
342 LOG(DEBUG) << StringPrintf("%s: exit; return %u", fn, retval);
343 return retval;
344 }
345
346 /*******************************************************************************
347 **
348 ** Function: deviceMgtPowerStateToString
349 **
350 ** Description: Decode power level to a string.
351 ** deviceMgtPowerState: power level.
352 **
353 ** Returns: Text representation of power level.
354 **
355 *******************************************************************************/
deviceMgtPowerStateToString(uint8_t deviceMgtPowerState)356 const char* PowerSwitch::deviceMgtPowerStateToString(
357 uint8_t deviceMgtPowerState) {
358 switch (deviceMgtPowerState) {
359 case NFA_DM_PWR_MODE_FULL:
360 return "DM-FULL";
361 case NFA_DM_PWR_MODE_OFF_SLEEP:
362 return "DM-OFF";
363 default:
364 return "DM-unknown????";
365 }
366 }
367
368 /*******************************************************************************
369 **
370 ** Function: powerLevelToString
371 **
372 ** Description: Decode power level to a string.
373 ** level: power level.
374 **
375 ** Returns: Text representation of power level.
376 **
377 *******************************************************************************/
powerLevelToString(PowerLevel level)378 const char* PowerSwitch::powerLevelToString(PowerLevel level) {
379 switch (level) {
380 case UNKNOWN_LEVEL:
381 return "PS-UNKNOWN";
382 case FULL_POWER:
383 return "PS-FULL";
384 case LOW_POWER:
385 return "PS-LOW-POWER";
386 case POWER_OFF:
387 return "PS-POWER-OFF";
388 default:
389 return "PS-unknown????";
390 }
391 }
392
393 /*******************************************************************************
394 **
395 ** Function: screenOffPowerStateToString
396 **
397 ** Description: Decode power level to a string.
398 ** level: power level.
399 **
400 ** Returns: Text representation of power level.
401 **
402 *******************************************************************************/
screenOffPowerStateToString(ScreenOffPowerState state)403 const char* PowerSwitch::screenOffPowerStateToString(
404 ScreenOffPowerState state) {
405 switch (state) {
406 case POWER_STATE_OFF:
407 return "SOPS-POWER_OFF";
408 case POWER_STATE_FULL:
409 return "SOPS-FULL";
410 case POWER_STATE_CARD_EMULATION:
411 return "SOPS-CARD_EMULATION";
412 default:
413 return "SOPS-unknown????";
414 }
415 }
416
417 /*******************************************************************************
418 **
419 ** Function: abort
420 **
421 ** Description: Abort and unblock currrent operation.
422 **
423 ** Returns: None
424 **
425 *******************************************************************************/
abort()426 void PowerSwitch::abort() {
427 static const char fn[] = "PowerSwitch::abort";
428 LOG(DEBUG) << StringPrintf("%s", fn);
429 SyncEventGuard guard(mPowerStateEvent);
430 mPowerStateEvent.notifyOne();
431 }
432
433 /*******************************************************************************
434 **
435 ** Function: deviceManagementCallback
436 **
437 ** Description: Callback function for the stack.
438 ** event: event ID.
439 ** eventData: event's data.
440 **
441 ** Returns: None
442 **
443 *******************************************************************************/
deviceManagementCallback(uint8_t event,tNFA_DM_CBACK_DATA * eventData)444 void PowerSwitch::deviceManagementCallback(uint8_t event,
445 tNFA_DM_CBACK_DATA* eventData) {
446 static const char fn[] = "PowerSwitch::deviceManagementCallback";
447
448 switch (event) {
449 case NFA_DM_PWR_MODE_CHANGE_EVT: {
450 tNFA_DM_PWR_MODE_CHANGE& power_mode = eventData->power_mode;
451 LOG(DEBUG) << StringPrintf(
452 "%s: NFA_DM_PWR_MODE_CHANGE_EVT; status=0x%X; device mgt power "
453 "state=%s (0x%X)",
454 fn, power_mode.status,
455 sPowerSwitch.deviceMgtPowerStateToString(power_mode.power_mode),
456 power_mode.power_mode);
457 SyncEventGuard guard(sPowerSwitch.mPowerStateEvent);
458 if (power_mode.status == NFA_STATUS_OK) {
459 // the event data does not contain the newly configured power mode,
460 // so this code assigns the expected value
461 sPowerSwitch.mCurrDeviceMgtPowerState =
462 sPowerSwitch.mExpectedDeviceMgtPowerState;
463 }
464 sPowerSwitch.mPowerStateEvent.notifyOne();
465 } break;
466 }
467 }
468
469 /*******************************************************************************
470 **
471 ** Function: isPowerOffSleepFeatureEnabled
472 **
473 ** Description: Whether power-off-sleep feature is enabled in .conf file.
474 **
475 ** Returns: True if feature is enabled.
476 **
477 *******************************************************************************/
isPowerOffSleepFeatureEnabled()478 bool PowerSwitch::isPowerOffSleepFeatureEnabled() {
479 return mDesiredScreenOffPowerState == 0;
480 }
481