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