Merge "Initialize pointerCapture"
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 00f9f42..49383e5 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -982,9 +982,13 @@
auto to_de = create_data_user_de_path(volume_uuid, user);
int rc = copy_directory_recursive(from_de.c_str(), to_de.c_str());
if (rc != 0) {
- // TODO(narayan): Should we clear clear the rolled back CE data if
- // something goes wrong here ? We're choosing between leaving the
- // app devoid of all its data or with just its ce data installed.
+ if (needs_ce_rollback) {
+ auto ce_data = create_data_user_ce_package_path(volume_uuid, user, package_name);
+ LOG(WARNING) << "de_data rollback failed. Erasing rolled back ce_data " << ce_data;
+ if (delete_dir_contents(ce_data.c_str(), 1, nullptr) != 0) {
+ LOG(WARNING) << "Failed to delete rolled back ce_data " << ce_data;
+ }
+ }
res = error(rc, "Failed copying " + from_de + " to " + to_de);
return res;
}
diff --git a/cmds/installd/tests/binder_test_utils.h b/cmds/installd/tests/binder_test_utils.h
new file mode 100644
index 0000000..efd1391
--- /dev/null
+++ b/cmds/installd/tests/binder_test_utils.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 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.
+ */
+
+#pragma once
+
+#include <binder/Status.h>
+#include <gtest/gtest.h>
+#include <utils/String8.h>
+
+#define ASSERT_BINDER_SUCCESS(expr) \
+ ({ \
+ binder::Status expect_status = (expr); \
+ ASSERT_TRUE(expect_status.isOk()) << expect_status.toString8().c_str(); \
+ expect_status; \
+ })
+#define ASSERT_BINDER_FAIL(expr) \
+ ({ \
+ binder::Status expect_status = (expr); \
+ ASSERT_FALSE(expect_status.isOk()); \
+ expect_status; \
+ })
+#define EXPECT_BINDER_SUCCESS(expr) \
+ ({ \
+ binder::Status expect_status = (expr); \
+ EXPECT_TRUE(expect_status.isOk()) << expect_status.toString8().c_str(); \
+ expect_status; \
+ })
+#define EXPECT_BINDER_FAIL(expr) \
+ ({ \
+ binder::Status expect_status = (expr); \
+ EXPECT_FALSE(expect_status.isOk()); \
+ expect_status; \
+ })
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index 79e6859..e2afe1d 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -25,7 +25,7 @@
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/unique_fd.h>
-
+#include <binder/Status.h>
#include <cutils/properties.h>
#include <gtest/gtest.h>
@@ -33,6 +33,7 @@
#include <selinux/android.h>
#include <selinux/avc.h>
+#include "binder_test_utils.h"
#include "dexopt.h"
#include "InstalldNativeService.h"
#include "globals.h"
@@ -451,11 +452,9 @@
std::unique_ptr<std::string> compilation_reason_ptr(new std::string("test-reason"));
bool prof_result;
- binder::Status prof_binder_result = service_->prepareAppProfile(
+ ASSERT_BINDER_SUCCESS(service_->prepareAppProfile(
package_name_, kTestUserId, kTestAppId, *profile_name_ptr, apk_path_,
- /*dex_metadata*/ nullptr, &prof_result);
-
- ASSERT_TRUE(prof_binder_result.isOk()) << prof_binder_result.toString8().c_str();
+ /*dex_metadata*/ nullptr, &prof_result));
ASSERT_TRUE(prof_result);
binder::Status result = service_->dexopt(apk_path_,
@@ -760,9 +759,8 @@
void createProfileSnapshot(int32_t appid, const std::string& package_name,
bool expected_result) {
bool result;
- binder::Status binder_result = service_->createProfileSnapshot(
- appid, package_name, kPrimaryProfile, apk_path_, &result);
- ASSERT_TRUE(binder_result.isOk()) << binder_result.toString8().c_str();
+ ASSERT_BINDER_SUCCESS(service_->createProfileSnapshot(
+ appid, package_name, kPrimaryProfile, apk_path_, &result));
ASSERT_EQ(expected_result, result);
if (!expected_result) {
@@ -802,9 +800,8 @@
const std::string& code_path,
bool expected_result) {
bool result;
- binder::Status binder_result = service_->mergeProfiles(
- kTestAppUid, package_name, code_path, &result);
- ASSERT_TRUE(binder_result.isOk()) << binder_result.toString8().c_str();
+ ASSERT_BINDER_SUCCESS(service_->mergeProfiles(
+ kTestAppUid, package_name, code_path, &result));
ASSERT_EQ(expected_result, result);
if (!expected_result) {
@@ -830,10 +827,9 @@
void preparePackageProfile(const std::string& package_name, const std::string& profile_name,
bool expected_result) {
bool result;
- binder::Status binder_result = service_->prepareAppProfile(
+ ASSERT_BINDER_SUCCESS(service_->prepareAppProfile(
package_name, kTestUserId, kTestAppId, profile_name, apk_path_,
- /*dex_metadata*/ nullptr, &result);
- ASSERT_TRUE(binder_result.isOk()) << binder_result.toString8().c_str();
+ /*dex_metadata*/ nullptr, &result));
ASSERT_EQ(expected_result, result);
if (!expected_result) {
@@ -919,8 +915,7 @@
SetupProfiles(/*setup_ref*/ true);
createProfileSnapshot(kTestAppId, package_name_, /*expected_result*/ true);
- binder::Status binder_result = service_->destroyProfileSnapshot(package_name_, kPrimaryProfile);
- ASSERT_TRUE(binder_result.isOk()) << binder_result.toString8().c_str();
+ ASSERT_BINDER_SUCCESS(service_->destroyProfileSnapshot(package_name_, kPrimaryProfile));
struct stat st;
ASSERT_EQ(-1, stat(snap_profile_.c_str(), &st));
ASSERT_EQ(ENOENT, errno);
@@ -978,7 +973,7 @@
ASSERT_EQ(0, chmod(ref_profile_dir.c_str(), 0700));
// Run createAppData again which will offer to fix-up the profile directories.
- ASSERT_TRUE(service_->createAppData(
+ ASSERT_BINDER_SUCCESS(service_->createAppData(
volume_uuid_,
package_name_,
kTestUserId,
@@ -986,7 +981,7 @@
kTestAppUid,
se_info_,
kOSdkVersion,
- &ce_data_inode_).isOk());
+ &ce_data_inode_));
// Check the file access.
CheckFileAccess(cur_profile_dir, kTestAppUid, kTestAppUid, 0700 | S_IFDIR);
@@ -1032,9 +1027,8 @@
void createBootImageProfileSnapshot(const std::string& classpath, bool expected_result) {
bool result;
- binder::Status binder_result = service_->createProfileSnapshot(
- -1, "android", "android.prof", classpath, &result);
- ASSERT_TRUE(binder_result.isOk());
+ ASSERT_BINDER_SUCCESS(service_->createProfileSnapshot(
+ -1, "android", "android.prof", classpath, &result));
ASSERT_EQ(expected_result, result);
if (!expected_result) {
diff --git a/cmds/installd/tests/installd_service_test.cpp b/cmds/installd/tests/installd_service_test.cpp
index 1d50737..e2c5907 100644
--- a/cmds/installd/tests/installd_service_test.cpp
+++ b/cmds/installd/tests/installd_service_test.cpp
@@ -15,18 +15,23 @@
*/
#include <sstream>
+#include <string>
+
+#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/statvfs.h>
#include <sys/xattr.h>
-#include <android-base/logging.h>
#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
#include <android-base/scopeguard.h>
#include <android-base/stringprintf.h>
#include <cutils/properties.h>
#include <gtest/gtest.h>
+#include "binder_test_utils.h"
#include "InstalldNativeService.h"
#include "dexopt.h"
#include "globals.h"
@@ -164,8 +169,8 @@
std::vector<uint8_t> result;
std::string dexPath = get_full_path("com.example/foo/file");
- EXPECT_TRUE(service->hashSecondaryDexFile(
- dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result).isOk());
+ EXPECT_BINDER_SUCCESS(service->hashSecondaryDexFile(
+ dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result));
EXPECT_EQ(result.size(), 32U);
@@ -184,8 +189,8 @@
std::vector<uint8_t> result;
std::string dexPath = get_full_path("com.example/foo/file");
- EXPECT_TRUE(service->hashSecondaryDexFile(
- dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result).isOk());
+ EXPECT_BINDER_SUCCESS(service->hashSecondaryDexFile(
+ dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result));
EXPECT_EQ(result.size(), 0U);
}
@@ -199,8 +204,8 @@
std::vector<uint8_t> result;
std::string dexPath = get_full_path("com.example/foo/file");
- EXPECT_TRUE(service->hashSecondaryDexFile(
- dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result).isOk());
+ EXPECT_BINDER_SUCCESS(service->hashSecondaryDexFile(
+ dexPath, "com.example", 10000, testUuid, FLAG_STORAGE_CE, &result));
EXPECT_EQ(result.size(), 0U);
}
@@ -214,8 +219,8 @@
std::vector<uint8_t> result;
std::string dexPath = get_full_path("com.example/foo/file");
- EXPECT_FALSE(service->hashSecondaryDexFile(
- dexPath, "com.wrong", 10000, testUuid, FLAG_STORAGE_CE, &result).isOk());
+ EXPECT_BINDER_FAIL(service->hashSecondaryDexFile(
+ dexPath, "com.wrong", 10000, testUuid, FLAG_STORAGE_CE, &result));
}
TEST_F(ServiceTest, CalculateOat) {
@@ -288,8 +293,8 @@
// Request a snapshot of the CE content but not the DE content.
int64_t ce_snapshot_inode;
- ASSERT_TRUE(service->snapshotAppData(std::make_unique<std::string>("TEST"),
- "com.foo", 0, FLAG_STORAGE_CE, &ce_snapshot_inode).isOk());
+ ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
+ "com.foo", 0, FLAG_STORAGE_CE, &ce_snapshot_inode));
struct stat buf;
memset(&buf, 0, sizeof(buf));
ASSERT_EQ(0, stat((rollback_ce_dir + "/com.foo").c_str(), &buf));
@@ -310,8 +315,8 @@
0700, 10000, 20000, false /* follow_symlinks */));
// Request a snapshot of the DE content but not the CE content.
- ASSERT_TRUE(service->snapshotAppData(std::make_unique<std::string>("TEST"),
- "com.foo", 0, FLAG_STORAGE_DE, &ce_snapshot_inode).isOk());
+ ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
+ "com.foo", 0, FLAG_STORAGE_DE, &ce_snapshot_inode));
// Only DE content snapshot was requested.
ASSERT_EQ(ce_snapshot_inode, 0);
@@ -331,8 +336,8 @@
0700, 10000, 20000, false /* follow_symlinks */));
// Request a snapshot of both the CE as well as the DE content.
- ASSERT_TRUE(service->snapshotAppData(std::make_unique<std::string>("TEST"),
- "com.foo", 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr).isOk());
+ ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
+ "com.foo", 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
ASSERT_TRUE(android::base::ReadFileToString(
rollback_ce_dir + "/com.foo/file1", &ce_content, false /* follow_symlinks */));
@@ -359,10 +364,10 @@
auto scope_guard = android::base::make_scope_guard(deleter);
int64_t ce_snapshot_inode;
- ASSERT_TRUE(service->snapshotAppData(std::make_unique<std::string>("TEST"),
- "com.foo", 0, FLAG_STORAGE_CE, &ce_snapshot_inode).isOk());
- ASSERT_TRUE(service->snapshotAppData(std::make_unique<std::string>("TEST"),
- "com.foo", 0, FLAG_STORAGE_DE, nullptr).isOk());
+ ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
+ "com.foo", 0, FLAG_STORAGE_CE, &ce_snapshot_inode));
+ ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
+ "com.foo", 0, FLAG_STORAGE_DE, nullptr));
// No CE content snapshot was performed.
ASSERT_EQ(ce_snapshot_inode, 0);
@@ -413,8 +418,8 @@
"TEST_CONTENT_2_DE", fake_package_de_path + "/file2",
0700, 10000, 20000, false /* follow_symlinks */));
- ASSERT_TRUE(service->snapshotAppData(std::make_unique<std::string>("TEST"),
- "com.foo", 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr).isOk());
+ ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
+ "com.foo", 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE, nullptr));
// Previous snapshot (with data for file1) must be cleared.
struct stat sb;
@@ -439,8 +444,8 @@
};
auto scope_guard = android::base::make_scope_guard(deleter);
- ASSERT_FALSE(service->snapshotAppData(std::make_unique<std::string>("FOO"),
- "com.foo", 0, FLAG_STORAGE_DE, nullptr).isOk());
+ EXPECT_BINDER_FAIL(service->snapshotAppData(std::make_unique<std::string>("FOO"),
+ "com.foo", 0, FLAG_STORAGE_DE, nullptr));
}
TEST_F(ServiceTest, CreateAppDataSnapshot_ClearsCache) {
@@ -488,8 +493,8 @@
ASSERT_TRUE(android::base::WriteStringToFile(
"TEST_CONTENT_DE", fake_package_de_code_cache_path + "/file1",
0700, 10000, 20000, false /* follow_symlinks */));
- ASSERT_TRUE(service->snapshotAppData(std::make_unique<std::string>("TEST"),
- "com.foo", 0, FLAG_STORAGE_CE | FLAG_STORAGE_DE, nullptr).isOk());
+ ASSERT_BINDER_SUCCESS(service->snapshotAppData(std::make_unique<std::string>("TEST"),
+ "com.foo", 0, FLAG_STORAGE_CE | FLAG_STORAGE_DE, nullptr));
// The snapshot call must clear cache.
struct stat sb;
ASSERT_EQ(-1, stat((fake_package_ce_cache_path + "/file1").c_str(), &sb));
@@ -539,8 +544,8 @@
"TEST_CONTENT_DE", fake_package_de_path + "/file1",
0700, 10000, 20000, false /* follow_symlinks */));
- ASSERT_TRUE(service->restoreAppDataSnapshot(std::make_unique<std::string>("TEST"),
- "com.foo", 10000, -1, "", 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE).isOk());
+ ASSERT_BINDER_SUCCESS(service->restoreAppDataSnapshot(std::make_unique<std::string>("TEST"),
+ "com.foo", 10000, -1, "", 0, FLAG_STORAGE_DE | FLAG_STORAGE_CE));
std::string ce_content, de_content;
ASSERT_TRUE(android::base::ReadFileToString(
@@ -705,8 +710,8 @@
};
auto scope_guard = android::base::make_scope_guard(deleter);
- ASSERT_FALSE(service->restoreAppDataSnapshot(std::make_unique<std::string>("BAR"),
- "com.foo", 10000, -1, "", 0, FLAG_STORAGE_DE).isOk());
+ EXPECT_BINDER_FAIL(service->restoreAppDataSnapshot(std::make_unique<std::string>("BAR"),
+ "com.foo", 10000, -1, "", 0, FLAG_STORAGE_DE));
}
} // namespace installd
diff --git a/cmds/installd/tests/test_utils.h b/cmds/installd/tests/test_utils.h
index a7ef674..70eefe2 100644
--- a/cmds/installd/tests/test_utils.h
+++ b/cmds/installd/tests/test_utils.h
@@ -1,3 +1,21 @@
+/*
+ * 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 <stdlib.h>
#include <string.h>
#include <sys/capability.h>
diff --git a/headers/media_plugin/media/cas/CasAPI.h b/headers/media_plugin/media/cas/CasAPI.h
index 4de314d..c87ee56 100644
--- a/headers/media_plugin/media/cas/CasAPI.h
+++ b/headers/media_plugin/media/cas/CasAPI.h
@@ -48,6 +48,14 @@
uint8_t *data,
size_t size);
+typedef void (*CasPluginCallbackExt)(
+ void *appData,
+ int32_t event,
+ int32_t arg,
+ uint8_t *data,
+ size_t size,
+ const CasSessionId *sessionId);
+
struct CasFactory {
CasFactory() {}
virtual ~CasFactory() {}
@@ -67,6 +75,13 @@
CasPluginCallback callback,
CasPlugin **plugin) = 0;
+ // Construct a new extend instance of a CasPlugin given a CA_system_id
+ virtual status_t createPlugin(
+ int32_t CA_system_id,
+ void *appData,
+ CasPluginCallbackExt callback,
+ CasPlugin **plugin) = 0;
+
private:
CasFactory(const CasFactory &);
CasFactory &operator=(const CasFactory &); /* NOLINT */
@@ -110,7 +125,15 @@
int32_t arg,
const CasData &eventData) = 0;
- // Native implementation of the MediaCas Java API provision method.
+ // Deliver an session event to the CasPlugin. The format of the event is
+ // specific to the CA scheme and is opaque to the framework.
+ virtual status_t sendSessionEvent(
+ const CasSessionId &sessionId,
+ int32_t event,
+ int32_t arg,
+ const CasData &eventData) = 0;
+
+ // Native implementation of the MediaCas Java API provision method.
virtual status_t provision(
const String8 &provisionString) = 0;
diff --git a/headers/media_plugin/media/drm/DrmAPI.h b/headers/media_plugin/media/drm/DrmAPI.h
index 0ce50f2..59bd292 100644
--- a/headers/media_plugin/media/drm/DrmAPI.h
+++ b/headers/media_plugin/media/drm/DrmAPI.h
@@ -183,10 +183,10 @@
kOfflineLicenseStateUnknown,
// Offline license state is usable, the keys may be used for decryption.
kOfflineLicenseStateUsable,
- // Offline license state is inactive, the keys have been marked for
+ // Offline license state is released, the keys have been marked for
// release using getKeyRequest() with kKeyType_Release but the
// key response has not been received.
- kOfflineLicenseStateInactive
+ kOfflineLicenseStateReleased
};
DrmPlugin() {}
diff --git a/headers/media_plugin/media/openmax/OMX_AsString.h b/headers/media_plugin/media/openmax/OMX_AsString.h
index 152015b..ce30b41 100644
--- a/headers/media_plugin/media/openmax/OMX_AsString.h
+++ b/headers/media_plugin/media/openmax/OMX_AsString.h
@@ -911,6 +911,9 @@
case OMX_VIDEO_AVCLevel5: return "Level5";
case OMX_VIDEO_AVCLevel51: return "Level51";
case OMX_VIDEO_AVCLevel52: return "Level52";
+ case OMX_VIDEO_AVCLevel6: return "Level6";
+ case OMX_VIDEO_AVCLevel61: return "Level61";
+ case OMX_VIDEO_AVCLevel62: return "Level62";
default: return def;
}
}
diff --git a/headers/media_plugin/media/openmax/OMX_Video.h b/headers/media_plugin/media/openmax/OMX_Video.h
index 9fd2fd2..b6edaa9 100644
--- a/headers/media_plugin/media/openmax/OMX_Video.h
+++ b/headers/media_plugin/media/openmax/OMX_Video.h
@@ -832,6 +832,9 @@
OMX_VIDEO_AVCLevel5 = 0x4000, /**< Level 5 */
OMX_VIDEO_AVCLevel51 = 0x8000, /**< Level 5.1 */
OMX_VIDEO_AVCLevel52 = 0x10000, /**< Level 5.2 */
+ OMX_VIDEO_AVCLevel6 = 0x20000, /**< Level 6 */
+ OMX_VIDEO_AVCLevel61 = 0x40000, /**< Level 6.1 */
+ OMX_VIDEO_AVCLevel62 = 0x80000, /**< Level 6.2 */
OMX_VIDEO_AVCLevelKhronosExtensions = 0x6F000000, /**< Reserved region for introducing Khronos Standard Extensions */
OMX_VIDEO_AVCLevelVendorStartUnused = 0x7F000000, /**< Reserved region for introducing Vendor Extensions */
OMX_VIDEO_AVCLevelMax = 0x7FFFFFFF
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index e0e211f..0f987c3 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -444,7 +444,7 @@
}
virtual bool updateInfo() {
- mInfo.token = mServerChannel->getToken();
+ mInfo.token = mServerChannel ? mServerChannel->getToken() : nullptr;
mInfo.name = mName;
mInfo.layoutParamsFlags = 0;
mInfo.layoutParamsType = InputWindowInfo::TYPE_APPLICATION;
@@ -474,8 +474,8 @@
}
void releaseChannel() {
+ mServerChannel.clear();
InputWindowHandle::releaseChannel();
- mDispatcher->unregisterInputChannel(mServerChannel);
}
protected:
virtual bool handled() {
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 2a70293..f514fe3 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -152,6 +152,7 @@
"Scheduler/MessageQueue.cpp",
"Scheduler/Scheduler.cpp",
"Scheduler/SchedulerUtils.cpp",
+ "Scheduler/PhaseOffsets.cpp",
"StartPropertySetThread.cpp",
"SurfaceFlinger.cpp",
"SurfaceInterceptor.cpp",
diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
index 9b2a6fc..075e238 100644
--- a/services/surfaceflinger/Scheduler/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -757,18 +757,7 @@
const uint32_t hwcLatency = 0;
// Ask DispSync when the next refresh will be (CLOCK_MONOTONIC).
- const nsecs_t nextRefresh = computeNextRefresh(hwcLatency);
-
- // The DispSync time is already adjusted for the difference between
- // vsync and reported-vsync (SurfaceFlinger::dispSyncPresentTimeOffset), so
- // we don't need to factor that in here. Pad a little to avoid
- // weird effects if apps might be requesting times right on the edge.
- nsecs_t extraPadding = 0;
- if (SurfaceFlinger::vsyncPhaseOffsetNs == 0) {
- extraPadding = 1000000; // 1ms (6% of 60Hz)
- }
-
- return nextRefresh + extraPadding;
+ return computeNextRefresh(hwcLatency);
}
} // namespace impl
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
new file mode 100644
index 0000000..a0a4455
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
@@ -0,0 +1,117 @@
+/*
+ * 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, "1000000");
+ const int highFpsLateAppOffsetNs = atoi(value);
+
+ property_get("debug.sf.high_fps_late_sf_phase_offset_ns", value, "8000000");
+ 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
+ : highFpsLateAppOffsetNs,
+ highFpsEarlyAppOffsetNs != -1 ? highFpsEarlyAppOffsetNs
+ : highFpsLateSfOffsetNs};
+ mHighRefreshRateOffsets.earlyGl = {highFpsEarlyGlSfOffsetNs != -1 ? highFpsEarlyGlSfOffsetNs
+ : highFpsLateAppOffsetNs,
+ highFpsEarlyGlAppOffsetNs != -1 ? highFpsEarlyGlAppOffsetNs
+ : highFpsLateSfOffsetNs};
+ mHighRefreshRateOffsets.late = {highFpsLateAppOffsetNs, highFpsLateSfOffsetNs};
+}
+
+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
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.h b/services/surfaceflinger/Scheduler/PhaseOffsets.h
new file mode 100644
index 0000000..cbcaade
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.h
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cinttypes>
+
+#include "RefreshRateConfigs.h"
+#include "VSyncModulator.h"
+
+namespace android {
+namespace scheduler {
+
+/*
+ * This class encapsulates offsets for different refresh rates. Depending
+ * on what refresh rate we are using, and wheter we are composing in GL,
+ * different offsets will help us with latency. This class keeps track of
+ * which mode the device is on, and returns approprate offsets when needed.
+ */
+class PhaseOffsets {
+public:
+ struct Offsets {
+ VSyncModulator::Offsets early;
+ VSyncModulator::Offsets earlyGl;
+ VSyncModulator::Offsets late;
+ };
+
+ virtual ~PhaseOffsets();
+
+ virtual nsecs_t getCurrentAppOffset() = 0;
+ virtual nsecs_t getCurrentSfOffset() = 0;
+ virtual Offsets getCurrentOffsets() const = 0;
+ virtual void setRefreshRateType(RefreshRateConfigs::RefreshRateType refreshRateType) = 0;
+ virtual void dump(std::string& result) const = 0;
+};
+
+namespace impl {
+class PhaseOffsets : public scheduler::PhaseOffsets {
+public:
+ PhaseOffsets();
+
+ nsecs_t getCurrentAppOffset() override;
+ nsecs_t getCurrentSfOffset() override;
+
+ // Returns early, early GL, and late offsets for Apps and SF.
+ Offsets getCurrentOffsets() const override;
+
+ // This function should be called when the device is switching between different
+ // refresh rates, to properly update the offsets.
+ void setRefreshRateType(RefreshRateConfigs::RefreshRateType refreshRateType) override {
+ mRefreshRateType = refreshRateType;
+ }
+
+ // Returns current offsets in human friendly format.
+ void dump(std::string& result) const override;
+
+private:
+ Offsets getmDefaultRefreshRateOffsets() { return mDefaultRefreshRateOffsets; }
+ Offsets getmHighRefreshRateOffsets() { return mHighRefreshRateOffsets; }
+
+ std::atomic<RefreshRateConfigs::RefreshRateType> mRefreshRateType =
+ RefreshRateConfigs::RefreshRateType::DEFAULT;
+
+ Offsets mDefaultRefreshRateOffsets;
+ Offsets mHighRefreshRateOffsets;
+};
+} // namespace impl
+
+} // namespace scheduler
+} // namespace android
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index b003451..00820f1 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -70,7 +70,7 @@
mEventControlThread = std::make_unique<impl::EventControlThread>(function);
char value[PROPERTY_VALUE_MAX];
- property_get("debug.sf.set_idle_timer_ms", value, "0");
+ property_get("debug.sf.set_idle_timer_ms", value, "30");
mSetIdleTimerMs = atoi(value);
if (mSetIdleTimerMs > 0) {
diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.h b/services/surfaceflinger/Scheduler/VSyncModulator.h
index dde0c57..d7ec733 100644
--- a/services/surfaceflinger/Scheduler/VSyncModulator.h
+++ b/services/surfaceflinger/Scheduler/VSyncModulator.h
@@ -18,9 +18,10 @@
#include <utils/Errors.h>
+#include <cinttypes>
#include <mutex>
-using namespace android::surfaceflinger;
+#include "Scheduler.h"
namespace android {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ee202a3..2cf2cd8 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -211,8 +211,6 @@
constexpr float kSrgbWhiteZ = 1.0891f;
// ---------------------------------------------------------------------------
-int64_t SurfaceFlinger::vsyncPhaseOffsetNs;
-int64_t SurfaceFlinger::sfVsyncPhaseOffsetNs;
int64_t SurfaceFlinger::dispSyncPresentTimeOffset;
bool SurfaceFlinger::useHwcForRgbToYuv;
uint64_t SurfaceFlinger::maxVirtualDisplaySize;
@@ -273,6 +271,7 @@
mLayersRemoved(false),
mLayersAdded(false),
mBootTime(systemTime()),
+ mPhaseOffsets{getFactory().createPhaseOffsets()},
mVisibleRegionsDirty(false),
mGeometryInvalid(false),
mAnimCompositionPending(false),
@@ -298,10 +297,6 @@
: SurfaceFlinger(factory, SkipInitialization) {
ALOGI("SurfaceFlinger is starting");
- vsyncPhaseOffsetNs = vsync_event_phase_offset_ns(1000000);
-
- sfVsyncPhaseOffsetNs = vsync_sf_event_phase_offset_ns(1000000);
-
hasSyncFramework = running_without_sync_framework(true);
dispSyncPresentTimeOffset = present_time_offset_from_vsync_ns(0);
@@ -400,29 +395,11 @@
auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize));
mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize;
- 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.use_scheduler", value, "0");
mUseScheduler = atoi(value);
- const VSyncModulator::Offsets earlyOffsets =
- {earlySfOffsetNs != -1 ? earlySfOffsetNs : sfVsyncPhaseOffsetNs,
- earlyAppOffsetNs != -1 ? earlyAppOffsetNs : vsyncPhaseOffsetNs};
- const VSyncModulator::Offsets earlyGlOffsets =
- {earlyGlSfOffsetNs != -1 ? earlyGlSfOffsetNs : sfVsyncPhaseOffsetNs,
- earlyGlAppOffsetNs != -1 ? earlyGlAppOffsetNs : vsyncPhaseOffsetNs};
- mVsyncModulator.setPhaseOffsets(earlyOffsets, earlyGlOffsets,
- {sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs});
+ const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
+ mVsyncModulator.setPhaseOffsets(early, gl, late);
// We should be reading 'persist.sys.sf.color_saturation' here
// but since /data may be encrypted, we need to wait until after vold
@@ -629,7 +606,7 @@
ALOGI( "SurfaceFlinger's main thread ready to run. "
"Initializing graphics H/W...");
- ALOGI("Phase offest NS: %" PRId64 "", vsyncPhaseOffsetNs);
+ ALOGI("Phase offset NS: %" PRId64 "", mPhaseOffsets->getCurrentAppOffset());
Mutex::Autolock _l(mStateLock);
@@ -640,13 +617,17 @@
mScheduler = getFactory().createScheduler([this](bool enabled) {
setVsyncEnabled(EventThread::DisplayType::Primary, enabled);
});
+ // TODO(b/113612090): Currently we assume that if scheduler is turned on, then the refresh
+ // rate is 90. Once b/122905403 is completed, this should be updated accordingly.
+ mPhaseOffsets->setRefreshRateType(
+ scheduler::RefreshRateConfigs::RefreshRateType::PERFORMANCE);
mAppConnectionHandle =
- mScheduler->createConnection("appConnection", SurfaceFlinger::vsyncPhaseOffsetNs,
+ mScheduler->createConnection("appConnection", mPhaseOffsets->getCurrentAppOffset(),
resyncCallback,
impl::EventThread::InterceptVSyncsCallback());
mSfConnectionHandle =
- mScheduler->createConnection("sfConnection", SurfaceFlinger::sfVsyncPhaseOffsetNs,
+ mScheduler->createConnection("sfConnection", mPhaseOffsets->getCurrentSfOffset(),
resyncCallback, [this](nsecs_t timestamp) {
mInterceptor->saveVSyncEvent(timestamp);
});
@@ -657,14 +638,14 @@
} else {
mEventThreadSource =
std::make_unique<DispSyncSource>(mPrimaryDispSync.get(),
- SurfaceFlinger::vsyncPhaseOffsetNs, true, "app");
+ mPhaseOffsets->getCurrentAppOffset(), true, "app");
mEventThread =
std::make_unique<impl::EventThread>(mEventThreadSource.get(),
impl::EventThread::InterceptVSyncsCallback(),
"appEventThread");
mSfEventThreadSource =
std::make_unique<DispSyncSource>(mPrimaryDispSync.get(),
- SurfaceFlinger::sfVsyncPhaseOffsetNs, true, "sf");
+ mPhaseOffsets->getCurrentSfOffset(), true, "sf");
mSFEventThread =
std::make_unique<impl::EventThread>(mSfEventThreadSource.get(),
@@ -745,8 +726,20 @@
}
if (mUseScheduler) {
- mScheduler->setExpiredIdleTimerCallback([this]() { setRefreshRateTo(60.f /* fps */); });
- mScheduler->setResetIdleTimerCallback([this]() { setRefreshRateTo(90.f /* fps */); });
+ mScheduler->setExpiredIdleTimerCallback([this]() {
+ mPhaseOffsets->setRefreshRateType(
+ scheduler::RefreshRateConfigs::RefreshRateType::DEFAULT);
+ const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
+ mVsyncModulator.setPhaseOffsets(early, gl, late);
+ setRefreshRateTo(60.f /* fps */);
+ });
+ mScheduler->setResetIdleTimerCallback([this]() {
+ mPhaseOffsets->setRefreshRateType(
+ scheduler::RefreshRateConfigs::RefreshRateType::PERFORMANCE);
+ const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
+ mVsyncModulator.setPhaseOffsets(early, gl, late);
+ setRefreshRateTo(90.f /* fps */);
+ });
mRefreshRateStats = std::make_unique<scheduler::RefreshRateStats>(
getHwComposer().getConfigs(*display->getId()));
}
@@ -901,7 +894,7 @@
info.xdpi = xdpi;
info.ydpi = ydpi;
info.fps = 1e9 / hwConfig->getVsyncPeriod();
- info.appVsyncOffset = vsyncPhaseOffsetNs;
+ info.appVsyncOffset = mPhaseOffsets->getCurrentAppOffset();
// This is how far in advance a buffer must be queued for
// presentation at a given time. If you want a buffer to appear
@@ -915,8 +908,8 @@
//
// We add an additional 1ms to allow for processing time and
// differences between the ideal and actual refresh rate.
- info.presentationDeadline = hwConfig->getVsyncPeriod() -
- sfVsyncPhaseOffsetNs + 1000000;
+ info.presentationDeadline =
+ hwConfig->getVsyncPeriod() - mPhaseOffsets->getCurrentSfOffset() + 1000000;
// All non-virtual displays are currently considered secure.
info.secure = true;
@@ -1966,11 +1959,11 @@
nsecs_t compositeToPresentLatency) {
// Integer division and modulo round toward 0 not -inf, so we need to
// treat negative and positive offsets differently.
- nsecs_t idealLatency = (sfVsyncPhaseOffsetNs > 0)
- ? (stats.vsyncPeriod - (sfVsyncPhaseOffsetNs % stats.vsyncPeriod))
- : ((-sfVsyncPhaseOffsetNs) % stats.vsyncPeriod);
+ nsecs_t idealLatency = (mPhaseOffsets->getCurrentSfOffset() > 0)
+ ? (stats.vsyncPeriod - (mPhaseOffsets->getCurrentSfOffset() % stats.vsyncPeriod))
+ : ((-mPhaseOffsets->getCurrentSfOffset()) % stats.vsyncPeriod);
- // Just in case sfVsyncPhaseOffsetNs == -vsyncInterval.
+ // Just in case mPhaseOffsets->getCurrentSfOffset() == -vsyncInterval.
if (idealLatency <= 0) {
idealLatency = stats.vsyncPeriod;
}
@@ -1979,7 +1972,7 @@
// composition and present times, which often have >1ms of jitter.
// Reducing jitter is important if an app attempts to extrapolate
// something (such as user input) to an accurate diasplay time.
- // Snapping also allows an app to precisely calculate sfVsyncPhaseOffsetNs
+ // Snapping also allows an app to precisely calculate mPhaseOffsets->getCurrentSfOffset()
// with (presentLatency % interval).
nsecs_t bias = stats.vsyncPeriod / 2;
int64_t extraVsyncs = (compositeToPresentLatency - idealLatency + bias) / stats.vsyncPeriod;
@@ -4520,15 +4513,10 @@
}
void SurfaceFlinger::dumpVSync(std::string& result) const {
- const auto [sfEarlyOffset, appEarlyOffset] = mVsyncModulator.getEarlyOffsets();
- const auto [sfEarlyGlOffset, appEarlyGlOffset] = mVsyncModulator.getEarlyGlOffsets();
+ mPhaseOffsets->dump(result);
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"
" present offset: %9" PRId64 " ns\t VSYNC period: %9" PRId64 " ns\n\n",
- vsyncPhaseOffsetNs, sfVsyncPhaseOffsetNs, appEarlyOffset, sfEarlyOffset,
- appEarlyGlOffset, sfEarlyGlOffset, dispSyncPresentTimeOffset, getVsyncPeriod());
+ dispSyncPresentTimeOffset, getVsyncPeriod());
StringAppendF(&result, "Scheduler: %s\n\n", mUseScheduler ? "enabled" : "disabled");
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index dfb01fb..a48e811 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -59,6 +59,7 @@
#include "Scheduler/DispSync.h"
#include "Scheduler/EventThread.h"
#include "Scheduler/MessageQueue.h"
+#include "Scheduler/PhaseOffsets.h"
#include "Scheduler/RefreshRateStats.h"
#include "Scheduler/Scheduler.h"
#include "Scheduler/VSyncModulator.h"
@@ -952,7 +953,10 @@
std::unique_ptr<EventControlThread> mEventControlThread;
std::unordered_map<DisplayId, sp<IBinder>> mPhysicalDisplayTokens;
+ // Calculates correct offsets.
VSyncModulator mVsyncModulator;
+ // Keeps track of all available phase offsets for different refresh types.
+ std::unique_ptr<scheduler::PhaseOffsets> mPhaseOffsets;
// Can only accessed from the main thread, these members
// don't need synchronization
diff --git a/services/surfaceflinger/SurfaceFlingerFactory.cpp b/services/surfaceflinger/SurfaceFlingerFactory.cpp
index 77679e3..773a5d1 100644
--- a/services/surfaceflinger/SurfaceFlingerFactory.cpp
+++ b/services/surfaceflinger/SurfaceFlingerFactory.cpp
@@ -33,6 +33,7 @@
#include "Scheduler/DispSync.h"
#include "Scheduler/EventControlThread.h"
#include "Scheduler/MessageQueue.h"
+#include "Scheduler/PhaseOffsets.h"
#include "Scheduler/Scheduler.h"
#include "TimeStats/TimeStats.h"
@@ -68,6 +69,10 @@
return std::make_unique<android::impl::MessageQueue>();
}
+ std::unique_ptr<scheduler::PhaseOffsets> createPhaseOffsets() override {
+ return std::make_unique<scheduler::impl::PhaseOffsets>();
+ }
+
std::unique_ptr<Scheduler> createScheduler(std::function<void(bool)> callback) override {
return std::make_unique<Scheduler>(callback);
}
diff --git a/services/surfaceflinger/SurfaceFlingerFactory.h b/services/surfaceflinger/SurfaceFlingerFactory.h
index f747684..ac99e2a 100644
--- a/services/surfaceflinger/SurfaceFlingerFactory.h
+++ b/services/surfaceflinger/SurfaceFlingerFactory.h
@@ -52,6 +52,10 @@
namespace compositionengine {
class CompositionEngine;
} // namespace compositionengine
+
+namespace scheduler {
+class PhaseOffsets;
+} // namespace scheduler
namespace surfaceflinger {
class NativeWindowSurface;
@@ -66,6 +70,7 @@
std::function<void(bool)> setVSyncEnabled) = 0;
virtual std::unique_ptr<HWComposer> createHWComposer(const std::string& serviceName) = 0;
virtual std::unique_ptr<MessageQueue> createMessageQueue() = 0;
+ virtual std::unique_ptr<scheduler::PhaseOffsets> createPhaseOffsets() = 0;
virtual std::unique_ptr<Scheduler> createScheduler(std::function<void(bool)> callback) = 0;
virtual std::unique_ptr<SurfaceInterceptor> createSurfaceInterceptor(SurfaceFlinger*) = 0;
diff --git a/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
new file mode 100644
index 0000000..0739f15
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <gmock/gmock.h>
+
+#include "Scheduler/PhaseOffsets.h"
+
+namespace android {
+namespace scheduler {
+
+class FakePhaseOffsets : public android::scheduler::PhaseOffsets {
+ nsecs_t FAKE_PHASE_OFFSET_NS = 0;
+
+public:
+ FakePhaseOffsets() = default;
+ ~FakePhaseOffsets() = default;
+
+ nsecs_t getCurrentAppOffset() override { return FAKE_PHASE_OFFSET_NS; }
+ nsecs_t getCurrentSfOffset() override { return FAKE_PHASE_OFFSET_NS; }
+
+ // Returns early, early GL, and late offsets for Apps and SF.
+ PhaseOffsets::Offsets getCurrentOffsets() const override {
+ return Offsets{{FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS},
+ {FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS},
+ {FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS}};
+ }
+
+ // This function should be called when the device is switching between different
+ // refresh rates, to properly update the offsets.
+ void setRefreshRateType(RefreshRateConfigs::RefreshRateType /*refreshRateType*/) override {}
+
+ // Returns current offsets in human friendly format.
+ void dump(std::string& /*result*/) const override {}
+};
+
+} // namespace scheduler
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index b9b0cf8..3a62c40 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -23,6 +23,7 @@
#include "ColorLayer.h"
#include "ContainerLayer.h"
#include "DisplayDevice.h"
+#include "FakePhaseOffsets.h"
#include "Layer.h"
#include "NativeWindowSurface.h"
#include "StartPropertySetThread.h"
@@ -75,6 +76,10 @@
return std::make_unique<android::impl::MessageQueue>();
}
+ std::unique_ptr<scheduler::PhaseOffsets> createPhaseOffsets() override {
+ return std::make_unique<scheduler::FakePhaseOffsets>();
+ }
+
std::unique_ptr<Scheduler> createScheduler(std::function<void(bool)>) override {
// TODO: Use test-fixture controlled factory
return nullptr;