Merge "Reroute surfaceflinger atoms through system server" into sc-dev am: d07ae7b445

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14164946

Change-Id: I9b27a61226d601ac5b242fd98ed5c3856e711ecc
This commit is contained in:
TreeHugger Robot
2021-04-21 01:13:24 +00:00
committed by Automerger Merge Worker
7 changed files with 289 additions and 1 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 The Android Open Source Project
* Copyright 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.
@@ -432,6 +432,7 @@ public class StatsPullAtomService extends SystemService {
mContext = context;
}
private native void initializeNativePullers();
/**
* Use of this StatsPullAtomCallbackImpl means we avoid one class per tagId, which we would
* get if we used lambdas.
@@ -713,6 +714,7 @@ public class StatsPullAtomService extends SystemService {
super.onBootPhase(phase);
if (phase == PHASE_SYSTEM_SERVICES_READY) {
BackgroundThread.getHandler().post(() -> {
initializeNativePullers(); // Initialize pullers that need JNI.
initializePullersState();
registerPullers();
registerEventListeners();

View File

@@ -34,6 +34,7 @@ cc_library_static {
"gnss/GnssMeasurement.cpp",
"gnss/GnssMeasurementCallback.cpp",
"gnss/Utils.cpp",
"stats/SurfaceFlingerPuller.cpp",
"com_android_server_adb_AdbDebuggingManager.cpp",
"com_android_server_am_BatteryStatsService.cpp",
"com_android_server_biometrics_SurfaceToNativeHandleConverter.cpp",
@@ -53,6 +54,7 @@ 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",
@@ -127,6 +129,7 @@ cc_defaults {
"libsensorservice",
"libsensorservicehidl",
"libgui",
"libtimestats_atoms_proto",
"libusbhost",
"libtinyalsa",
"libEGL",

View File

@@ -0,0 +1,61 @@
/*
* Copyright 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/SurfaceFlingerPuller.h"
namespace android {
static server::stats::SurfaceFlingerPuller gSurfaceFlingerPuller;
static AStatsManager_PullAtomCallbackReturn onSurfaceFlingerPullCallback(int32_t atom_tag,
AStatsEventList* data,
void* cookie) {
return gSurfaceFlingerPuller.pull(atom_tag, data);
}
static void initializeNativePullers(JNIEnv* env, jobject javaObject) {
// Surface flinger layer & global info.
gSurfaceFlingerPuller = server::stats::SurfaceFlingerPuller();
AStatsManager_setPullAtomCallback(android::util::SURFACEFLINGER_STATS_GLOBAL_INFO,
/* metadata= */ nullptr, onSurfaceFlingerPullCallback,
/* cookie= */ nullptr);
AStatsManager_setPullAtomCallback(android::util::SURFACEFLINGER_STATS_LAYER_INFO,
/* metadata= */ nullptr, onSurfaceFlingerPullCallback,
/* cookie= */ nullptr);
}
static const JNINativeMethod sMethods[] = {
{"initializeNativePullers", "()V", (void*)initializeNativePullers}};
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

View File

@@ -61,6 +61,7 @@ int register_android_server_com_android_server_pm_PackageManagerShellCommandData
int register_android_server_AdbDebuggingManager(JNIEnv* env);
int register_android_server_FaceService(JNIEnv* env);
int register_android_server_GpuService(JNIEnv* env);
int register_android_server_stats_pull_StatsPullAtomService(JNIEnv* env);
};
using namespace android;
@@ -115,5 +116,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
register_android_server_AdbDebuggingManager(env);
register_android_server_FaceService(env);
register_android_server_GpuService(env);
register_android_server_stats_pull_StatsPullAtomService(env);
return JNI_VERSION_1_4;
}

View File

@@ -0,0 +1,8 @@
jeffreyhuang@google.com
jtnguyen@google.com
muhammadq@google.com
sharaieko@google.com
singhtejinder@google.com
tsaichristine@google.com
yaochen@google.com
yro@google.com

View File

@@ -0,0 +1,168 @@
/*
* Copyright 2021 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 "SurfaceFlingerPuller"
#include "SurfaceFlingerPuller.h"
#include <gui/SurfaceComposerClient.h>
#include <log/log.h>
#include <statslog.h>
#include <timestatsatomsproto/TimeStatsAtomsProtoHeader.h>
#include <vector>
namespace android {
namespace server {
namespace stats {
using android::util::BytesField;
using std::optional;
namespace {
optional<BytesField> getBytes(const google::protobuf::MessageLite& proto, std::string& data) {
if (!proto.SerializeToString(&data)) {
ALOGW("Unable to serialize surface flinger bytes field");
return std::nullopt;
}
return {BytesField(data.data(), data.size())};
}
} // namespace
AStatsManager_PullAtomCallbackReturn SurfaceFlingerPuller::pull(int32_t atomTag,
AStatsEventList* data) {
// Don't need mutexes here, since there is no global state.
// SurfaceComposerClient is thread safe, and surfaceflinger is internally thread safe.
bool success = false;
std::string pullDataProto;
status_t err = SurfaceComposerClient::onPullAtom(atomTag, &pullDataProto, &success);
if (!success || err != NO_ERROR) {
ALOGW("Failed to pull atom %" PRId32
" from surfaceflinger. Success is %d, binder status is %s",
atomTag, (int)success, binder::Status::exceptionToString(err).c_str());
return AStatsManager_PULL_SKIP;
}
switch (atomTag) {
case android::util::SURFACEFLINGER_STATS_GLOBAL_INFO:
return parseGlobalInfoPull(pullDataProto, data);
case android::util::SURFACEFLINGER_STATS_LAYER_INFO:
return parseLayerInfoPull(pullDataProto, data);
default:
ALOGW("Invalid atom id for surfaceflinger pullers: %" PRId32, atomTag);
return AStatsManager_PULL_SKIP;
}
}
AStatsManager_PullAtomCallbackReturn SurfaceFlingerPuller::parseGlobalInfoPull(
const std::string& protoData, AStatsEventList* data) {
android::surfaceflinger::SurfaceflingerStatsGlobalInfoWrapper atomList;
if (!atomList.ParseFromString(protoData)) {
ALOGW("Error parsing surface flinger global stats to proto");
return AStatsManager_PULL_SKIP;
}
for (const auto& atom : atomList.atom()) {
// The strings must outlive the BytesFields, which only have a pointer to the data.
std::string frameDurationStr, renderEngineTimeStr, deadlineMissesStr, predictionErrorsStr;
optional<BytesField> frameDuration = getBytes(atom.frame_duration(), frameDurationStr);
optional<BytesField> renderEngineTime =
getBytes(atom.render_engine_timing(), renderEngineTimeStr);
optional<BytesField> deadlineMisses =
getBytes(atom.sf_deadline_misses(), deadlineMissesStr);
optional<BytesField> predictionErrors =
getBytes(atom.sf_prediction_errors(), predictionErrorsStr);
// Fail if any serialization to bytes failed.
if (!frameDuration || !renderEngineTime || !deadlineMisses || !predictionErrors) {
return AStatsManager_PULL_SKIP;
}
android::util::addAStatsEvent(data, android::util::SURFACEFLINGER_STATS_GLOBAL_INFO,
atom.total_frames(), atom.missed_frames(),
atom.client_composition_frames(), atom.display_on_millis(),
atom.animation_millis(), atom.event_connection_count(),
frameDuration.value(), renderEngineTime.value(),
atom.total_timeline_frames(), atom.total_janky_frames(),
atom.total_janky_frames_with_long_cpu(),
atom.total_janky_frames_with_long_gpu(),
atom.total_janky_frames_sf_unattributed(),
atom.total_janky_frames_app_unattributed(),
atom.total_janky_frames_sf_scheduling(),
atom.total_jank_frames_sf_prediction_error(),
atom.total_jank_frames_app_buffer_stuffing(),
atom.display_refresh_rate_bucket(), deadlineMisses.value(),
predictionErrors.value(), atom.render_rate_bucket());
}
return AStatsManager_PULL_SUCCESS;
}
AStatsManager_PullAtomCallbackReturn SurfaceFlingerPuller::parseLayerInfoPull(
const std::string& protoData, AStatsEventList* data) {
android::surfaceflinger::SurfaceflingerStatsLayerInfoWrapper atomList;
if (!atomList.ParseFromString(protoData)) {
ALOGW("Error parsing surface flinger layer stats to proto");
return AStatsManager_PULL_SKIP;
}
for (const auto& atom : atomList.atom()) {
// The strings must outlive the BytesFields, which only have a pointer to the data.
std::string present2PresentStr, post2presentStr, acquire2PresentStr, latch2PresentStr,
desired2PresentStr, post2AcquireStr, frameRateVoteStr, appDeadlineMissesStr;
optional<BytesField> present2Present =
getBytes(atom.present_to_present(), present2PresentStr);
optional<BytesField> post2present = getBytes(atom.post_to_present(), post2presentStr);
optional<BytesField> acquire2Present =
getBytes(atom.acquire_to_present(), acquire2PresentStr);
optional<BytesField> latch2Present = getBytes(atom.latch_to_present(), latch2PresentStr);
optional<BytesField> desired2Present =
getBytes(atom.desired_to_present(), desired2PresentStr);
optional<BytesField> post2Acquire = getBytes(atom.post_to_acquire(), post2AcquireStr);
optional<BytesField> frameRateVote = getBytes(atom.set_frame_rate_vote(), frameRateVoteStr);
optional<BytesField> appDeadlineMisses =
getBytes(atom.app_deadline_misses(), appDeadlineMissesStr);
// Fail if any serialization to bytes failed.
if (!present2Present || !post2present || !acquire2Present || !latch2Present ||
!desired2Present || !post2Acquire || !frameRateVote || !appDeadlineMisses) {
return AStatsManager_PULL_SKIP;
}
android::util::addAStatsEvent(data, android::util::SURFACEFLINGER_STATS_LAYER_INFO,
atom.layer_name().c_str(), atom.total_frames(),
atom.dropped_frames(), present2Present.value(),
post2present.value(), acquire2Present.value(),
latch2Present.value(), desired2Present.value(),
post2Acquire.value(), atom.late_acquire_frames(),
atom.bad_desired_present_frames(), atom.uid(),
atom.total_timeline_frames(), atom.total_janky_frames(),
atom.total_janky_frames_with_long_cpu(),
atom.total_janky_frames_with_long_gpu(),
atom.total_janky_frames_sf_unattributed(),
atom.total_janky_frames_app_unattributed(),
atom.total_janky_frames_sf_scheduling(),
atom.total_jank_frames_sf_prediction_error(),
atom.total_jank_frames_app_buffer_stuffing(),
atom.display_refresh_rate_bucket(), atom.render_rate_bucket(),
frameRateVote.value(), appDeadlineMisses.value());
}
return AStatsManager_PULL_SUCCESS;
}
} // namespace stats
} // namespace server
} // namespace android

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2021 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>
#include <utils/String16.h>
namespace android {
namespace server {
namespace stats {
/**
* Pulls data from surfaceflinger.
* The indirection is needed because surfaceflinger is a bootstrap process.
*/
class SurfaceFlingerPuller {
public:
AStatsManager_PullAtomCallbackReturn pull(int32_t atomTag, AStatsEventList* data);
private:
AStatsManager_PullAtomCallbackReturn parseGlobalInfoPull(const std::string& protoData,
AStatsEventList* data);
AStatsManager_PullAtomCallbackReturn parseLayerInfoPull(const std::string& protoData,
AStatsEventList* data);
};
} // namespace stats
} // namespace server
} // namespace android