NfCC power state tracker implementation
Calculate and log amount of time spent by NFCC
in following power states
1. Active mode.
2. Standby mode.
This log information can be read from
/data/vendor/nfc/nfc_power_state.txt
Bug:68656882
Test: NFC Enable, Disable & VTS Test.
Change-Id: I0692add33bd877e8425acb8b57bd84766ee6358b
diff --git a/Android.bp b/Android.bp
index 9b018fe..6f12e84 100755
--- a/Android.bp
+++ b/Android.bp
@@ -46,6 +46,7 @@
"halimpl/utils/phNxpConfig.cpp",
"halimpl/utils/phNxpNciHal_utils.cc",
"halimpl/utils/sparse_crc32.cc",
+ "halimpl/utils/NfccPowerTracker.cpp",
],
local_include_dirs: [
diff --git a/halimpl/hal/phNxpNciHal.cc b/halimpl/hal/phNxpNciHal.cc
index 15ebac9..f579f0c 100755
--- a/halimpl/hal/phNxpNciHal.cc
+++ b/halimpl/hal/phNxpNciHal.cc
@@ -13,13 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
+#include "NfccPowerTracker.h"
+#include "hal_nxpese.h"
+#include "hal_nxpnfc.h"
+#include "spi_spm.h"
+#include <EseAdaptation.h>
+#include <cutils/properties.h>
#include <log/log.h>
#include <phDal4Nfc_messageQueueLib.h>
#include <phDnldNfc.h>
#include <phNxpConfig.h>
#include <phNxpLog.h>
-#include <cutils/properties.h>
#include <phNxpNciHal.h>
#include <phNxpNciHal_Adaptation.h>
#include <phNxpNciHal_Dnld.h>
@@ -27,10 +31,6 @@
#include <phNxpNciHal_ext.h>
#include <phTmlNfc.h>
#include <sys/stat.h>
-#include <EseAdaptation.h>
-#include "hal_nxpnfc.h"
-#include "hal_nxpese.h"
-#include "spi_spm.h"
using namespace android::hardware::nfc::V1_1;
using android::hardware::nfc::V1_1::NfcEvent;
@@ -728,7 +728,7 @@
NXPLOG_NCIHAL_D("FW download Success");
}
}
-
+ NfccPowerTracker::getInstance().Initialize();
/* Call open complete */
phNxpNciHal_MinOpen_complete(wConfigStatus);
NXPLOG_NCIHAL_D("phNxpNciHal_MinOpen(): exit");
@@ -974,6 +974,9 @@
goto clean_and_return;
}
+ NfccPowerTracker::getInstance().ProcessCmd(
+ (uint8_t *)nxpncihal_ctrl.p_cmd_data, (uint16_t)nxpncihal_ctrl.cmd_len);
+
retry:
data_len = nxpncihal_ctrl.cmd_len;
@@ -1107,6 +1110,10 @@
phNxpNciHal_print_res_status(pInfo->pBuff, &pInfo->wLength);
+ if ((nxpncihal_ctrl.p_rx_data[0x00] & NCI_MT_MASK) == NCI_MT_NTF) {
+ NfccPowerTracker::getInstance().ProcessNtf(nxpncihal_ctrl.p_rx_data,
+ nxpncihal_ctrl.rx_data_len);
+ }
/* Check if response should go to hal module only */
if (nxpncihal_ctrl.hal_ext_enabled == TRUE &&
(nxpncihal_ctrl.p_rx_data[0x00] & NCI_MT_MASK) == NCI_MT_RSP) {
@@ -2153,7 +2160,7 @@
NXPLOG_NCIHAL_D("phNxpNciHal_close - phOsalNfc_DeInit completed");
}
-
+ NfccPowerTracker::getInstance().Pause();
CONCURRENCY_UNLOCK();
phNxpNciHal_cleanup_monitor();
@@ -2197,6 +2204,7 @@
******************************************************************************/
int phNxpNciHal_configDiscShutdown(void) {
NFCSTATUS status;
+ NfccPowerTracker::getInstance().Reset();
status = phNxpNciHal_close(true);
if(status != NFCSTATUS_SUCCESS) {
diff --git a/halimpl/libnfc-nxp-PN81B_example_NCI2_0.conf b/halimpl/libnfc-nxp-PN81B_example_NCI2_0.conf
index 03bcb20..d3fbec9 100755
--- a/halimpl/libnfc-nxp-PN81B_example_NCI2_0.conf
+++ b/halimpl/libnfc-nxp-PN81B_example_NCI2_0.conf
@@ -127,7 +127,8 @@
# DWP intf behavior config, SVDD Load activated by default if set to 0x31 A037
# SPI CL Sync enable A098
# EVT END OF Operation delay A0B2
-NXP_CORE_CONF_EXTN={20, 02, 31, 0C,
+# Power tracker command A091
+NXP_CORE_CONF_EXTN={20, 02, 35, 0D,
A0, EC, 01, 01,
A0, ED, 01, 01,
A0, 5E, 01, 01,
@@ -139,7 +140,8 @@
A0, D8, 01, 02,
A0, D5, 01, 0A,
A0, 98, 01, 03,
- A0, B2, 01, 19
+ A0, B2, 01, 19,
+ A0, 91, 01, 01
}
###############################################################################
diff --git a/halimpl/libnfc-nxp-PN81T_example_NCI2_0.conf b/halimpl/libnfc-nxp-PN81T_example_NCI2_0.conf
index c6d81f9..1286368 100755
--- a/halimpl/libnfc-nxp-PN81T_example_NCI2_0.conf
+++ b/halimpl/libnfc-nxp-PN81T_example_NCI2_0.conf
@@ -127,7 +127,7 @@
# DWP intf behavior config, SVDD Load activated by default if set to 0x31 A037
# SPI CL Sync enable A098
# EVT END OF Operation delay A0B2
-NXP_CORE_CONF_EXTN={20, 02, 31, 0C,
+NXP_CORE_CONF_EXTN={20, 02, 35, 0D,
A0, EC, 01, 01,
A0, ED, 01, 01,
A0, 5E, 01, 01,
@@ -139,7 +139,8 @@
A0, D8, 01, 02,
A0, D5, 01, 0A,
A0, 98, 01, 03,
- A0, B2, 01, 19
+ A0, B2, 01, 19,
+ A0, 91, 01, 01
}
###############################################################################
diff --git a/halimpl/utils/NfccPowerTracker.cpp b/halimpl/utils/NfccPowerTracker.cpp
new file mode 100644
index 0000000..99f2b8a
--- /dev/null
+++ b/halimpl/utils/NfccPowerTracker.cpp
@@ -0,0 +1,438 @@
+/******************************************************************************
+ *
+ * Copyright 2018 NXP
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+#define LOG_TAG "NfccPowerTracker"
+#include "NfccPowerTracker.h"
+#include "phNxpNciHal_ext.h"
+#include <assert.h>
+#include <fstream>
+#include <iostream>
+#include <log/log.h>
+#include <sstream>
+#include <stdio.h>
+#include <sys/file.h>
+#include <sys/time.h>
+using namespace std;
+
+extern bool nfc_debug_enabled;
+extern phNxpNciHal_Control_t nxpncihal_ctrl;
+static const uint64_t PWR_TRK_ERROR_MARGIN_IN_MILLISEC = 60000;
+static const std::string POWER_TRACKER_LOG_FILE =
+ "/data/vendor/nfc/nfc_power_state.txt";
+static const uint16_t TIMER_COUNT_MASK = 0x7FFF;
+
+NfccPowerTracker::NfccPowerTracker() {
+ mIsFirstPwrTrkNtfRecvd = false;
+ mLastPowerTrackAborted = false;
+ /*Default standby time*/
+ mStandbyTimePerDiscLoopInMillisec = 1000;
+}
+NfccPowerTracker::~NfccPowerTracker() {}
+
+/*******************************************************************************
+**
+** Function NfccPowerTracker::getInstance
+**
+** Description access class singleton
+**
+** Returns pointer to the singleton object
+**
+*******************************************************************************/
+NfccPowerTracker &NfccPowerTracker::getInstance() {
+ static NfccPowerTracker sPwrInstance;
+ return sPwrInstance;
+}
+/*******************************************************************************
+**
+** Function Initialize
+**
+** Description get all prerequisite information from NFCC needed for
+** Power tracker calculations.
+**
+** Returns void
+**
+*******************************************************************************/
+void NfccPowerTracker::Initialize() {
+ /*get total duration of discovery loop from NFCC using GET CONFIG command*/
+ uint8_t cmdGetConfigDiscLoopDuration[] = {0x20, 0x03, 0x02, 0x01, 0x00};
+ int status = phNxpNciHal_send_ext_cmd(sizeof(cmdGetConfigDiscLoopDuration),
+ cmdGetConfigDiscLoopDuration);
+ if (status != 0) {
+ ALOGD_IF(nfc_debug_enabled, "NfccPowerTracker::Initialize: failed");
+ return;
+ }
+ /*Check for valid get config response and update stanby time*/
+ if (nxpncihal_ctrl.p_rx_data[0] == 0x40 &&
+ nxpncihal_ctrl.p_rx_data[1] == 0x03 &&
+ nxpncihal_ctrl.p_rx_data[2] == 0x06 &&
+ nxpncihal_ctrl.p_rx_data[3] == 0x00 &&
+ nxpncihal_ctrl.p_rx_data[4] == 0x01 &&
+ nxpncihal_ctrl.p_rx_data[5] == 0x00 &&
+ nxpncihal_ctrl.p_rx_data[6] == 0x02) {
+ mStandbyTimePerDiscLoopInMillisec = (uint32_t)(
+ (nxpncihal_ctrl.p_rx_data[8] << 8) | nxpncihal_ctrl.p_rx_data[7]);
+ ALOGD_IF(nfc_debug_enabled, "mStandbyTimePerDiscLoopInMillisec value : %d",
+ mStandbyTimePerDiscLoopInMillisec);
+ }
+}
+
+/*******************************************************************************
+**
+** Function TimeDiff
+**
+** Description Computes time difference in milliseconds.
+**
+** Returns Time difference in milliseconds
+**
+*******************************************************************************/
+uint64_t NfccPowerTracker::TimeDiff(struct timespec start,
+ struct timespec end) {
+ uint64_t startTimeInMillisec =
+ start.tv_sec * 1000 + (start.tv_nsec / 1000000);
+ uint64_t endTimeInMillisec = end.tv_sec * 1000 + (end.tv_nsec / 1000000);
+
+ assert(startTimeInMillisec > endTimeInMillisec);
+ return (endTimeInMillisec - startTimeInMillisec);
+}
+
+/*******************************************************************************
+**
+** Function NfccPowerTracker::ProcessCmd
+**
+** Description Parse the commands going to NFCC,
+** get the time at which power relevant commands are sent
+** (ex:Screen state/OMAPI session)is sent and
+** log/cache the timestamp to file
+**
+** Returns void
+**
+*******************************************************************************/
+void NfccPowerTracker::ProcessCmd(uint8_t *cmd, uint16_t len) {
+ ALOGD_IF(nfc_debug_enabled,
+ "NfccPowerTracker::ProcessCmd: Enter,Recieved len :%d", len);
+ bool screenStateCommand;
+ if (cmd[0] == 0x20 && cmd[1] == 0x09) {
+ screenStateCommand = true;
+ } else {
+ screenStateCommand = false;
+ }
+
+ if (screenStateCommand && (cmd[3] == 0x00 || cmd[3] == 0x02)) {
+ /* Command for Screen State On-Locked or Unlocked */
+ clock_gettime(CLOCK_BOOTTIME, &mLastScreenOnTimeStamp);
+ mIsLastUpdateScreenOn = true;
+ } else if (screenStateCommand && (cmd[3] == 0x01 || cmd[3] == 0x03)) {
+ /* Command for Screen State OFF-locked or Unlocked */
+ clock_gettime(CLOCK_BOOTTIME, &mLastScreenOffTimeStamp);
+ mIsLastUpdateScreenOn = false;
+ } else if (cmd[0] == 0x20 && cmd[1] == 0x02 && cmd[2] == 0x05 &&
+ cmd[3] == 0x01 && cmd[4] == 0x00 && cmd[5] == 0x02) {
+ /* Command to update duration of discovery loop */
+ mStandbyTimePerDiscLoopInMillisec = (cmd[7] << 8 | cmd[6]);
+ ALOGD_IF(nfc_debug_enabled, "mStandbyTimePerDiscLoopInMillisec value : %d",
+ mStandbyTimePerDiscLoopInMillisec);
+ }
+}
+
+/*******************************************************************************
+**
+** Function NfccPowerTracker::ProcessNtf
+**
+** Description Parse the Notifications coming from NFCC,
+** get the time at which power relevant notifications are
+** received
+** (ex:RF ON-OFF/ACTIVATE-DEACTIVATE NTF/PROP_PWR_TRACKINFO)
+** calculate error in standby time by comparing the
+** expectated value from NFC HAL and received value from NFCC.
+** Cache relevant info (timestamps) to file
+**
+** Returns void
+**
+*******************************************************************************/
+void NfccPowerTracker::ProcessNtf(uint8_t *rsp, uint16_t rsp_len) {
+ ALOGD_IF(nfc_debug_enabled, "NfccPowerTracker::ProcessNtf: Enter");
+
+ /* Screen State Notification recieved */
+ if ((rsp[0] == 0x6F && rsp[1] == 0x05)) {
+ ProcessPowerTrackNtf(rsp, rsp_len);
+ } else if (rsp[0] == 0x61 && rsp[1] == 0x05) {
+ /*Activation notification received. Calculate the time NFCC is
+ active in Reader/P2P/CE duration */
+ clock_gettime(CLOCK_BOOTTIME, &mActiveTimeStart);
+ if (!mIsLastUpdateScreenOn) {
+ mActiveInfo.totalTransitions++;
+ }
+ } else if (rsp[0] == 0x61 && rsp[1] == 0x06) {
+ /* Deactivation notification received Calculate the time NFCC is
+ active in Reader/P2P/CE duration.Time between Activation and
+ Deacivation gives the active time*/
+ clock_gettime(CLOCK_BOOTTIME, &mActiveTimeEnd);
+ mActiveDurationFromLastScreenUpdate +=
+ TimeDiff(mActiveTimeStart, mActiveTimeEnd);
+ if (!mIsLastUpdateScreenOn) {
+ mStandbyInfo.totalTransitions++;
+ }
+ ALOGD_IF(nfc_debug_enabled, "mActiveDurationFromLastScreenUpdate: %llu",
+ (unsigned long long)mActiveDurationFromLastScreenUpdate);
+ }
+}
+
+/*******************************************************************************
+**
+** Function ProcessPowerTrackNtf
+**
+** Description Process Power Tracker notification and update timingInfo to
+** Log File.
+**
+** Returns void
+**
+*******************************************************************************/
+void NfccPowerTracker::ProcessPowerTrackNtf(uint8_t *rsp, uint16_t rsp_len) {
+ /* Enable Power Tracking computations after 1st Power tracker notification
+ * is received. */
+ if (!mIsFirstPwrTrkNtfRecvd) {
+ mIsFirstPwrTrkNtfRecvd = true;
+ ifstream ifile(POWER_TRACKER_LOG_FILE.c_str());
+ if ((bool)ifile == true) {
+ mLastPowerTrackAborted = true;
+ }
+ return;
+ }
+
+ /*Duration between screen state change is taken as reference for calculating
+ active and standby time*/
+ uint64_t totalDuration = 0;
+ totalDuration =
+ mIsLastUpdateScreenOn
+ ? TimeDiff(mLastScreenOffTimeStamp, mLastScreenOnTimeStamp)
+ : TimeDiff(mLastScreenOnTimeStamp, mLastScreenOffTimeStamp);
+ if (totalDuration == 0)
+ return;
+
+ /*Calculate Active and Standby time based on the pollCount provided in the
+ Power tracker Notification from NFCC*/
+ uint16_t sPollCount = (TIMER_COUNT_MASK & ((rsp[5] << 8) | rsp[4]));
+ ALOGD_IF(nfc_debug_enabled,
+ "Poll/Timer count recived from FW is %d and rsp_len :%d", sPollCount,
+ rsp_len);
+ uint64_t standbyTime = 0, activeTime = 0;
+ if (mIsLastUpdateScreenOn) {
+ activeTime = sPollCount * ACTIVE_TIME_PER_TIMER_COUNT_IN_MILLISEC;
+ /*Check for errors in count provided by NFCC*/
+ uint64_t error = (activeTime > mActiveDurationFromLastScreenUpdate)
+ ? (activeTime - mActiveDurationFromLastScreenUpdate)
+ : (mActiveDurationFromLastScreenUpdate - activeTime);
+ if (error > PWR_TRK_ERROR_MARGIN_IN_MILLISEC) {
+ ALOGD_IF(nfc_debug_enabled,
+ "Active Time Error observed with value is %llu",
+ (unsigned long long)error);
+ mErrorInStandbyInfo.residencyInMsecSinceBoot += error;
+ }
+ standbyTime = (totalDuration > activeTime) ? (totalDuration - activeTime)
+ : (activeTime - totalDuration);
+ if (rsp[3]) {
+ /*If notification trigger is counter overflow, update the screen on
+ timestamp as there is no screen state change*/
+ clock_gettime(CLOCK_BOOTTIME, &mLastScreenOnTimeStamp);
+ }
+ mActiveInfo.totalTransitions++;
+ } else {
+ standbyTime = (sPollCount * mStandbyTimePerDiscLoopInMillisec);
+ activeTime = totalDuration > standbyTime ? (totalDuration - standbyTime)
+ : (standbyTime - totalDuration);
+ if (rsp[3]) {
+ /*If notification trigger is counter overflow, update the screen off
+ timestamp as there is no screen state change*/
+ clock_gettime(CLOCK_BOOTTIME, &mLastScreenOffTimeStamp);
+ }
+ /*Total transitions in screen on -> Screen Off window is same as poll count
+ provided by NFCC, as, there is transition in each discovery loop*/
+ mActiveInfo.totalTransitions += sPollCount;
+ /*1 additional transition for screen state update*/
+ mStandbyInfo.totalTransitions += (sPollCount + 1);
+ }
+
+ ALOGD_IF(nfc_debug_enabled,
+ "activeTime: %llu, standbyTime: %llu, totalDuration :%llu",
+ (unsigned long long)activeTime, (unsigned long long)standbyTime,
+ (unsigned long long)totalDuration);
+ if (mLastPowerTrackAborted) {
+ ALOGD_IF(nfc_debug_enabled,
+ "Last Hal service aborted,so retrive the power info data and "
+ "continue\n");
+ /*Read the file content and store in mActiveInfo.residencyInMsecSinceBoot
+ and mStandbyInfo.residencyInMsecSinceBoot*/
+ if (ReadPowerStateLog()) {
+ mLastPowerTrackAborted = false;
+ }
+ }
+ mStandbyInfo.residencyInMsecSinceBoot += standbyTime;
+ mActiveInfo.residencyInMsecSinceBoot += activeTime;
+ UpdatePowerStateLog(mStandbyInfo, mActiveInfo);
+ mActiveDurationFromLastScreenUpdate = 0;
+}
+/*******************************************************************************
+**
+** Function NfccPowerTracker::UpdatePowerStateLog
+**
+** Description update the powerstate related information in log file
+**
+** Returns void
+**
+*******************************************************************************/
+void NfccPowerTracker::UpdatePowerStateLog(NfccPowerStateInfo_t mStandbyInfo,
+ NfccPowerStateInfo_t mActiveInfo) {
+ FILE *fp;
+ const string PWR_TRK_LOG_FILE_VERSION = "1.0";
+ /*Write the Active and standby timestamp into the file*/
+ fp = fopen(POWER_TRACKER_LOG_FILE.c_str(), "w");
+ if (fp == NULL) {
+ ALOGD_IF(nfc_debug_enabled, "Failed to Open Pwr Tracker Info File\n");
+ return;
+ }
+ ostringstream PwrTrackerInfo;
+ PwrTrackerInfo << "Version: " << PWR_TRK_LOG_FILE_VERSION.c_str() << endl;
+ PwrTrackerInfo << "NFC {" << endl;
+ PwrTrackerInfo << " { " << STR_ACTIVE
+ << std::to_string(mActiveInfo.residencyInMsecSinceBoot) << " }"
+ << endl;
+ PwrTrackerInfo << " { " << STR_STANDBY
+ << std::to_string(mStandbyInfo.residencyInMsecSinceBoot)
+ << " }" << endl;
+ PwrTrackerInfo << "}";
+ ALOGD_IF(nfc_debug_enabled,
+ "mActiveInfo.residencyInMsecSinceBoot: %llu, "
+ "mActiveInfo.totalTransitions: %llu,"
+ "mStandbyInfo.residencyInMsecSinceBoot "
+ ":%llu,mStandbyInfo.totalTransitions: %llu"
+ "mErrorInStandbyInfo.residencyInMsecSinceBoot: %llu",
+ (unsigned long long)mActiveInfo.residencyInMsecSinceBoot,
+ (unsigned long long)mActiveInfo.totalTransitions,
+ (unsigned long long)mStandbyInfo.residencyInMsecSinceBoot,
+ (unsigned long long)mStandbyInfo.totalTransitions,
+ (unsigned long long)mErrorInStandbyInfo.residencyInMsecSinceBoot);
+ string PwrInfo = PwrTrackerInfo.str();
+ if (!TryLockFile(fp)) {
+ ALOGD_IF(nfc_debug_enabled,
+ "Failed to Lock PwrTracker File.Skipping update\n");
+ fclose(fp);
+ return;
+ }
+ fwrite(PwrInfo.c_str(), sizeof(char), PwrInfo.length(), fp);
+ fflush(fp);
+ UnlockFile(fp);
+ fclose(fp);
+}
+/*******************************************************************************
+ **
+ ** Function ReadPowerStateLog
+ **
+ ** Description Retrieve powerstate related information from log file.
+ **
+ ** Returns true if read successful, false otherwise.
+ **
+ *******************************************************************************/
+bool NfccPowerTracker::ReadPowerStateLog() {
+ ifstream pwrStateFileStream;
+ string itemName;
+ ALOGD_IF(nfc_debug_enabled, "NfccPowerTracker::ReadPowerStateLog: Enter \n");
+ pwrStateFileStream.open(POWER_TRACKER_LOG_FILE.c_str());
+ if (pwrStateFileStream.fail()) {
+ ALOGE("Error: %s", strerror(errno));
+ return false;
+ }
+
+ /*Check for required string(time in millisec) in the log file and convert it
+ to integer*/
+ while (pwrStateFileStream >> itemName) {
+ if (STR_ACTIVE.compare(itemName) == 0) {
+ pwrStateFileStream >> itemName;
+ mActiveInfo.residencyInMsecSinceBoot = stoull(itemName.c_str(), nullptr);
+ } else if (STR_STANDBY.compare(itemName) == 0) {
+ pwrStateFileStream >> itemName;
+ mStandbyInfo.residencyInMsecSinceBoot = stoull(itemName.c_str(), nullptr);
+ }
+ }
+
+ ALOGD_IF(nfc_debug_enabled,
+ "Value retrieved from Powertracker file is"
+ "activeTime: %llu and standbyTime: %llu\n",
+ (unsigned long long)mActiveInfo.residencyInMsecSinceBoot,
+ (unsigned long long)mStandbyInfo.residencyInMsecSinceBoot);
+ pwrStateFileStream.close();
+ return true;
+}
+/*******************************************************************************
+**
+** Function Pause
+**
+** Description Pause Power state Information Tracking,Tracking will resume
+** once next power tracker notification is recieved as part of
+** ProcessNtf.
+**
+** Returns void
+**
+*******************************************************************************/
+void NfccPowerTracker::Pause() { mIsFirstPwrTrkNtfRecvd = false; }
+
+/*******************************************************************************
+**
+** Function Reset
+**
+** Description Stop power track information processing and delete
+** power tracker log file.
+**
+** Returns void
+**
+*******************************************************************************/
+void NfccPowerTracker::Reset() {
+ ALOGD_IF(nfc_debug_enabled, "NfccPowerTracker::Reset enter");
+ if (remove(POWER_TRACKER_LOG_FILE.c_str()) != 0) {
+ ALOGD_IF(nfc_debug_enabled, "Error deleting Power tracker file");
+ }
+}
+/*******************************************************************************
+**
+** Function TryLockFile
+**
+** Description Lock PowerTracker log file. Any application trying to read
+** from PowerTracker log file shall acquire lock before reading
+** to avoid inconsistent data.
+**
+** Returns true if locking was successful
+** false if there was a failure to lock PowerTracker log file.
+*******************************************************************************/
+bool NfccPowerTracker::TryLockFile(FILE *fp) {
+ uint8_t retryCount = 5;
+ do {
+ if (!flock(fileno(fp), LOCK_EX | LOCK_NB))
+ return true;
+ usleep(10000); /*10 millisec*/
+ } while (retryCount--);
+
+ return false;
+}
+/*******************************************************************************
+**
+** Function UnlockFile
+**
+** Description Unlock previously locked PowerTracker log file.
+**
+** Returns void
+**
+*******************************************************************************/
+void NfccPowerTracker::UnlockFile(FILE *fp) { flock(fileno(fp), LOCK_UN); }
diff --git a/halimpl/utils/NfccPowerTracker.h b/halimpl/utils/NfccPowerTracker.h
new file mode 100644
index 0000000..3b3e8c0
--- /dev/null
+++ b/halimpl/utils/NfccPowerTracker.h
@@ -0,0 +1,195 @@
+/******************************************************************************
+ *
+ * Copyright 2018 NXP
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ ******************************************************************************/
+#pragma once
+
+#include <string>
+#include <time.h>
+#include <vector>
+
+/*Time spent in Active mode per count provided by NFCC*/
+static const uint32_t ACTIVE_TIME_PER_TIMER_COUNT_IN_MILLISEC = 20;
+/*Types of Power states supported by NFCC */
+typedef struct NfccPowerStateInfo {
+ /* state name: Active/Standby */
+ std::string name;
+ /* Time spent in msec at this power state since boot */
+ uint64_t residencyInMsecSinceBoot;
+ /* Total number of times Nfcc entered this state */
+ uint64_t totalTransitions;
+} NfccPowerStateInfo_t;
+
+/*Class to track the time spent in Standby mode by NFCC*/
+class NfccPowerTracker {
+public:
+ static NfccPowerTracker &getInstance();
+
+ /*******************************************************************************
+ **
+ ** Function Initialize
+ **
+ ** Description get all prerequisite information from NFCC needed for
+ ** Power tracker calculations.
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+ void Initialize();
+
+ /*******************************************************************************
+ **
+ ** Function ProcessCmd
+ **
+ ** Description Parse the commands going to NFCC,
+ ** get the time at which power relevant commands are sent
+ ** (ex:Screen state/OMAPI session)is sent and
+ ** log/cache the timestamp to file.
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+ void ProcessCmd(uint8_t *, uint16_t len);
+
+ /*******************************************************************************
+ **
+ ** Function ProcessNtf
+ **
+ ** Description Parse the Notifications coming from NFCC,
+ ** get the time at which power relevant notifications are
+ ** received (ex:RF ON-OFF/ACTIVATE-DEACTIVATE NTF/
+ ** PROP_PWR_TRACKINFO). Calculate error in standby time by
+ ** comparing the expectated value from NFC HAL and received
+ ** value from NFCC. Update power state duration info
+ ** to file.
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+ void ProcessNtf(uint8_t *cmd, uint16_t len);
+
+ /*******************************************************************************
+ **
+ ** Function Pause
+ **
+ ** Description Pause Power state Information Tracking,Tracking will
+ ** resume once next power tracker notification is recieved as
+ ** part of ProcessNtf.
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+ void Pause();
+
+ /*******************************************************************************
+ **
+ ** Function Reset
+ **
+ ** Description Stop power tracker information processing and delete
+ ** power track log file.
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+ void Reset();
+
+private:
+ NfccPowerTracker();
+ ~NfccPowerTracker();
+
+ /*******************************************************************************
+ **
+ ** Function UpdatePowerStateLog
+ **
+ ** Description update the powerstate related information in log file
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+ void UpdatePowerStateLog(NfccPowerStateInfo_t standbyTime,
+ NfccPowerStateInfo_t activeTime);
+
+ /*******************************************************************************
+ **
+ ** Function ReadPowerStateLog
+ **
+ ** Description Retrieve powerstate related information from log file.
+ **
+ ** Returns true if read successful, false otherwise.
+ **
+ *******************************************************************************/
+ bool ReadPowerStateLog();
+
+ /*******************************************************************************
+ **
+ ** Function ProcessPowerTrackNtf
+ **
+ ** Description Process Power Tracker notification.
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+ void ProcessPowerTrackNtf(uint8_t *rsp, uint16_t rsp_len);
+
+ /*******************************************************************************
+ **
+ ** Function TimeDiff
+ **
+ ** Description Computes time difference in milliseconds.
+ **
+ ** Returns Time difference in milliseconds
+ **
+ *******************************************************************************/
+ uint64_t TimeDiff(timespec start, timespec end);
+ /*******************************************************************************
+ **
+ ** Function TryLockFile
+ **
+ ** Description Lock PowerTracker log file. Any application trying to read
+ ** from PowerTracker log file shall acquire lock before
+ ** reading to avoid inconsistent data.
+ **
+ ** Returns true if locking was successful
+ ** false if there was a failure to lock file.
+ *******************************************************************************/
+ bool TryLockFile(FILE *fp);
+ /*******************************************************************************
+ **
+ ** Function UnlockFile
+ **
+ ** Description Unlock previously locked PowerTracker log file.
+ **
+ ** Returns void
+ *******************************************************************************/
+ void UnlockFile(FILE *fp);
+ struct timespec mLastScreenOffTimeStamp = {0, 0},
+ mLastScreenOnTimeStamp = {0, 0};
+ /*Used to calculate time NFCC is active during Card emulation/P2P/Reader
+ * modes*/
+ struct timespec mActiveTimeStart = {0, 0}, mActiveTimeEnd = {0, 0};
+
+ bool mIsLastUpdateScreenOn;
+ bool mIsFirstPwrTrkNtfRecvd;
+
+ uint64_t mActiveDurationFromLastScreenUpdate = 0;
+ NfccPowerStateInfo_t mActiveInfo, mStandbyInfo, mErrorInStandbyInfo;
+
+ /*Last powertracker processing aborted due to NFC HAL Service abort*/
+ bool mLastPowerTrackAborted = false;
+ /* Time spent in standby mode in one discovery loop containing poll */
+ uint32_t mStandbyTimePerDiscLoopInMillisec;
+ const std::string STR_ACTIVE = "Active: ", STR_STANDBY = "StandBy: ";
+};