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