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