diff options
11 files changed, 176 insertions, 682 deletions
diff --git a/services/core/java/com/android/server/powerstats/PowerStatsService.java b/services/core/java/com/android/server/powerstats/PowerStatsService.java index 5bd907fb2654..5fe5db69bc8e 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 @@ public class PowerStatsService extends SystemService { private BatteryTrigger mBatteryTrigger; @Nullable private TimerTrigger mTimerTrigger; + @Nullable + private StatsPullAtomCallbackImpl mPullAtomCallback; @VisibleForTesting static class Injector { @@ -119,6 +121,11 @@ public class PowerStatsService extends SystemService { 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 @@ public class PowerStatsService extends SystemService { @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 @@ public class PowerStatsService extends SystemService { 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 000000000000..f8b9601bfd62 --- /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 0cc2a6c52b1d..263776c63db6 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 @@ public class StatsPullAtomService extends SystemService { 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 @@ public class StatsPullAtomService extends SystemService { 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 345b2464d75a..cc7e00a43a6e 100644 --- a/services/core/jni/Android.bp +++ b/services/core/jni/Android.bp @@ -25,8 +25,6 @@ cc_library_static { "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 @@ cc_library_static { "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 @@ cc_defaults { "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 b1fbe6461c44..000000000000 --- 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 189332107a5d..c5394f3aba69 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -59,7 +59,6 @@ int register_com_android_server_soundtrigger_middleware_AudioSessionProviderImpl 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 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */) 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 a61babf32e58..000000000000 --- 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 7f788c226c7b..000000000000 --- 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 db07d600d251..000000000000 --- 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 1ba98ef8dab7..000000000000 --- 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 da9679c68a64..000000000000 --- 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 |