|  | /* | 
|  | * Copyright 2019 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. | 
|  | */ | 
|  |  | 
|  | #include "PhaseOffsets.h" | 
|  |  | 
|  | #include <cutils/properties.h> | 
|  |  | 
|  | #include "SurfaceFlingerProperties.h" | 
|  |  | 
|  | namespace android { | 
|  | using namespace android::sysprop; | 
|  |  | 
|  | namespace scheduler { | 
|  |  | 
|  | PhaseOffsets::~PhaseOffsets() = default; | 
|  |  | 
|  | namespace impl { | 
|  | PhaseOffsets::PhaseOffsets() { | 
|  | int64_t vsyncPhaseOffsetNs = vsync_event_phase_offset_ns(1000000); | 
|  |  | 
|  | int64_t sfVsyncPhaseOffsetNs = vsync_sf_event_phase_offset_ns(1000000); | 
|  |  | 
|  | char value[PROPERTY_VALUE_MAX]; | 
|  | property_get("debug.sf.early_phase_offset_ns", value, "-1"); | 
|  | const int earlySfOffsetNs = atoi(value); | 
|  |  | 
|  | property_get("debug.sf.early_gl_phase_offset_ns", value, "-1"); | 
|  | const int earlyGlSfOffsetNs = atoi(value); | 
|  |  | 
|  | property_get("debug.sf.early_app_phase_offset_ns", value, "-1"); | 
|  | const int earlyAppOffsetNs = atoi(value); | 
|  |  | 
|  | property_get("debug.sf.early_gl_app_phase_offset_ns", value, "-1"); | 
|  | const int earlyGlAppOffsetNs = atoi(value); | 
|  |  | 
|  | property_get("debug.sf.high_fps_early_phase_offset_ns", value, "-1"); | 
|  | const int highFpsEarlySfOffsetNs = atoi(value); | 
|  |  | 
|  | property_get("debug.sf.high_fps_early_gl_phase_offset_ns", value, "-1"); | 
|  | const int highFpsEarlyGlSfOffsetNs = atoi(value); | 
|  |  | 
|  | property_get("debug.sf.high_fps_early_app_phase_offset_ns", value, "-1"); | 
|  | const int highFpsEarlyAppOffsetNs = atoi(value); | 
|  |  | 
|  | property_get("debug.sf.high_fps_early_gl_app_phase_offset_ns", value, "-1"); | 
|  | const int highFpsEarlyGlAppOffsetNs = atoi(value); | 
|  |  | 
|  | // TODO(b/122905996): Define these in device.mk. | 
|  | property_get("debug.sf.high_fps_late_app_phase_offset_ns", value, "2000000"); | 
|  | const int highFpsLateAppOffsetNs = atoi(value); | 
|  |  | 
|  | property_get("debug.sf.high_fps_late_sf_phase_offset_ns", value, "1000000"); | 
|  | const int highFpsLateSfOffsetNs = atoi(value); | 
|  |  | 
|  | mDefaultRefreshRateOffsets.early = {earlySfOffsetNs != -1 ? earlySfOffsetNs | 
|  | : sfVsyncPhaseOffsetNs, | 
|  | earlyAppOffsetNs != -1 ? earlyAppOffsetNs | 
|  | : vsyncPhaseOffsetNs}; | 
|  | mDefaultRefreshRateOffsets.earlyGl = {earlyGlSfOffsetNs != -1 ? earlyGlSfOffsetNs | 
|  | : sfVsyncPhaseOffsetNs, | 
|  | earlyGlAppOffsetNs != -1 ? earlyGlAppOffsetNs | 
|  | : vsyncPhaseOffsetNs}; | 
|  | mDefaultRefreshRateOffsets.late = {sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs}; | 
|  |  | 
|  | mHighRefreshRateOffsets.early = {highFpsEarlySfOffsetNs != -1 ? highFpsEarlySfOffsetNs | 
|  | : highFpsLateSfOffsetNs, | 
|  | highFpsEarlyAppOffsetNs != -1 ? highFpsEarlyAppOffsetNs | 
|  | : highFpsLateAppOffsetNs}; | 
|  | mHighRefreshRateOffsets.earlyGl = {highFpsEarlyGlSfOffsetNs != -1 ? highFpsEarlyGlSfOffsetNs | 
|  | : highFpsLateSfOffsetNs, | 
|  | highFpsEarlyGlAppOffsetNs != -1 ? highFpsEarlyGlAppOffsetNs | 
|  | : highFpsLateAppOffsetNs}; | 
|  | mHighRefreshRateOffsets.late = {highFpsLateSfOffsetNs, highFpsLateAppOffsetNs}; | 
|  | } | 
|  |  | 
|  | PhaseOffsets::Offsets PhaseOffsets::getCurrentOffsets() const { | 
|  | switch (mRefreshRateType) { | 
|  | case RefreshRateConfigs::RefreshRateType::PERFORMANCE: | 
|  | return mHighRefreshRateOffsets; | 
|  | default: | 
|  | return mDefaultRefreshRateOffsets; | 
|  | } | 
|  | } | 
|  |  | 
|  | void PhaseOffsets::dump(std::string& result) const { | 
|  | const auto [early, earlyGl, late] = getCurrentOffsets(); | 
|  | base::StringAppendF(&result, | 
|  | "         app phase: %9" PRId64 " ns\t         SF phase: %9" PRId64 " ns\n" | 
|  | "   early app phase: %9" PRId64 " ns\t   early SF phase: %9" PRId64 " ns\n" | 
|  | "GL early app phase: %9" PRId64 " ns\tGL early SF phase: %9" PRId64 " ns\n", | 
|  | late.app, late.sf, early.app, early.sf, earlyGl.app, earlyGl.sf); | 
|  | } | 
|  |  | 
|  | nsecs_t PhaseOffsets::getCurrentAppOffset() { | 
|  | return getCurrentOffsets().late.app; | 
|  | } | 
|  |  | 
|  | nsecs_t PhaseOffsets::getCurrentSfOffset() { | 
|  | return getCurrentOffsets().late.sf; | 
|  | } | 
|  |  | 
|  | } // namespace impl | 
|  | } // namespace scheduler | 
|  | } // namespace android |