stats: Pull power stats atoms from PowerStats service
Native layer is no longer needed to pull these atoms, so cleaning that
up as well.
Bug: 168832285
Test: cmd stats pull-source 10038
Test: cmd stats pull-source 10005
Change-Id: Ic20c9cc8e29b4e02161f3741b4422f520e1bb063
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsService.java b/services/core/java/com/android/server/powerstats/PowerStatsService.java
index 5bd907f..5fe5db6 100644
--- a/services/core/java/com/android/server/powerstats/PowerStatsService.java
+++ b/services/core/java/com/android/server/powerstats/PowerStatsService.java
@@ -69,6 +69,8 @@
private BatteryTrigger mBatteryTrigger;
@Nullable
private TimerTrigger mTimerTrigger;
+ @Nullable
+ private StatsPullAtomCallbackImpl mPullAtomCallback;
@VisibleForTesting
static class Injector {
@@ -119,6 +121,11 @@
TimerTrigger createTimerTrigger(Context context, PowerStatsLogger powerStatsLogger) {
return new TimerTrigger(context, powerStatsLogger, true /* trigger enabled */);
}
+
+ StatsPullAtomCallbackImpl createStatsPullerImpl(Context context,
+ IPowerStatsHALWrapper powerStatsHALWrapper) {
+ return new StatsPullAtomCallbackImpl(context, powerStatsHALWrapper);
+ }
}
private final class BinderService extends Binder {
@@ -156,8 +163,10 @@
@Override
public void onBootPhase(int phase) {
- if (phase == SystemService.PHASE_BOOT_COMPLETED) {
- onSystemServiceReady();
+ if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
+ onSystemServicesReady();
+ } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
+ onBootCompleted();
}
}
@@ -170,7 +179,18 @@
publishBinderService(Context.POWER_STATS_SERVICE, new BinderService());
}
- private void onSystemServiceReady() {
+ private void onSystemServicesReady() {
+ if (getPowerStatsHal().isInitialized()) {
+ if (DEBUG) Slog.d(TAG, "Starting PowerStatsService statsd pullers");
+
+ // Only start statsd pullers if initialization is successful.
+ mPullAtomCallback = mInjector.createStatsPullerImpl(mContext, getPowerStatsHal());
+ } else {
+ Slog.e(TAG, "Failed to start PowerStatsService statsd pullers");
+ }
+ }
+
+ private void onBootCompleted() {
if (getPowerStatsHal().isInitialized()) {
if (DEBUG) Slog.d(TAG, "Starting PowerStatsService loggers");
diff --git a/services/core/java/com/android/server/powerstats/StatsPullAtomCallbackImpl.java b/services/core/java/com/android/server/powerstats/StatsPullAtomCallbackImpl.java
new file mode 100644
index 0000000..f8b9601
--- /dev/null
+++ b/services/core/java/com/android/server/powerstats/StatsPullAtomCallbackImpl.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package com.android.server.powerstats;
+
+import android.app.StatsManager;
+import android.content.Context;
+import android.hardware.power.stats.Channel;
+import android.hardware.power.stats.EnergyMeasurement;
+import android.hardware.power.stats.PowerEntity;
+import android.hardware.power.stats.State;
+import android.hardware.power.stats.StateResidency;
+import android.hardware.power.stats.StateResidencyResult;
+import android.util.StatsEvent;
+
+import com.android.internal.util.ConcurrentUtils;
+import com.android.internal.util.FrameworkStatsLog;
+import com.android.server.powerstats.PowerStatsHALWrapper.IPowerStatsHALWrapper;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * StatsPullAtomCallbackImpl is responsible implementing the stats pullers for
+ * SUBSYSTEM_SLEEP_STATE and ON_DEVICE_POWER_MEASUREMENT statsd atoms.
+ */
+public class StatsPullAtomCallbackImpl implements StatsManager.StatsPullAtomCallback {
+ private Context mContext;
+ private IPowerStatsHALWrapper mPowerStatsHALWrapper;
+ private Map<Integer, Channel> mChannels = new HashMap();
+ private Map<Integer, String> mEntityNames = new HashMap();
+ private Map<Integer, Map<Integer, String>> mStateNames = new HashMap();;
+
+ @Override
+ public int onPullAtom(int atomTag, List<StatsEvent> data) {
+ switch (atomTag) {
+ case FrameworkStatsLog.SUBSYSTEM_SLEEP_STATE:
+ return pullSubsystemSleepState(atomTag, data);
+ case FrameworkStatsLog.ON_DEVICE_POWER_MEASUREMENT:
+ return pullOnDevicePowerMeasurement(atomTag, data);
+ default:
+ throw new UnsupportedOperationException("Unknown tagId=" + atomTag);
+ }
+ }
+
+ private void initPullOnDevicePowerMeasurement() {
+ Channel[] channels = mPowerStatsHALWrapper.getEnergyMeterInfo();
+ if (channels == null) {
+ return;
+ }
+
+ for (int i = 0; i < channels.length; i++) {
+ final Channel channel = channels[i];
+ mChannels.put(channel.id, channel);
+ }
+ }
+
+ private int pullOnDevicePowerMeasurement(int atomTag, List<StatsEvent> events) {
+ EnergyMeasurement[] energyMeasurements = mPowerStatsHALWrapper.readEnergyMeters(new int[0]);
+ if (energyMeasurements == null) {
+ return StatsManager.PULL_SKIP;
+ }
+
+ for (int i = 0; i < energyMeasurements.length; i++) {
+ // Only report energy measurements that have been accumulated since boot
+ final EnergyMeasurement energyMeasurement = energyMeasurements[i];
+ if (energyMeasurement.durationMs == energyMeasurement.timestampMs) {
+ events.add(FrameworkStatsLog.buildStatsEvent(
+ atomTag,
+ mChannels.get(energyMeasurement.id).subsystem,
+ mChannels.get(energyMeasurement.id).name,
+ energyMeasurement.durationMs,
+ energyMeasurement.energyUWs));
+ }
+ }
+
+ return StatsManager.PULL_SUCCESS;
+ }
+
+ private void initSubsystemSleepState() {
+ PowerEntity[] entities = mPowerStatsHALWrapper.getPowerEntityInfo();
+ if (entities == null) {
+ return;
+ }
+
+ for (int i = 0; i < entities.length; i++) {
+ final PowerEntity entity = entities[i];
+ Map<Integer, String> states = new HashMap();
+ for (int j = 0; j < entity.states.length; j++) {
+ final State state = entity.states[j];
+ states.put(state.id, state.name);
+ }
+
+ mEntityNames.put(entity.id, entity.name);
+ mStateNames.put(entity.id, states);
+ }
+ }
+
+ private int pullSubsystemSleepState(int atomTag, List<StatsEvent> events) {
+ StateResidencyResult[] results = mPowerStatsHALWrapper.getStateResidency(new int[0]);
+ if (results == null) {
+ return StatsManager.PULL_SKIP;
+ }
+ for (int i = 0; i < results.length; i++) {
+ final StateResidencyResult result = results[i];
+ for (int j = 0; j < result.stateResidencyData.length; j++) {
+ final StateResidency stateResidency = result.stateResidencyData[j];
+ events.add(FrameworkStatsLog.buildStatsEvent(
+ atomTag,
+ mEntityNames.get(result.id),
+ mStateNames.get(result.id).get(stateResidency.id),
+ stateResidency.totalStateEntryCount,
+ stateResidency.totalTimeInStateMs));
+ }
+ }
+
+ return StatsManager.PULL_SUCCESS;
+ }
+
+ public StatsPullAtomCallbackImpl(Context context, IPowerStatsHALWrapper powerStatsHALWrapper) {
+ mContext = context;
+ mPowerStatsHALWrapper = powerStatsHALWrapper;
+ initPullOnDevicePowerMeasurement();
+ initSubsystemSleepState();
+
+ StatsManager manager = mContext.getSystemService(StatsManager.class);
+ manager.setPullAtomCallback(
+ FrameworkStatsLog.SUBSYSTEM_SLEEP_STATE,
+ null, // use default PullAtomMetadata values
+ ConcurrentUtils.DIRECT_EXECUTOR,
+ this);
+ manager.setPullAtomCallback(
+ FrameworkStatsLog.ON_DEVICE_POWER_MEASUREMENT,
+ null, // use default PullAtomMetadata values
+ ConcurrentUtils.DIRECT_EXECUTOR,
+ this);
+ }
+}
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 0cc2a6c..263776c 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -407,8 +407,6 @@
mContext = context;
}
- private native void nativeInit();
-
/**
* Use of this StatsPullAtomCallbackImpl means we avoid one class per tagId, which we would
* get if we used lambdas.
@@ -681,7 +679,6 @@
super.onBootPhase(phase);
if (phase == PHASE_SYSTEM_SERVICES_READY) {
BackgroundThread.getHandler().post(() -> {
- nativeInit();
initializePullersState();
registerPullers();
registerEventListeners();
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 345b246..cc7e00a 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -25,8 +25,6 @@
"gnss/GnssMeasurement.cpp",
"gnss/GnssMeasurementCallback.cpp",
"gnss/Utils.cpp",
- "stats/PowerStatsPuller.cpp",
- "stats/SubsystemSleepStatePuller.cpp",
"com_android_server_adb_AdbDebuggingManager.cpp",
"com_android_server_am_BatteryStatsService.cpp",
"com_android_server_biometrics_SurfaceToNativeHandleConverter.cpp",
@@ -45,7 +43,6 @@
"com_android_server_SerialService.cpp",
"com_android_server_soundtrigger_middleware_AudioSessionProviderImpl.cpp",
"com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker.cpp",
- "com_android_server_stats_pull_StatsPullAtomService.cpp",
"com_android_server_storage_AppFuseBridge.cpp",
"com_android_server_SystemServer.cpp",
"com_android_server_tv_TvUinputBridge.cpp",
@@ -152,6 +149,7 @@
"android.hardware.power@1.1",
"android.hardware.power-cpp",
"android.hardware.power.stats@1.0",
+ "android.hardware.power.stats-ndk_platform",
"android.hardware.thermal@1.0",
"android.hardware.tv.input@1.0",
"android.hardware.vibrator-unstable-cpp",
diff --git a/services/core/jni/com_android_server_stats_pull_StatsPullAtomService.cpp b/services/core/jni/com_android_server_stats_pull_StatsPullAtomService.cpp
deleted file mode 100644
index b1fbe64..0000000
--- a/services/core/jni/com_android_server_stats_pull_StatsPullAtomService.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * 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 "StatsPullAtomService"
-
-#include <jni.h>
-#include <log/log.h>
-#include <nativehelper/JNIHelp.h>
-#include <stats_event.h>
-#include <stats_pull_atom_callback.h>
-#include <statslog.h>
-
-#include "stats/PowerStatsPuller.h"
-#include "stats/SubsystemSleepStatePuller.h"
-
-namespace android {
-
-static server::stats::PowerStatsPuller gPowerStatsPuller;
-static server::stats::SubsystemSleepStatePuller gSubsystemSleepStatePuller;
-
-static AStatsManager_PullAtomCallbackReturn onDevicePowerMeasurementCallback(int32_t atom_tag,
- AStatsEventList* data,
- void* cookie) {
- return gPowerStatsPuller.Pull(atom_tag, data);
-}
-
-static AStatsManager_PullAtomCallbackReturn subsystemSleepStateCallback(int32_t atom_tag,
- AStatsEventList* data,
- void* cookie) {
- return gSubsystemSleepStatePuller.Pull(atom_tag, data);
-}
-
-static void nativeInit(JNIEnv* env, jobject javaObject) {
- // on device power measurement
- gPowerStatsPuller = server::stats::PowerStatsPuller();
- AStatsManager_setPullAtomCallback(android::util::ON_DEVICE_POWER_MEASUREMENT,
- /* metadata= */ nullptr, onDevicePowerMeasurementCallback,
- /* cookie= */ nullptr);
-
- // subsystem sleep state
- gSubsystemSleepStatePuller = server::stats::SubsystemSleepStatePuller();
- AStatsManager_setPullAtomCallback(android::util::SUBSYSTEM_SLEEP_STATE,
- /* metadata= */ nullptr, subsystemSleepStateCallback,
- /* cookie= */ nullptr);
-}
-
-static const JNINativeMethod sMethods[] = {{"nativeInit", "()V", (void*)nativeInit}};
-
-int register_android_server_stats_pull_StatsPullAtomService(JNIEnv* env) {
- int res = jniRegisterNativeMethods(env, "com/android/server/stats/pull/StatsPullAtomService",
- sMethods, NELEM(sMethods));
- if (res < 0) {
- ALOGE("failed to register native methods");
- }
- return res;
-}
-
-} // namespace android
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 1893321..c5394f3 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -59,7 +59,6 @@
int register_com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker(
JNIEnv* env);
int register_android_server_com_android_server_pm_PackageManagerShellCommandDataLoader(JNIEnv* env);
-int register_android_server_stats_pull_StatsPullAtomService(JNIEnv* env);
int register_android_server_AdbDebuggingManager(JNIEnv* env);
int register_android_server_FaceService(JNIEnv* env);
int register_android_server_GpuService(JNIEnv* env);
@@ -115,7 +114,6 @@
register_com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker(
env);
register_android_server_com_android_server_pm_PackageManagerShellCommandDataLoader(env);
- register_android_server_stats_pull_StatsPullAtomService(env);
register_android_server_AdbDebuggingManager(env);
register_android_server_FaceService(env);
register_android_server_GpuService(env);
diff --git a/services/core/jni/stats/OWNERS b/services/core/jni/stats/OWNERS
deleted file mode 100644
index a61babf..0000000
--- a/services/core/jni/stats/OWNERS
+++ /dev/null
@@ -1,9 +0,0 @@
-jeffreyhuang@google.com
-joeo@google.com
-jtnguyen@google.com
-muhammadq@google.com
-ruchirr@google.com
-singhtejinder@google.com
-tsaichristine@google.com
-yaochen@google.com
-yro@google.com
diff --git a/services/core/jni/stats/PowerStatsPuller.cpp b/services/core/jni/stats/PowerStatsPuller.cpp
deleted file mode 100644
index 7f788c2..0000000
--- a/services/core/jni/stats/PowerStatsPuller.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * 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 DEBUG false // STOPSHIP if true
-#define LOG_TAG "PowerStatsPuller"
-
-#include <android/hardware/power/stats/1.0/IPowerStats.h>
-#include <log/log.h>
-#include <statslog.h>
-
-#include <vector>
-
-#include "PowerStatsPuller.h"
-
-using android::hardware::hidl_vec;
-using android::hardware::Return;
-using android::hardware::Void;
-using android::hardware::power::stats::V1_0::EnergyData;
-using android::hardware::power::stats::V1_0::IPowerStats;
-using android::hardware::power::stats::V1_0::RailInfo;
-using android::hardware::power::stats::V1_0::Status;
-
-namespace android {
-namespace server {
-namespace stats {
-
-static sp<android::hardware::power::stats::V1_0::IPowerStats> gPowerStatsHal = nullptr;
-static std::mutex gPowerStatsHalMutex;
-static bool gPowerStatsExist = true; // Initialized to ensure making a first attempt.
-static std::vector<RailInfo> gRailInfo;
-
-struct PowerStatsPullerDeathRecipient : virtual public hardware::hidl_death_recipient {
- virtual void serviceDied(uint64_t cookie,
- const wp<android::hidl::base::V1_0::IBase>& who) override {
- // The HAL just died. Reset all handles to HAL services.
- std::lock_guard<std::mutex> lock(gPowerStatsHalMutex);
- gPowerStatsHal = nullptr;
- }
-};
-
-static sp<PowerStatsPullerDeathRecipient> gDeathRecipient = new PowerStatsPullerDeathRecipient();
-
-static bool getPowerStatsHalLocked() {
- if (gPowerStatsHal == nullptr && gPowerStatsExist) {
- gPowerStatsHal = android::hardware::power::stats::V1_0::IPowerStats::getService();
- if (gPowerStatsHal == nullptr) {
- ALOGW("Couldn't load power.stats HAL service");
- gPowerStatsExist = false;
- } else {
- // Link death recipient to power.stats service handle
- hardware::Return<bool> linked = gPowerStatsHal->linkToDeath(gDeathRecipient, 0);
- if (!linked.isOk()) {
- ALOGE("Transaction error in linking to power.stats HAL death: %s",
- linked.description().c_str());
- gPowerStatsHal = nullptr;
- return false;
- } else if (!linked) {
- ALOGW("Unable to link to power.stats HAL death notifications");
- // We should still continue even though linking failed
- }
- }
- }
- return gPowerStatsHal != nullptr;
-}
-
-PowerStatsPuller::PowerStatsPuller() {}
-
-AStatsManager_PullAtomCallbackReturn PowerStatsPuller::Pull(int32_t atomTag,
- AStatsEventList* data) {
- std::lock_guard<std::mutex> lock(gPowerStatsHalMutex);
-
- if (!getPowerStatsHalLocked()) {
- return AStatsManager_PULL_SKIP;
- }
-
- // Pull getRailInfo if necessary
- if (gRailInfo.empty()) {
- bool resultSuccess = true;
- Return<void> ret = gPowerStatsHal->getRailInfo(
- [&resultSuccess](const hidl_vec<RailInfo>& list, Status status) {
- resultSuccess = (status == Status::SUCCESS || status == Status::NOT_SUPPORTED);
- if (status != Status::SUCCESS) return;
- gRailInfo.reserve(list.size());
- for (size_t i = 0; i < list.size(); ++i) {
- gRailInfo.push_back(list[i]);
- }
- });
- if (!resultSuccess || !ret.isOk()) {
- ALOGE("power.stats getRailInfo() failed. Description: %s", ret.description().c_str());
- gPowerStatsHal = nullptr;
- return AStatsManager_PULL_SKIP;
- }
- // If SUCCESS but empty, or if NOT_SUPPORTED, then never try again.
- if (gRailInfo.empty()) {
- ALOGE("power.stats has no rail information");
- gPowerStatsExist = false; // No rail info, so never try again.
- gPowerStatsHal = nullptr;
- return AStatsManager_PULL_SKIP;
- }
- }
-
- // Pull getEnergyData and write the data out
- const hidl_vec<uint32_t> desiredRailIndices; // Empty vector indicates we want all.
- bool resultSuccess = true;
- Return<void> ret =
- gPowerStatsHal
- ->getEnergyData(desiredRailIndices,
- [&data, &resultSuccess](hidl_vec<EnergyData> energyDataList,
- Status status) {
- resultSuccess = (status == Status::SUCCESS);
- if (!resultSuccess) return;
-
- for (size_t i = 0; i < energyDataList.size(); i++) {
- const EnergyData& energyData = energyDataList[i];
-
- if (energyData.index >= gRailInfo.size()) {
- ALOGE("power.stats getEnergyData() returned an "
- "invalid rail index %u.",
- energyData.index);
- resultSuccess = false;
- return;
- }
- const RailInfo& rail = gRailInfo[energyData.index];
-
- android::util::addAStatsEvent(
- data,
- android::util::ON_DEVICE_POWER_MEASUREMENT,
- rail.subsysName.c_str(), rail.railName.c_str(),
- energyData.timestamp, energyData.energy);
-
- ALOGV("power.stat: %s.%s: %llu, %llu",
- rail.subsysName.c_str(), rail.railName.c_str(),
- (unsigned long long)energyData.timestamp,
- (unsigned long long)energyData.energy);
- }
- });
- if (!resultSuccess || !ret.isOk()) {
- ALOGE("power.stats getEnergyData() failed. Description: %s", ret.description().c_str());
- gPowerStatsHal = nullptr;
- return AStatsManager_PULL_SKIP;
- }
- return AStatsManager_PULL_SUCCESS;
-}
-
-} // namespace stats
-} // namespace server
-} // namespace android
diff --git a/services/core/jni/stats/PowerStatsPuller.h b/services/core/jni/stats/PowerStatsPuller.h
deleted file mode 100644
index db07d60..0000000
--- a/services/core/jni/stats/PowerStatsPuller.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * 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 <stats_event.h>
-#include <stats_pull_atom_callback.h>
-
-namespace android {
-namespace server {
-namespace stats {
-
-/**
- * Reads hal for power.stats
- */
-class PowerStatsPuller {
-public:
- PowerStatsPuller();
- AStatsManager_PullAtomCallbackReturn Pull(int32_t atomTag, AStatsEventList* data);
-};
-
-} // namespace stats
-} // namespace server
-} // namespace android
diff --git a/services/core/jni/stats/SubsystemSleepStatePuller.cpp b/services/core/jni/stats/SubsystemSleepStatePuller.cpp
deleted file mode 100644
index 1ba98ef..0000000
--- a/services/core/jni/stats/SubsystemSleepStatePuller.cpp
+++ /dev/null
@@ -1,357 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * 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 DEBUG false // STOPSHIP if true
-#define LOG_TAG "SubsystemSleepStatePuller"
-
-#include <log/log.h>
-#include <statslog.h>
-
-#include <android/hardware/power/1.0/IPower.h>
-#include <android/hardware/power/1.1/IPower.h>
-#include <android/hardware/power/stats/1.0/IPowerStats.h>
-
-#include <fcntl.h>
-#include <hardware/power.h>
-#include <hardware_legacy/power.h>
-#include <inttypes.h>
-#include <semaphore.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <unordered_map>
-#include "SubsystemSleepStatePuller.h"
-
-using android::hardware::hidl_vec;
-using android::hardware::power::V1_0::IPower;
-using android::hardware::power::V1_0::PowerStatePlatformSleepState;
-using android::hardware::power::V1_0::PowerStateVoter;
-using android::hardware::power::V1_1::PowerStateSubsystem;
-using android::hardware::power::V1_1::PowerStateSubsystemSleepState;
-using android::hardware::power::stats::V1_0::PowerEntityInfo;
-using android::hardware::power::stats::V1_0::PowerEntityStateResidencyResult;
-using android::hardware::power::stats::V1_0::PowerEntityStateSpace;
-
-using android::hardware::Return;
-using android::hardware::Void;
-
-namespace android {
-namespace server {
-namespace stats {
-
-static std::function<AStatsManager_PullAtomCallbackReturn(int32_t atomTag, AStatsEventList* data)>
- gPuller = {};
-
-static sp<android::hardware::power::V1_0::IPower> gPowerHalV1_0 = nullptr;
-static sp<android::hardware::power::V1_1::IPower> gPowerHalV1_1 = nullptr;
-static sp<android::hardware::power::stats::V1_0::IPowerStats> gPowerStatsHalV1_0 = nullptr;
-
-static std::unordered_map<uint32_t, std::string> gEntityNames = {};
-static std::unordered_map<uint32_t, std::unordered_map<uint32_t, std::string>> gStateNames = {};
-
-static std::mutex gPowerHalMutex;
-
-// The caller must be holding gPowerHalMutex.
-static void deinitPowerStatsLocked() {
- gPowerHalV1_0 = nullptr;
- gPowerHalV1_1 = nullptr;
- gPowerStatsHalV1_0 = nullptr;
-}
-
-struct SubsystemSleepStatePullerDeathRecipient : virtual public hardware::hidl_death_recipient {
- virtual void serviceDied(uint64_t cookie,
- const wp<android::hidl::base::V1_0::IBase>& who) override {
-
- // The HAL just died. Reset all handles to HAL services.
- std::lock_guard<std::mutex> lock(gPowerHalMutex);
- deinitPowerStatsLocked();
- }
-};
-
-static sp<SubsystemSleepStatePullerDeathRecipient> gDeathRecipient =
- new SubsystemSleepStatePullerDeathRecipient();
-
-SubsystemSleepStatePuller::SubsystemSleepStatePuller() {}
-
-// The caller must be holding gPowerHalMutex.
-static bool checkResultLocked(const Return<void> &ret, const char* function) {
- if (!ret.isOk()) {
- ALOGE("%s failed: requested HAL service not available. Description: %s",
- function, ret.description().c_str());
- if (ret.isDeadObject()) {
- deinitPowerStatsLocked();
- }
- return false;
- }
- return true;
-}
-
-// The caller must be holding gPowerHalMutex.
-// gPowerStatsHalV1_0 must not be null
-static bool initializePowerStats() {
- using android::hardware::power::stats::V1_0::Status;
-
- // Clear out previous content if we are re-initializing
- gEntityNames.clear();
- gStateNames.clear();
-
- Return<void> ret;
- ret = gPowerStatsHalV1_0->getPowerEntityInfo([](auto infos, auto status) {
- if (status != Status::SUCCESS) {
- ALOGE("Error getting power entity info");
- return;
- }
-
- // construct lookup table of powerEntityId to power entity name
- for (auto info : infos) {
- gEntityNames.emplace(info.powerEntityId, info.powerEntityName);
- }
- });
- if (!checkResultLocked(ret, __func__)) {
- return false;
- }
-
- ret = gPowerStatsHalV1_0->getPowerEntityStateInfo({}, [](auto stateSpaces, auto status) {
- if (status != Status::SUCCESS) {
- ALOGE("Error getting state info");
- return;
- }
-
- // construct lookup table of powerEntityId, powerEntityStateId to power entity state name
- for (auto stateSpace : stateSpaces) {
- std::unordered_map<uint32_t, std::string> stateNames = {};
- for (auto state : stateSpace.states) {
- stateNames.emplace(state.powerEntityStateId,
- state.powerEntityStateName);
- }
- gStateNames.emplace(stateSpace.powerEntityId, stateNames);
- }
- });
- if (!checkResultLocked(ret, __func__)) {
- return false;
- }
-
- return (!gEntityNames.empty()) && (!gStateNames.empty());
-}
-
-// The caller must be holding gPowerHalMutex.
-static bool getPowerStatsHalLocked() {
- if(gPowerStatsHalV1_0 == nullptr) {
- gPowerStatsHalV1_0 = android::hardware::power::stats::V1_0::IPowerStats::getService();
- if (gPowerStatsHalV1_0 == nullptr) {
- ALOGE("Unable to get power.stats HAL service.");
- return false;
- }
-
- // Link death recipient to power.stats service handle
- hardware::Return<bool> linked = gPowerStatsHalV1_0->linkToDeath(gDeathRecipient, 0);
- if (!linked.isOk()) {
- ALOGE("Transaction error in linking to power.stats HAL death: %s",
- linked.description().c_str());
- deinitPowerStatsLocked();
- return false;
- } else if (!linked) {
- ALOGW("Unable to link to power.stats HAL death notifications");
- // We should still continue even though linking failed
- }
- return initializePowerStats();
- }
- return true;
-}
-
-// The caller must be holding gPowerHalMutex.
-static AStatsManager_PullAtomCallbackReturn getIPowerStatsDataLocked(int32_t atomTag,
- AStatsEventList* data) {
- using android::hardware::power::stats::V1_0::Status;
-
- if(!getPowerStatsHalLocked()) {
- return AStatsManager_PULL_SKIP;
- }
- // Get power entity state residency data
- bool success = false;
- Return<void> ret = gPowerStatsHalV1_0->getPowerEntityStateResidencyData(
- {}, [&data, &success](auto results, auto status) {
- if (status == Status::NOT_SUPPORTED) {
- ALOGW("getPowerEntityStateResidencyData is not supported");
- success = false;
- return;
- }
- for (auto result : results) {
- for (auto stateResidency : result.stateResidencyData) {
- android::util::addAStatsEvent(data, android::util::SUBSYSTEM_SLEEP_STATE,
- gEntityNames.at(result.powerEntityId).c_str(),
- gStateNames.at(result.powerEntityId)
- .at(stateResidency.powerEntityStateId)
- .c_str(),
- stateResidency.totalStateEntryCount,
- stateResidency.totalTimeInStateMs);
- }
- }
- success = true;
- });
- // Intentionally not returning early here.
- // bool success determines if this succeeded or not.
- checkResultLocked(ret, __func__);
- if (!success) {
- return AStatsManager_PULL_SKIP;
- }
- return AStatsManager_PULL_SUCCESS;
-}
-
-// The caller must be holding gPowerHalMutex.
-static bool getPowerHalLocked() {
- if(gPowerHalV1_0 == nullptr) {
- gPowerHalV1_0 = android::hardware::power::V1_0::IPower::getService();
- if(gPowerHalV1_0 == nullptr) {
- ALOGE("Unable to get power HAL service.");
- return false;
- }
- gPowerHalV1_1 = android::hardware::power::V1_1::IPower::castFrom(gPowerHalV1_0);
-
- // Link death recipient to power service handle
- hardware::Return<bool> linked = gPowerHalV1_0->linkToDeath(gDeathRecipient, 0);
- if (!linked.isOk()) {
- ALOGE("Transaction error in linking to power HAL death: %s",
- linked.description().c_str());
- gPowerHalV1_0 = nullptr;
- return false;
- } else if (!linked) {
- ALOGW("Unable to link to power. death notifications");
- // We should still continue even though linking failed
- }
- }
- return true;
-}
-
-// The caller must be holding gPowerHalMutex.
-static AStatsManager_PullAtomCallbackReturn getIPowerDataLocked(int32_t atomTag,
- AStatsEventList* data) {
- using android::hardware::power::V1_0::Status;
-
- if(!getPowerHalLocked()) {
- return AStatsManager_PULL_SKIP;
- }
-
- Return<void> ret;
- ret = gPowerHalV1_0->getPlatformLowPowerStats(
- [&data](hidl_vec<PowerStatePlatformSleepState> states, Status status) {
- if (status != Status::SUCCESS) return;
-
- for (size_t i = 0; i < states.size(); i++) {
- const PowerStatePlatformSleepState& state = states[i];
- android::util::addAStatsEvent(data, android::util::SUBSYSTEM_SLEEP_STATE,
- state.name.c_str(), "",
- state.totalTransitions,
- state.residencyInMsecSinceBoot);
-
- ALOGV("powerstate: %s, %lld, %lld, %d", state.name.c_str(),
- (long long)state.residencyInMsecSinceBoot,
- (long long)state.totalTransitions,
- state.supportedOnlyInSuspend ? 1 : 0);
- for (const auto& voter : state.voters) {
- android::util::addAStatsEvent(data,
- android::util::SUBSYSTEM_SLEEP_STATE,
- state.name.c_str(), voter.name.c_str(),
- voter.totalNumberOfTimesVotedSinceBoot,
- voter.totalTimeInMsecVotedForSinceBoot);
-
- ALOGV("powerstatevoter: %s, %s, %lld, %lld", state.name.c_str(),
- voter.name.c_str(),
- (long long)voter.totalTimeInMsecVotedForSinceBoot,
- (long long)voter.totalNumberOfTimesVotedSinceBoot);
- }
- }
- });
- if (!checkResultLocked(ret, __func__)) {
- return AStatsManager_PULL_SKIP;
- }
-
- // Trying to cast to IPower 1.1, this will succeed only for devices supporting 1.1
- sp<android::hardware::power::V1_1::IPower> gPowerHal_1_1 =
- android::hardware::power::V1_1::IPower::castFrom(gPowerHalV1_0);
- if (gPowerHal_1_1 != nullptr) {
- ret = gPowerHal_1_1->getSubsystemLowPowerStats(
- [&data](hidl_vec<PowerStateSubsystem> subsystems, Status status) {
- if (status != Status::SUCCESS) return;
-
- if (subsystems.size() > 0) {
- for (size_t i = 0; i < subsystems.size(); i++) {
- const PowerStateSubsystem& subsystem = subsystems[i];
- for (size_t j = 0; j < subsystem.states.size(); j++) {
- const PowerStateSubsystemSleepState& state =
- subsystem.states[j];
- android::util::
- addAStatsEvent(data,
- android::util::SUBSYSTEM_SLEEP_STATE,
- subsystem.name.c_str(),
- state.name.c_str(),
- state.totalTransitions,
- state.residencyInMsecSinceBoot);
-
- ALOGV("subsystemstate: %s, %s, %lld, %lld, %lld",
- subsystem.name.c_str(), state.name.c_str(),
- (long long)state.residencyInMsecSinceBoot,
- (long long)state.totalTransitions,
- (long long)state.lastEntryTimestampMs);
- }
- }
- }
- });
- }
- return AStatsManager_PULL_SUCCESS;
-}
-
-// The caller must be holding gPowerHalMutex.
-std::function<AStatsManager_PullAtomCallbackReturn(int32_t atomTag, AStatsEventList* data)>
-getPullerLocked() {
- std::function<AStatsManager_PullAtomCallbackReturn(int32_t atomTag, AStatsEventList * data)>
- ret = {};
-
- // First see if power.stats HAL is available. Fall back to power HAL if
- // power.stats HAL is unavailable.
- if(android::hardware::power::stats::V1_0::IPowerStats::getService() != nullptr) {
- ALOGI("Using power.stats HAL");
- ret = getIPowerStatsDataLocked;
- } else if(android::hardware::power::V1_0::IPower::getService() != nullptr) {
- ALOGI("Using power HAL");
- ret = getIPowerDataLocked;
- }
-
- return ret;
-}
-
-AStatsManager_PullAtomCallbackReturn SubsystemSleepStatePuller::Pull(int32_t atomTag,
- AStatsEventList* data) {
- std::lock_guard<std::mutex> lock(gPowerHalMutex);
-
- if(!gPuller) {
- gPuller = getPullerLocked();
- }
-
- if(gPuller) {
- return gPuller(atomTag, data);
- }
-
- ALOGE("Unable to load Power Hal or power.stats HAL");
- return AStatsManager_PULL_SKIP;
-}
-
-} // namespace stats
-} // namespace server
-} // namespace android
diff --git a/services/core/jni/stats/SubsystemSleepStatePuller.h b/services/core/jni/stats/SubsystemSleepStatePuller.h
deleted file mode 100644
index da9679c..0000000
--- a/services/core/jni/stats/SubsystemSleepStatePuller.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * 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 <stats_event.h>
-#include <stats_pull_atom_callback.h>
-
-namespace android {
-namespace server {
-namespace stats {
-
-/**
- * Reads hal for sleep states
- */
-class SubsystemSleepStatePuller {
-public:
- SubsystemSleepStatePuller();
- AStatsManager_PullAtomCallbackReturn Pull(int32_t atomTag, AStatsEventList* data);
-};
-
-} // namespace stats
-} // namespace server
-} // namespace android