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