Home | History | Annotate | Download | only in jni
      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 *******************************************************************************/
     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 *******************************************************************************/
     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 *******************************************************************************/
     79 PowerSwitch& PowerSwitch::getInstance() { return sPowerSwitch; }
     80 
     81 /*******************************************************************************
     82 **
     83 ** Function:        initialize
     84 **
     85 ** Description:     Initialize member variables.
     86 **
     87 ** Returns:         None
     88 **
     89 *******************************************************************************/
     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 *******************************************************************************/
    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 *******************************************************************************/
    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 
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    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 *******************************************************************************/
    481 bool PowerSwitch::isPowerOffSleepFeatureEnabled() {
    482   return mDesiredScreenOffPowerState == 0;
    483 }
    484