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