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
26namespace android
27{
28    void doStartupConfig ();
29}
30
31extern bool         gActivated;
32extern SyncEvent    gDeactivatedEvent;
33
34PowerSwitch PowerSwitch::sPowerSwitch;
35const PowerSwitch::PowerActivity PowerSwitch::DISCOVERY=0x01;
36const PowerSwitch::PowerActivity PowerSwitch::SE_ROUTING=0x02;
37const PowerSwitch::PowerActivity PowerSwitch::SE_CONNECTED=0x04;
38const PowerSwitch::PowerActivity PowerSwitch::HOST_ROUTING=0x08;
39
40/*******************************************************************************
41**
42** Function:        PowerSwitch
43**
44** Description:     Initialize member variables.
45**
46** Returns:         None
47**
48*******************************************************************************/
49PowerSwitch::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*******************************************************************************/
68PowerSwitch::~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*******************************************************************************/
82PowerSwitch& 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*******************************************************************************/
97void 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*******************************************************************************/
138PowerSwitch::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*******************************************************************************/
158bool 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
216TheEnd:
217    mMutex.unlock ();
218    return retval;
219}
220
221
222bool 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*******************************************************************************/
244bool 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*******************************************************************************/
266bool 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*******************************************************************************/
289bool 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;
360TheEnd:
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*******************************************************************************/
376const 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*******************************************************************************/
400const 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*******************************************************************************/
427const 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*******************************************************************************/
451void 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*******************************************************************************/
471void 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*******************************************************************************/
506bool PowerSwitch::isPowerOffSleepFeatureEnabled ()
507{
508    return mDesiredScreenOffPowerState == 0;
509}
510
511