Merge "ProjectionSpace fixes for caching:" into sc-dev
diff --git a/include/android/imagedecoder.h b/include/android/imagedecoder.h
index 8d1bf99..c3d3a4b 100644
--- a/include/android/imagedecoder.h
+++ b/include/android/imagedecoder.h
@@ -739,6 +739,9 @@
* skipping frames in an image with such frames may not produce the correct
* results.
*
+ * Only supported by {@link ANDROID_BITMAP_FORMAT_RGBA_8888} and
+ * {@link ANDROID_BITMAP_FORMAT_RGBA_F16}.
+ *
* @param decoder an {@link AImageDecoder} object.
* @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value
* indicating the reason for the failure.
@@ -747,6 +750,8 @@
* - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The AImageDecoder
* represents an image that is not animated (see
* {@link AImageDecoder_isAnimated}) or the AImageDecoder is null.
+ * - {@link ANDROID_IMAGE_DECODER_INVALID_STATE): The requested
+ * {@link AndroidBitmapFormat} does not support animation.
* - {@link ANDROID_IMAGE_DECODER_INCOMPLETE}: The input appears
* to be truncated. The client must call {@link AImageDecoder_rewind}
* before calling {@link AImageDecoder_decodeImage} again.
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index b7eafcd..f6c2e55 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -534,11 +534,12 @@
*
* \param compatibility The frame rate compatibility of this surface. The compatibility value may
* influence the system's choice of display frame rate. To specify a compatibility use the
- * ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* enum.
+ * ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* enum. This parameter is ignored when frameRate is 0.
*
- * \param changeFrameRateStrategy Whether display refresh rate transitions should be seamless.
- * A seamless transition is one that doesn't have any visual interruptions, such as a black
- * screen for a second or two. See the ANATIVEWINDOW_CHANGE_FRAME_RATE_* values.
+ * \param changeFrameRateStrategy Whether display refresh rate transitions caused by this
+ * surface should be seamless. A seamless transition is one that doesn't have any visual
+ * interruptions, such as a black screen for a second or two. See the
+ * ANATIVEWINDOW_CHANGE_FRAME_RATE_* values. This parameter is ignored when frameRate is 0.
*
* Available since API level 31.
*/
diff --git a/libs/binder/PermissionCache.cpp b/libs/binder/PermissionCache.cpp
index 6eae5ef..670fd55 100644
--- a/libs/binder/PermissionCache.cpp
+++ b/libs/binder/PermissionCache.cpp
@@ -109,5 +109,10 @@
return granted;
}
+void PermissionCache::purgeCache() {
+ PermissionCache& pc(PermissionCache::getInstance());
+ pc.purge();
+}
+
// ---------------------------------------------------------------------------
} // namespace android
diff --git a/libs/binder/RpcConnection.cpp b/libs/binder/RpcConnection.cpp
index 1388a80..f2302f7 100644
--- a/libs/binder/RpcConnection.cpp
+++ b/libs/binder/RpcConnection.cpp
@@ -130,24 +130,21 @@
#endif // __BIONIC__
-class SocketAddressImpl : public RpcConnection::SocketAddress {
+class InetSocketAddress : public RpcConnection::SocketAddress {
public:
- SocketAddressImpl(const sockaddr* addr, size_t size, const String8& desc)
- : mAddr(addr), mSize(size), mDesc(desc) {}
+ InetSocketAddress(const sockaddr* sockAddr, size_t size, const char* addr, unsigned int port)
+ : mSockAddr(sockAddr), mSize(size), mAddr(addr), mPort(port) {}
[[nodiscard]] std::string toString() const override {
- return std::string(mDesc.c_str(), mDesc.size());
+ return String8::format("%s:%u", mAddr, mPort).c_str();
}
- [[nodiscard]] const sockaddr* addr() const override { return mAddr; }
+ [[nodiscard]] const sockaddr* addr() const override { return mSockAddr; }
[[nodiscard]] size_t addrSize() const override { return mSize; }
- void set(const sockaddr* addr, size_t size) {
- mAddr = addr;
- mSize = size;
- }
private:
- const sockaddr* mAddr = nullptr;
- size_t mSize = 0;
- String8 mDesc;
+ const sockaddr* mSockAddr;
+ size_t mSize;
+ const char* mAddr;
+ unsigned int mPort;
};
AddrInfo GetAddrInfo(const char* addr, unsigned int port) {
@@ -170,14 +167,15 @@
}
bool RpcConnection::setupInetServer(unsigned int port) {
- auto aiStart = GetAddrInfo("127.0.0.1", port);
+ const char* kAddr = "127.0.0.1";
+
+ auto aiStart = GetAddrInfo(kAddr, port);
if (aiStart == nullptr) return false;
- SocketAddressImpl socketAddress(nullptr, 0, String8::format("127.0.0.1:%u", port));
for (auto ai = aiStart.get(); ai != nullptr; ai = ai->ai_next) {
- socketAddress.set(ai->ai_addr, ai->ai_addrlen);
+ InetSocketAddress socketAddress(ai->ai_addr, ai->ai_addrlen, kAddr, port);
if (setupSocketServer(socketAddress)) return true;
}
- ALOGE("None of the socket address resolved for 127.0.0.1:%u can be set up as inet server.",
+ ALOGE("None of the socket address resolved for %s:%u can be set up as inet server.", kAddr,
port);
return false;
}
@@ -185,9 +183,8 @@
bool RpcConnection::addInetClient(const char* addr, unsigned int port) {
auto aiStart = GetAddrInfo(addr, port);
if (aiStart == nullptr) return false;
- SocketAddressImpl socketAddress(nullptr, 0, String8::format("%s:%u", addr, port));
for (auto ai = aiStart.get(); ai != nullptr; ai = ai->ai_next) {
- socketAddress.set(ai->ai_addr, ai->ai_addrlen);
+ InetSocketAddress socketAddress(ai->ai_addr, ai->ai_addrlen, addr, port);
if (addSocketClient(socketAddress)) return true;
}
ALOGE("None of the socket address resolved for %s:%u can be added as inet client.", addr, port);
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index 1fa37ba..9a0be92 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -30,8 +30,6 @@
namespace android {
-using base::unique_fd;
-
RpcServer::RpcServer() {}
RpcServer::~RpcServer() {}
@@ -48,16 +46,20 @@
auto connection = RpcConnection::make();
connection->setForServer(sp<RpcServer>::fromExisting(this));
- mConnections.push_back(connection);
+ {
+ std::lock_guard<std::mutex> _l(mLock);
+ mConnections.push_back(connection);
+ }
return connection;
}
void RpcServer::setRootObject(const sp<IBinder>& binder) {
- LOG_ALWAYS_FATAL_IF(mRootObject != nullptr, "There can only be one root object");
+ std::lock_guard<std::mutex> _l(mLock);
mRootObject = binder;
}
sp<IBinder> RpcServer::getRootObject() {
+ std::lock_guard<std::mutex> _l(mLock);
return mRootObject;
}
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index 31f63c8..52f221d 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -49,39 +49,39 @@
{
public:
enum {
- FIRST_CALL_TRANSACTION = 0x00000001,
- LAST_CALL_TRANSACTION = 0x00ffffff,
+ FIRST_CALL_TRANSACTION = 0x00000001,
+ LAST_CALL_TRANSACTION = 0x00ffffff,
- PING_TRANSACTION = B_PACK_CHARS('_','P','N','G'),
- DUMP_TRANSACTION = B_PACK_CHARS('_','D','M','P'),
- SHELL_COMMAND_TRANSACTION = B_PACK_CHARS('_','C','M','D'),
- INTERFACE_TRANSACTION = B_PACK_CHARS('_', 'N', 'T', 'F'),
- SYSPROPS_TRANSACTION = B_PACK_CHARS('_', 'S', 'P', 'R'),
- EXTENSION_TRANSACTION = B_PACK_CHARS('_', 'E', 'X', 'T'),
- DEBUG_PID_TRANSACTION = B_PACK_CHARS('_', 'P', 'I', 'D'),
+ PING_TRANSACTION = B_PACK_CHARS('_', 'P', 'N', 'G'),
+ DUMP_TRANSACTION = B_PACK_CHARS('_', 'D', 'M', 'P'),
+ SHELL_COMMAND_TRANSACTION = B_PACK_CHARS('_', 'C', 'M', 'D'),
+ INTERFACE_TRANSACTION = B_PACK_CHARS('_', 'N', 'T', 'F'),
+ SYSPROPS_TRANSACTION = B_PACK_CHARS('_', 'S', 'P', 'R'),
+ EXTENSION_TRANSACTION = B_PACK_CHARS('_', 'E', 'X', 'T'),
+ DEBUG_PID_TRANSACTION = B_PACK_CHARS('_', 'P', 'I', 'D'),
// See android.os.IBinder.TWEET_TRANSACTION
// Most importantly, messages can be anything not exceeding 130 UTF-8
// characters, and callees should exclaim "jolly good message old boy!"
- TWEET_TRANSACTION = B_PACK_CHARS('_', 'T', 'W', 'T'),
+ TWEET_TRANSACTION = B_PACK_CHARS('_', 'T', 'W', 'T'),
// See android.os.IBinder.LIKE_TRANSACTION
// Improve binder self-esteem.
- LIKE_TRANSACTION = B_PACK_CHARS('_', 'L', 'I', 'K'),
+ LIKE_TRANSACTION = B_PACK_CHARS('_', 'L', 'I', 'K'),
// Corresponds to TF_ONE_WAY -- an asynchronous call.
- FLAG_ONEWAY = 0x00000001,
+ FLAG_ONEWAY = 0x00000001,
// Corresponds to TF_CLEAR_BUF -- clear transaction buffers after call
// is made
- FLAG_CLEAR_BUF = 0x00000020,
+ FLAG_CLEAR_BUF = 0x00000020,
// Private userspace flag for transaction which is being requested from
// a vendor context.
- FLAG_PRIVATE_VENDOR = 0x10000000,
+ FLAG_PRIVATE_VENDOR = 0x10000000,
};
- IBinder();
+ IBinder();
/**
* Check if this IBinder implements the interface named by
diff --git a/libs/binder/include/binder/PermissionCache.h b/libs/binder/include/binder/PermissionCache.h
index 835a3a8..21aa705 100644
--- a/libs/binder/include/binder/PermissionCache.h
+++ b/libs/binder/include/binder/PermissionCache.h
@@ -73,6 +73,8 @@
static bool checkPermission(const String16& permission,
pid_t pid, uid_t uid);
+
+ static void purgeCache();
};
// ---------------------------------------------------------------------------
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index d29b651..a665fad 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -21,6 +21,8 @@
#include <utils/Errors.h>
#include <utils/RefBase.h>
+#include <mutex>
+
// WARNING: This is a feature which is still in development, and it is subject
// to radical change. Any production use of this may subject your code to any
// number of problems.
@@ -30,9 +32,6 @@
/**
* This represents a server of an interface, which may be connected to by any
* number of clients over sockets.
- *
- * This object is not (currently) thread safe. All calls to it are expected to
- * happen at process startup.
*/
class RpcServer final : public virtual RefBase {
public:
@@ -51,16 +50,8 @@
sp<RpcConnection> addClientConnection();
/**
- * Allowing a server to explicitly drop clients would be easy to add here,
- * but it is not currently implemented, since users of this functionality
- * could not use similar functionality if they are running under real
- * binder.
- */
- // void drop(const sp<RpcConnection>& connection);
-
- /**
* The root object can be retrieved by any client, without any
- * authentication.
+ * authentication. TODO(b/183988761)
*/
void setRootObject(const sp<IBinder>& binder);
@@ -77,8 +68,8 @@
bool mAgreedExperimental = false;
+ std::mutex mLock;
sp<IBinder> mRootObject;
-
std::vector<sp<RpcConnection>> mConnections; // per-client
};
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index eb103d3..b03e24c 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -55,7 +55,9 @@
defaults: ["libbinder_ndk_host_user"],
host_supported: true,
- llndk_stubs: "libbinder_ndk.llndk",
+ llndk: {
+ symbol_file: "libbinder_ndk.map.txt",
+ },
export_include_dirs: [
"include_cpp",
@@ -192,13 +194,3 @@
symbol_file: "libbinder_ndk.map.txt",
first_version: "29",
}
-
-llndk_library {
- name: "libbinder_ndk.llndk",
- symbol_file: "libbinder_ndk.map.txt",
- export_include_dirs: [
- "include_cpp",
- "include_ndk",
- "include_platform",
- ],
-}
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index f303b7c..c0f7c99 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -35,6 +35,7 @@
name: "binderDriverInterfaceTest_IPC_32",
defaults: ["binder_test_defaults"],
srcs: ["binderDriverInterfaceTest.cpp"],
+ header_libs: ["libbinder_headers"],
compile_multilib: "32",
multilib: { lib32: { suffix: "" } },
cflags: ["-DBINDER_IPC_32BIT=1"],
@@ -49,7 +50,7 @@
cflags: ["-DBINDER_IPC_32BIT=1"],
},
},
-
+ header_libs: ["libbinder_headers"],
srcs: ["binderDriverInterfaceTest.cpp"],
test_suites: ["device-tests", "vts"],
}
diff --git a/libs/gui/include/gui/JankInfo.h b/libs/gui/include/gui/JankInfo.h
index 85ae9cb..ce9716f 100644
--- a/libs/gui/include/gui/JankInfo.h
+++ b/libs/gui/include/gui/JankInfo.h
@@ -42,6 +42,10 @@
BufferStuffing = 0x40,
// Jank due to unknown reasons.
Unknown = 0x80,
+ // SF is said to be stuffed if the previous frame ran longer than expected resulting in the case
+ // where the previous frame was presented in the current frame's expected vsync. This pushes the
+ // current frame to the next vsync. The behavior is similar to BufferStuffing.
+ SurfaceFlingerStuffing = 0x100,
};
} // namespace android
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index 8675439..9286009 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -60,7 +60,13 @@
cc_library {
name: "libnativewindow",
- llndk_stubs: "libnativewindow.llndk",
+ llndk: {
+ symbol_file: "libnativewindow.map.txt",
+ unversioned: true,
+ override_export_include_dirs: [
+ "include"
+ ],
+ },
export_include_dirs: [
"include",
"include-private",
@@ -115,11 +121,4 @@
},
}
-llndk_library {
- name: "libnativewindow.llndk",
- symbol_file: "libnativewindow.map.txt",
- unversioned: true,
- export_include_dirs: ["include"],
-}
-
subdirs = ["tests"]
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index 61b3f94..3865ba5 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -302,6 +302,8 @@
*
* Available since API level 31.
*
+ * \param window pointer to an ANativeWindow object.
+ *
* \param frameRate The intended frame rate of this window, in frames per
* second. 0 is a special value that indicates the app will accept the system's
* choice for the display frame rate, which is the default behavior if this
@@ -309,15 +311,16 @@
* valid refresh rate for this device's display - e.g., it's fine to pass 30fps
* to a device that can only run the display at 60fps.
*
- * \param window pointer to an ANativeWindow object.
- *
* \param compatibility The frame rate compatibility of this window. The
* compatibility value may influence the system's choice of display refresh
* rate. See the ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* values for more info.
+ * This parameter is ignored when frameRate is 0.
*
- * \param changeFrameRateStrategy Whether display refresh rate transitions should be seamless.
+ * \param changeFrameRateStrategy Whether display refresh rate transitions caused by this
+ * window should be seamless.
* A seamless transition is one that doesn't have any visual interruptions, such as a black
* screen for a second or two. See the ANATIVEWINDOW_CHANGE_FRAME_RATE_* values.
+ * This parameter is ignored when frameRate is 0.
*
* \return 0 for success, -EINVAL if the window, frame rate, or compatibility
* value are invalid.
diff --git a/libs/permission/Android.bp b/libs/permission/Android.bp
index 1ae0a00..a5712b3 100644
--- a/libs/permission/Android.bp
+++ b/libs/permission/Android.bp
@@ -7,42 +7,17 @@
default_applicable_licenses: ["frameworks_native_license"],
}
-aidl_interface {
- name: "framework-permission-aidl",
- unstable: true,
- local_include_dir: "aidl",
- backend: {
- ndk: {
- enabled: false
- }
- },
- srcs: [
- "aidl/android/content/AttributionSourceState.aidl",
- "aidl/android/permission/IPermissionChecker.aidl",
- ],
-}
-
cc_library_shared {
name: "libpermission",
- cflags: [
- "-Wall",
- "-Wextra",
- "-Werror",
- ],
srcs: [
"AppOpsManager.cpp",
"IAppOpsCallback.cpp",
"IAppOpsService.cpp",
- "android/permission/PermissionChecker.cpp",
],
export_include_dirs: ["include"],
shared_libs: [
- "libutils",
"libbinder",
- "libcutils",
"liblog",
- ],
- static_libs: [
- "framework-permission-aidl-cpp",
+ "libutils",
],
}
diff --git a/libs/permission/aidl/android/content/AttributionSourceState.aidl b/libs/permission/aidl/android/content/AttributionSourceState.aidl
deleted file mode 100644
index b6e54bf..0000000
--- a/libs/permission/aidl/android/content/AttributionSourceState.aidl
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-package android.content;
-
-/**
- * Payload for the {@link AttributionSource} class needed to interoperate
- * with different languages.
- *
- * {@hide}
- */
-parcelable AttributionSourceState {
- /** The UID that is accessing the permission protected data. */
- int uid;
- /** The package that is accessing the permission protected data. */
- @nullable @utf8InCpp String packageName;
- /** The attribution tag of the app accessing the permission protected data. */
- @nullable @utf8InCpp String attributionTag;
- /** Unique token for that source. */
- @nullable IBinder token;
- /** Permissions that should be considered revoked regardless if granted. */
- @nullable @utf8InCpp String[] renouncedPermissions;
- /** The next app to receive the permission protected data. */
- // TODO: We use an array as a workaround - the C++ backend doesn't
- // support referring to the parcelable as it expects ctor/dtor
- @nullable AttributionSourceState[] next;
-}
diff --git a/libs/permission/aidl/android/permission/IPermissionChecker.aidl b/libs/permission/aidl/android/permission/IPermissionChecker.aidl
deleted file mode 100644
index 1f0e32d..0000000
--- a/libs/permission/aidl/android/permission/IPermissionChecker.aidl
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-package android.permission;
-
-import android.content.AttributionSourceState;
-
-/**
- * Interface to communicate directly with the permission checker service.
- */
-interface IPermissionChecker {
- const int PERMISSION_GRANTED = 0;
- const int PERMISSION_SOFT_DENIED = 1;
- const int PERMISSION_HARD_DENIED = 2;
-
- int checkPermission(String permission, in AttributionSourceState attributionSource,
- @nullable String message, boolean forDataDelivery, boolean startDataDelivery,
- boolean fromDatasource);
-
- void finishDataDelivery(String op, in AttributionSourceState attributionSource);
-
- int checkOp(int op, in AttributionSourceState attributionSource,
- String message, boolean forDataDelivery, boolean startDataDelivery);
-}
diff --git a/libs/permission/android/permission/PermissionChecker.cpp b/libs/permission/android/permission/PermissionChecker.cpp
deleted file mode 100644
index a8083ee..0000000
--- a/libs/permission/android/permission/PermissionChecker.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 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.
- */
-
-#include <mutex>
-#include <include/android/permission/PermissionChecker.h>
-#include <binder/Binder.h>
-#include <binder/IServiceManager.h>
-
-#include <utils/SystemClock.h>
-
-#include <sys/types.h>
-#include <private/android_filesystem_config.h>
-
-#ifdef LOG_TAG
-#undef LOG_TAG
-#endif
-#define LOG_TAG "PermissionChecker"
-
-namespace android {
-
-using android::content::AttributionSourceState;
-
-PermissionChecker::PermissionChecker()
-{
-}
-
-sp<IPermissionChecker> PermissionChecker::getService()
-{
- static String16 permission_checker("permission_checker");
-
- std::lock_guard<Mutex> scoped_lock(mLock);
- int64_t startTime = 0;
- sp<IPermissionChecker> service = mService;
- while (service == nullptr || !IInterface::asBinder(service)->isBinderAlive()) {
- sp<IBinder> binder = defaultServiceManager()->checkService(permission_checker);
- if (binder == nullptr) {
- // Wait for the permission checker service to come back...
- if (startTime == 0) {
- startTime = uptimeMillis();
- ALOGW("Waiting for permission checker service");
- } else if ((uptimeMillis() - startTime) > 10000) {
- ALOGE("Waiting too long for permission checker service, giving up");
- service = nullptr;
- break;
- }
- sleep(1);
- } else {
- mService = interface_cast<IPermissionChecker>(binder);
- }
- }
- return mService;
-}
-
-PermissionChecker::PermissionResult
- PermissionChecker::checkPermissionForDataDeliveryFromDatasource(
- const String16& permission, AttributionSourceState& attributionSource,
- const String16& message)
-{
- return static_cast<PermissionResult>(checkPermission(permission, attributionSource, message,
- /*forDataDelivery*/ true, /*startDataDelivery*/ false,/*fromDatasource*/ true));
-}
-
-PermissionChecker::PermissionResult
- PermissionChecker::checkPermissionForStartDataDeliveryFromDatasource(
- const String16& permission, AttributionSourceState& attributionSource,
- const String16& message)
-{
- return static_cast<PermissionResult>(checkPermission(permission, attributionSource, message,
- /*forDataDelivery*/ true, /*startDataDelivery*/ true, /*fromDatasource*/ true));
-}
-
-void PermissionChecker::finishDataDelivery(const String16& op,
- AttributionSourceState& attributionSource)
-{
- sp<IPermissionChecker> service = getService();
- if (service != nullptr) {
- binder::Status status = service->finishDataDelivery(op, attributionSource);
- if (!status.isOk()) {
- ALOGE("finishDataDelivery failed: %s", status.exceptionMessage().c_str());
- }
- }
-}
-
-int32_t PermissionChecker::checkPermission(const String16& permission,
- AttributionSourceState& attributionSource, const String16& message,
- bool forDataDelivery, bool startDataDelivery, bool fromDatasource)
-{
- sp<IPermissionChecker> service = getService();
- if (service != nullptr) {
- int32_t result;
- binder::Status status = service->checkPermission(permission, attributionSource, message,
- forDataDelivery, startDataDelivery, fromDatasource, &result);
- if (status.isOk()) {
- return result;
- }
- ALOGE("checkPermission failed: %s", status.exceptionMessage().c_str());
- }
- return PERMISSION_DENIED;
-}
-
-} // namespace android
diff --git a/libs/permission/include/android/permission/PermissionChecker.h b/libs/permission/include/android/permission/PermissionChecker.h
deleted file mode 100644
index 20ab51f..0000000
--- a/libs/permission/include/android/permission/PermissionChecker.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright (C) 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 <android/content/AttributionSourceState.h>
-#include <android/permission/IPermissionChecker.h>
-
-#include <utils/threads.h>
-
-#include <optional>
-
-#ifdef __ANDROID_VNDK__
-#error "This header is not visible to vendors"
-#endif
-
-// ---------------------------------------------------------------------------
-namespace android {
-
-using android::content::AttributionSourceState;
-using android::permission::IPermissionChecker;
-
-class PermissionChecker
-{
-public:
-
- enum PermissionResult {
-
- /**
- * The permission is granted.
- */
- PERMISSION_GRANTED = IPermissionChecker::PERMISSION_GRANTED,
-
- /**
- * The permission is denied. Applicable only to runtime and app op permissions.
- *
- * Returned when:
- * - the runtime permission is granted, but the corresponding app op is denied
- * for runtime permissions.
- * - the app ops is ignored for app op permissions.
- *
- */
- PERMISSION_SOFT_DENIED = IPermissionChecker::PERMISSION_SOFT_DENIED,
-
- /**
- * The permission is denied.
- *
- * Returned when:
- * - the permission is denied for non app op permissions.
- * - the app op is denied or app op is AppOpsManager#MODE_DEFAULT and permission is denied.
- */
- PERMISSION_HARD_DENIED = IPermissionChecker::PERMISSION_HARD_DENIED
- };
-
- PermissionChecker();
-
- /**
- * Checks whether a given data access chain described by the given attribution source
- * has a given permission and whether the app op that corresponds to this permission
- * is allowed. Call this method if you are the datasource which would not blame you for
- * access to the data since you are the data. Note that the attribution source chain
- *
- * NOTE: The attribution source should be for yourself with its next attribution
- * source being the app that would receive the data from you.
- *
- * NOTE: Use this method only for permission checks at the point where you will deliver
- * the permission protected data to clients.
- *
- * @param permission The permission to check.
- * @param attributionSource The attribution chain to check.
- * @param message A message describing the reason the permission was checked.
- * @return The permission check result which is either PERMISSION_GRANTED,
- * or PERMISSION_SOFT_DENIED or PERMISSION_HARD_DENIED.
- */
- PermissionChecker::PermissionResult checkPermissionForDataDeliveryFromDatasource(
- const String16& permission, AttributionSourceState& attributionSource,
- const String16& message);
-
- /**
- * Checks whether a given data access chain described by the given attribution source
- * has a given permission and whether the app op that corresponds to this permission
- * is allowed. The app ops are also marked as started. This is useful for long running
- * permissions like camera and microphone.
- *
- * NOTE: The attribution source should be for yourself with its next attribution
- * source being the app that would receive the data from you.
- *
- * NOTE: Use this method only for permission checks at the point where you will deliver
- * the permission protected data to clients.
- *
- * @param permission The permission to check.
- * @param attributionSource The attribution chain to check.
- * @param message A message describing the reason the permission was checked.
- * @return The permission check result which is either PERMISSION_GRANTED,
- * or PERMISSION_SOFT_DENIED or PERMISSION_HARD_DENIED.
- */
- PermissionResult checkPermissionForStartDataDeliveryFromDatasource(
- const String16& permission, AttributionSourceState& attributionSource,
- const String16& message);
-
- /**
- * Finishes an ongoing op for data access chain described by the given
- * attribution source.
- *
- * @param op The op to finish.
- * @param attributionSource The attribution chain for which to finish data delivery.
- */
- void finishDataDelivery(const String16& op, AttributionSourceState& attributionSource);
-
-private:
- Mutex mLock;
- sp<IPermissionChecker> mService;
- sp<IPermissionChecker> getService();
-
- int32_t checkPermission(const String16& permission, AttributionSourceState& attributionSource,
- const String16& message, bool forDataDelivery, bool startDataDelivery,
- bool fromDatasource);
-};
-
-
-} // namespace android
-
-// ---------------------------------------------------------------------------
diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp
index 1c2b2fc..a0da888 100644
--- a/libs/renderengine/skia/Cache.cpp
+++ b/libs/renderengine/skia/Cache.cpp
@@ -37,12 +37,17 @@
0.f, 0.7f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
67.3f, 52.2f, 0.f, 1.f);
+const auto kScaleYOnly = mat4(1.f, 0.f, 0.f, 0.f,
+ 0.f, 0.7f, 0.f, 0.f,
+ 0.f, 0.f, 1.f, 0.f,
+ 0.f, 0.f, 0.f, 1.f);
// clang-format on
// When choosing dataspaces below, whether the match the destination or not determined whether
// a color correction effect is added to the shader. There may be other additional shader details
// for particular color spaces.
// TODO(b/184842383) figure out which color related shaders are necessary
constexpr auto kDestDataSpace = ui::Dataspace::SRGB;
+constexpr auto kOtherDataSpace = ui::Dataspace::DISPLAY_P3;
} // namespace
static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
@@ -182,6 +187,37 @@
}
}
+static void drawTextureScaleLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
+ const std::shared_ptr<ExternalTexture>& dstTexture,
+ const std::shared_ptr<ExternalTexture>& srcTexture) {
+ const Rect& displayRect = display.physicalDisplay;
+ FloatRect rect(0, 0, displayRect.width(), displayRect.height());
+ LayerSettings layer{
+ .geometry =
+ Geometry{
+ .boundaries = rect,
+ .roundedCornersCrop = rect,
+ .positionTransform = kScaleAndTranslate,
+ .roundedCornersRadius = 300,
+ },
+ .source = PixelSource{.buffer =
+ Buffer{
+ .buffer = srcTexture,
+ .maxMasteringLuminance = 1000.f,
+ .maxContentLuminance = 1000.f,
+ .textureTransform = kScaleYOnly,
+ }},
+ .sourceDataspace = kOtherDataSpace,
+ };
+
+ auto layers = std::vector<const LayerSettings*>{&layer};
+ for (float alpha : {0.5f, 1.f}) {
+ layer.alpha = alpha,
+ renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache,
+ base::unique_fd(), nullptr);
+ }
+}
+
//
// The collection of shaders cached here were found by using perfetto to record shader compiles
// during actions that involve RenderEngine, logging the layer settings, and the shader code
@@ -250,6 +286,9 @@
// between 6 and 8 will occur in real uses.
drawImageLayers(renderengine, display, dstTexture, externalTexture);
+ // Draw layers for b/185569240.
+ drawTextureScaleLayers(renderengine, display, dstTexture, externalTexture);
+
const nsecs_t timeAfter = systemTime();
const float compileTimeMs = static_cast<float>(timeAfter - timeBefore) / 1.0E6;
const int shadersCompiled = renderengine->reportShadersCompiled();
diff --git a/libs/renderengine/skia/filters/BlurFilter.cpp b/libs/renderengine/skia/filters/BlurFilter.cpp
index 6dd4161..2028def 100644
--- a/libs/renderengine/skia/filters/BlurFilter.cpp
+++ b/libs/renderengine/skia/filters/BlurFilter.cpp
@@ -53,7 +53,7 @@
}
)");
- auto [blurEffect, error] = SkRuntimeEffect::Make(blurString);
+ auto [blurEffect, error] = SkRuntimeEffect::MakeForShader(blurString);
if (!blurEffect) {
LOG_ALWAYS_FATAL("RuntimeShader error: %s", error.c_str());
}
@@ -65,11 +65,11 @@
uniform float mixFactor;
half4 main(float2 xy) {
- return half4(mix(sample(originalInput), sample(blurredInput), mixFactor));
+ return half4(mix(sample(originalInput, xy), sample(blurredInput, xy), mixFactor));
}
)");
- auto [mixEffect, mixError] = SkRuntimeEffect::Make(mixString);
+ auto [mixEffect, mixError] = SkRuntimeEffect::MakeForShader(mixString);
if (!mixEffect) {
LOG_ALWAYS_FATAL("RuntimeShader error: %s", mixError.c_str());
}
diff --git a/libs/renderengine/skia/filters/LinearEffect.cpp b/libs/renderengine/skia/filters/LinearEffect.cpp
index 8e8e42e..0fbd669 100644
--- a/libs/renderengine/skia/filters/LinearEffect.cpp
+++ b/libs/renderengine/skia/filters/LinearEffect.cpp
@@ -438,7 +438,7 @@
generateOETF(linearEffect.outputDataspace, shaderString);
generateEffectiveOOTF(linearEffect.undoPremultipliedAlpha, shaderString);
- auto [shader, error] = SkRuntimeEffect::Make(shaderString);
+ auto [shader, error] = SkRuntimeEffect::MakeForShader(shaderString);
if (!shader) {
LOG_ALWAYS_FATAL("LinearColorFilter construction error: %s", error.c_str());
}
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 7861d62..4146764 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -137,7 +137,12 @@
cc_library_shared {
name: "libEGL",
defaults: ["egl_libs_defaults"],
- llndk_stubs: "libEGL.llndk",
+ llndk: {
+ symbol_file: "libEGL.map.txt",
+ export_llndk_headers: ["gl_llndk_headers"],
+ // Don't export EGL/include from the LLNDK variant.
+ override_export_include_dirs: [],
+ },
srcs: [
"EGL/egl_tls.cpp",
"EGL/egl_cache.cpp",
@@ -203,7 +208,12 @@
cc_library_shared {
name: "libGLESv1_CM",
defaults: ["gles_libs_defaults"],
- llndk_stubs: "libGLESv1_CM.llndk",
+ llndk: {
+ symbol_file: "libGLESv1_CM.map.txt",
+ export_llndk_headers: ["gl_llndk_headers"],
+ // Don't export EGL/include from the LLNDK variant.
+ override_export_include_dirs: [],
+ },
srcs: ["GLES_CM/gl.cpp"],
cflags: ["-DLOG_TAG=\"libGLESv1\""],
version_script: "libGLESv1_CM.map.txt",
@@ -215,7 +225,12 @@
cc_library_shared {
name: "libGLESv2",
defaults: ["gles_libs_defaults"],
- llndk_stubs: "libGLESv2.llndk",
+ llndk: {
+ symbol_file: "libGLESv2.map.txt",
+ export_llndk_headers: ["gl_llndk_headers"],
+ // Don't export EGL/include from the LLNDK variant.
+ override_export_include_dirs: [],
+ },
srcs: ["GLES2/gl2.cpp"],
cflags: ["-DLOG_TAG=\"libGLESv2\""],
@@ -230,31 +245,12 @@
cc_library_shared {
name: "libGLESv3",
defaults: ["gles_libs_defaults"],
- llndk_stubs: "libGLESv3.llndk",
+ llndk: {
+ symbol_file: "libGLESv3.map.txt",
+ export_llndk_headers: ["gl_llndk_headers"],
+ // Don't export EGL/include from the LLNDK variant.
+ override_export_include_dirs: [],
+ },
srcs: ["GLES2/gl2.cpp"],
cflags: ["-DLOG_TAG=\"libGLESv3\""],
}
-
-llndk_library {
- name: "libEGL.llndk",
- symbol_file: "libEGL.map.txt",
- export_llndk_headers: ["gl_llndk_headers"],
-}
-
-llndk_library {
- name: "libGLESv1_CM.llndk",
- symbol_file: "libGLESv1_CM.map.txt",
- export_llndk_headers: ["gl_llndk_headers"],
-}
-
-llndk_library {
- name: "libGLESv2.llndk",
- symbol_file: "libGLESv2.map.txt",
- export_llndk_headers: ["gl_llndk_headers"],
-}
-
-llndk_library {
- name: "libGLESv3.llndk",
- symbol_file: "libGLESv3.map.txt",
- export_llndk_headers: ["gl_llndk_headers"],
-}
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index edbf21a..27443b0 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -2967,7 +2967,7 @@
return; // Not a key or a motion
}
- std::unordered_set<sp<IBinder>, IBinderHash> newConnectionTokens;
+ std::unordered_set<sp<IBinder>, StrongPointerHash<IBinder>> newConnectionTokens;
std::vector<sp<Connection>> newConnections;
for (const InputTarget& target : targets) {
if ((target.flags & InputTarget::FLAG_DISPATCH_AS_OUTSIDE) ==
@@ -4284,12 +4284,8 @@
return nullptr;
}
-sp<InputWindowHandle> InputDispatcher::getFocusedWindowHandleLocked(int displayId) const {
- sp<IBinder> focusedToken = mFocusResolver.getFocusedWindowToken(displayId);
- return getWindowHandleLocked(focusedToken, displayId);
-}
-
-bool InputDispatcher::hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const {
+sp<InputWindowHandle> InputDispatcher::getWindowHandleLocked(
+ const sp<InputWindowHandle>& windowHandle) const {
for (auto& it : mWindowHandlesByDisplay) {
const std::vector<sp<InputWindowHandle>>& windowHandles = it.second;
for (const sp<InputWindowHandle>& handle : windowHandles) {
@@ -4301,11 +4297,16 @@
windowHandle->getName().c_str(), it.first,
windowHandle->getInfo()->displayId);
}
- return true;
+ return handle;
}
}
}
- return false;
+ return nullptr;
+}
+
+sp<InputWindowHandle> InputDispatcher::getFocusedWindowHandleLocked(int displayId) const {
+ sp<IBinder> focusedToken = mFocusResolver.getFocusedWindowToken(displayId);
+ return getWindowHandleLocked(focusedToken, displayId);
}
bool InputDispatcher::hasResponsiveConnectionLocked(InputWindowHandle& windowHandle) const {
@@ -4461,7 +4462,7 @@
TouchState& state = stateIt->second;
for (size_t i = 0; i < state.windows.size();) {
TouchedWindow& touchedWindow = state.windows[i];
- if (!hasWindowHandleLocked(touchedWindow.windowHandle)) {
+ if (getWindowHandleLocked(touchedWindow.windowHandle) == nullptr) {
if (DEBUG_FOCUS) {
ALOGD("Touched window was removed: %s in display %" PRId32,
touchedWindow.windowHandle->getName().c_str(), displayId);
@@ -4493,7 +4494,7 @@
// Otherwise, they might stick around until the window handle is destroyed
// which might not happen until the next GC.
for (const sp<InputWindowHandle>& oldWindowHandle : oldWindowHandles) {
- if (!hasWindowHandleLocked(oldWindowHandle)) {
+ if (getWindowHandleLocked(oldWindowHandle) == nullptr) {
if (DEBUG_FOCUS) {
ALOGD("Window went away: %s", oldWindowHandle->getName().c_str());
}
diff --git a/services/inputflinger/dispatcher/InputDispatcher.h b/services/inputflinger/dispatcher/InputDispatcher.h
index 5708fac..7ab4fd7 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.h
+++ b/services/inputflinger/dispatcher/InputDispatcher.h
@@ -221,12 +221,11 @@
void removeConnectionLocked(const sp<Connection>& connection) REQUIRES(mLock);
- struct IBinderHash {
- std::size_t operator()(const sp<IBinder>& b) const {
- return std::hash<IBinder*>{}(b.get());
- }
+ template <typename T>
+ struct StrongPointerHash {
+ std::size_t operator()(const sp<T>& b) const { return std::hash<T*>{}(b.get()); }
};
- std::unordered_map<sp<IBinder>, std::shared_ptr<InputChannel>, IBinderHash>
+ std::unordered_map<sp<IBinder>, std::shared_ptr<InputChannel>, StrongPointerHash<IBinder>>
mInputChannelsByToken GUARDED_BY(mLock);
// Finds the display ID of the gesture monitor identified by the provided token.
@@ -327,10 +326,11 @@
// to loop through all displays.
sp<InputWindowHandle> getWindowHandleLocked(const sp<IBinder>& windowHandleToken,
int displayId) const REQUIRES(mLock);
+ sp<InputWindowHandle> getWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const
+ REQUIRES(mLock);
std::shared_ptr<InputChannel> getInputChannelLocked(const sp<IBinder>& windowToken) const
REQUIRES(mLock);
sp<InputWindowHandle> getFocusedWindowHandleLocked(int displayId) const REQUIRES(mLock);
- bool hasWindowHandleLocked(const sp<InputWindowHandle>& windowHandle) const REQUIRES(mLock);
bool hasResponsiveConnectionLocked(InputWindowHandle& windowHandle) const REQUIRES(mLock);
/*
@@ -371,7 +371,8 @@
std::string mLastAnrState GUARDED_BY(mLock);
// The connection tokens of the channels that the user last interacted, for debugging
- std::unordered_set<sp<IBinder>, IBinderHash> mInteractionConnectionTokens GUARDED_BY(mLock);
+ std::unordered_set<sp<IBinder>, StrongPointerHash<IBinder>> mInteractionConnectionTokens
+ GUARDED_BY(mLock);
void updateInteractionTokensLocked(const EventEntry& entry,
const std::vector<InputTarget>& targets) REQUIRES(mLock);
diff --git a/services/surfaceflinger/Clock.h b/services/surfaceflinger/Clock.h
new file mode 100644
index 0000000..3f23c6d
--- /dev/null
+++ b/services/surfaceflinger/Clock.h
@@ -0,0 +1,42 @@
+/*
+ * 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 <chrono>
+
+namespace android {
+
+// Abstract interface for timekeeping which can be injected for unit tests.
+class Clock {
+public:
+ Clock() = default;
+ virtual ~Clock() = default;
+
+ // Returns the current time
+ virtual std::chrono::steady_clock::time_point now() const = 0;
+};
+
+class SteadyClock : public Clock {
+public:
+ virtual ~SteadyClock() = default;
+
+ std::chrono::steady_clock::time_point now() const override {
+ return std::chrono::steady_clock::now();
+ }
+};
+
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/FpsReporter.cpp b/services/surfaceflinger/FpsReporter.cpp
index 0bc2d3e..23db805 100644
--- a/services/surfaceflinger/FpsReporter.cpp
+++ b/services/surfaceflinger/FpsReporter.cpp
@@ -26,10 +26,18 @@
namespace android {
-FpsReporter::FpsReporter(frametimeline::FrameTimeline& frameTimeline, SurfaceFlinger& flinger)
- : mFrameTimeline(frameTimeline), mFlinger(flinger) {}
+FpsReporter::FpsReporter(frametimeline::FrameTimeline& frameTimeline, SurfaceFlinger& flinger,
+ std::unique_ptr<Clock> clock)
+ : mFrameTimeline(frameTimeline), mFlinger(flinger), mClock(std::move(clock)) {
+ LOG_ALWAYS_FATAL_IF(mClock == nullptr, "Passed in null clock when constructing FpsReporter!");
+}
-void FpsReporter::dispatchLayerFps() const {
+void FpsReporter::dispatchLayerFps() {
+ const auto now = mClock->now();
+ if (now - mLastDispatch < kMinDispatchDuration) {
+ return;
+ }
+
std::vector<TrackedListener> localListeners;
{
std::scoped_lock lock(mMutex);
@@ -71,6 +79,8 @@
listener.listener->onFpsReported(mFrameTimeline.computeFps(layerIds));
}
+
+ mLastDispatch = now;
}
void FpsReporter::binderDied(const wp<IBinder>& who) {
diff --git a/services/surfaceflinger/FpsReporter.h b/services/surfaceflinger/FpsReporter.h
index 1cec295..bd7b9a5 100644
--- a/services/surfaceflinger/FpsReporter.h
+++ b/services/surfaceflinger/FpsReporter.h
@@ -22,6 +22,7 @@
#include <unordered_map>
+#include "Clock.h"
#include "FrameTimeline/FrameTimeline.h"
namespace android {
@@ -31,12 +32,13 @@
class FpsReporter : public IBinder::DeathRecipient {
public:
- FpsReporter(frametimeline::FrameTimeline& frameTimeline, SurfaceFlinger& flinger);
+ FpsReporter(frametimeline::FrameTimeline& frameTimeline, SurfaceFlinger& flinger,
+ std::unique_ptr<Clock> clock = std::make_unique<SteadyClock>());
// Dispatches updated layer fps values for the registered listeners
// This method promotes Layer weak pointers and performs layer stack traversals, so mStateLock
// must be held when calling this method.
- void dispatchLayerFps() const EXCLUDES(mMutex);
+ void dispatchLayerFps() EXCLUDES(mMutex);
// Override for IBinder::DeathRecipient
void binderDied(const wp<IBinder>&) override;
@@ -61,6 +63,10 @@
frametimeline::FrameTimeline& mFrameTimeline;
SurfaceFlinger& mFlinger;
+ static const constexpr std::chrono::steady_clock::duration kMinDispatchDuration =
+ std::chrono::milliseconds(500);
+ std::unique_ptr<Clock> mClock;
+ std::chrono::steady_clock::time_point mLastDispatch;
std::unordered_map<wp<IBinder>, TrackedListener, WpHash> mListeners GUARDED_BY(mMutex);
};
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
index be552c6..0033dbe 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
@@ -256,6 +256,10 @@
protoJank |= FrameTimelineEvent::JANK_UNKNOWN;
jankType &= ~JankType::Unknown;
}
+ if (jankType & JankType::SurfaceFlingerStuffing) {
+ protoJank |= FrameTimelineEvent::JANK_SF_STUFFING;
+ jankType &= ~JankType::SurfaceFlingerStuffing;
+ }
// jankType should be 0 if all types of jank were checked for.
LOG_ALWAYS_FATAL_IF(jankType != 0, "Unrecognized jank type value 0x%x", jankType);
@@ -875,7 +879,8 @@
mGpuFence = gpuFence;
}
-void FrameTimeline::DisplayFrame::classifyJank(nsecs_t& deadlineDelta, nsecs_t& deltaToVsync) {
+void FrameTimeline::DisplayFrame::classifyJank(nsecs_t& deadlineDelta, nsecs_t& deltaToVsync,
+ nsecs_t previousPresentTime) {
if (mPredictionState == PredictionState::Expired ||
mSurfaceFlingerActuals.presentTime == Fence::SIGNAL_TIME_INVALID) {
// Cannot do jank classification with expired predictions or invalid signal times. Set the
@@ -949,7 +954,15 @@
mJankType = JankType::Unknown;
}
} else if (mFramePresentMetadata == FramePresentMetadata::LatePresent) {
- if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
+ if (std::abs(mSurfaceFlingerPredictions.presentTime - previousPresentTime) <=
+ mJankClassificationThresholds.presentThreshold ||
+ previousPresentTime > mSurfaceFlingerPredictions.presentTime) {
+ // The previous frame was either presented in the current frame's expected vsync or
+ // it was presented even later than the current frame's expected vsync.
+ mJankType = JankType::SurfaceFlingerStuffing;
+ }
+ if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish &&
+ !(mJankType & JankType::SurfaceFlingerStuffing)) {
// Finish on time, Present late
if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
@@ -963,11 +976,12 @@
mJankType = JankType::PredictionError;
}
} else if (mFrameReadyMetadata == FrameReadyMetadata::LateFinish) {
- if (mFrameStartMetadata == FrameStartMetadata::LateStart) {
- // Late start, Late finish, Late Present
- mJankType = JankType::SurfaceFlingerScheduling;
- } else {
- // OnTime start, Finish late, Present late
+ if (!(mJankType & JankType::SurfaceFlingerStuffing) ||
+ mSurfaceFlingerActuals.presentTime - previousPresentTime >
+ mRefreshRate.getPeriodNsecs() +
+ mJankClassificationThresholds.presentThreshold) {
+ // Classify CPU vs GPU if SF wasn't stuffed or if SF was stuffed but this frame
+ // was presented more than a vsync late.
if (mGpuFence != FenceTime::NO_FENCE &&
mSurfaceFlingerActuals.endTime - mSurfaceFlingerActuals.startTime <
mRefreshRate.getPeriodNsecs()) {
@@ -989,11 +1003,11 @@
}
}
-void FrameTimeline::DisplayFrame::onPresent(nsecs_t signalTime) {
+void FrameTimeline::DisplayFrame::onPresent(nsecs_t signalTime, nsecs_t previousPresentTime) {
mSurfaceFlingerActuals.presentTime = signalTime;
nsecs_t deadlineDelta = 0;
nsecs_t deltaToVsync = 0;
- classifyJank(deadlineDelta, deltaToVsync);
+ classifyJank(deadlineDelta, deltaToVsync, previousPresentTime);
for (auto& surfaceFrame : mSurfaceFrames) {
surfaceFrame->onPresent(signalTime, mJankType, mRefreshRate, deadlineDelta, deltaToVsync);
@@ -1158,8 +1172,9 @@
}
}
auto& displayFrame = pendingPresentFence.second;
- displayFrame->onPresent(signalTime);
+ displayFrame->onPresent(signalTime, mPreviousPresentTime);
displayFrame->trace(mSurfaceFlingerPid);
+ mPreviousPresentTime = signalTime;
mPendingPresentFences.erase(mPendingPresentFences.begin() + static_cast<int>(i));
--i;
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
index 41f4978..0563a53 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
@@ -370,7 +370,7 @@
void onSfWakeUp(int64_t token, Fps refreshRate, std::optional<TimelineItem> predictions,
nsecs_t wakeUpTime);
// Sets the appropriate metadata and classifies the jank.
- void onPresent(nsecs_t signalTime);
+ void onPresent(nsecs_t signalTime, nsecs_t previousPresentTime);
// Adds the provided SurfaceFrame to the current display frame.
void addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame);
@@ -398,7 +398,8 @@
void dump(std::string& result, nsecs_t baseTime) const;
void tracePredictions(pid_t surfaceFlingerPid) const;
void traceActuals(pid_t surfaceFlingerPid) const;
- void classifyJank(nsecs_t& deadlineDelta, nsecs_t& deltaToVsync);
+ void classifyJank(nsecs_t& deadlineDelta, nsecs_t& deltaToVsync,
+ nsecs_t previousPresentTime);
int64_t mToken = FrameTimelineInfo::INVALID_VSYNC_ID;
@@ -480,6 +481,7 @@
uint32_t mMaxDisplayFrames;
std::shared_ptr<TimeStats> mTimeStats;
const pid_t mSurfaceFlingerPid;
+ nsecs_t mPreviousPresentTime = 0;
const JankClassificationThresholds mJankClassificationThresholds;
static constexpr uint32_t kDefaultMaxDisplayFrames = 64;
// The initial container size for the vector<SurfaceFrames> inside display frame. Although
diff --git a/services/surfaceflinger/Scheduler/OneShotTimer.cpp b/services/surfaceflinger/Scheduler/OneShotTimer.cpp
index d659398..16f041a 100644
--- a/services/surfaceflinger/Scheduler/OneShotTimer.cpp
+++ b/services/surfaceflinger/Scheduler/OneShotTimer.cpp
@@ -15,7 +15,6 @@
*/
#include "OneShotTimer.h"
-
#include <utils/Log.h>
#include <utils/Timers.h>
#include <chrono>
@@ -40,14 +39,9 @@
namespace android {
namespace scheduler {
-std::chrono::steady_clock::time_point OneShotTimer::Clock::now() const {
- return std::chrono::steady_clock::now();
-}
-
OneShotTimer::OneShotTimer(std::string name, const Interval& interval,
const ResetCallback& resetCallback,
- const TimeoutCallback& timeoutCallback,
- std::unique_ptr<OneShotTimer::Clock> clock)
+ const TimeoutCallback& timeoutCallback, std::unique_ptr<Clock> clock)
: mClock(std::move(clock)),
mName(std::move(name)),
mInterval(interval),
diff --git a/services/surfaceflinger/Scheduler/OneShotTimer.h b/services/surfaceflinger/Scheduler/OneShotTimer.h
index 7285427..09265bb 100644
--- a/services/surfaceflinger/Scheduler/OneShotTimer.h
+++ b/services/surfaceflinger/Scheduler/OneShotTimer.h
@@ -20,6 +20,7 @@
#include <chrono>
#include <condition_variable>
#include <thread>
+#include "../Clock.h"
#include <android-base/thread_annotations.h>
@@ -36,17 +37,9 @@
using ResetCallback = std::function<void()>;
using TimeoutCallback = std::function<void()>;
- class Clock {
- public:
- Clock() = default;
- virtual ~Clock() = default;
-
- virtual std::chrono::steady_clock::time_point now() const;
- };
-
OneShotTimer(std::string name, const Interval& interval, const ResetCallback& resetCallback,
const TimeoutCallback& timeoutCallback,
- std::unique_ptr<OneShotTimer::Clock> = std::make_unique<OneShotTimer::Clock>());
+ std::unique_ptr<Clock> clock = std::make_unique<SteadyClock>());
~OneShotTimer();
// Initializes and turns on the idle timer.
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 57bd045..fac2c65 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -583,13 +583,9 @@
scheduler::LayerHistory::LayerVoteType voteType;
- if (layer->getWindowType() == InputWindowInfo::Type::STATUS_BAR) {
+ if (!mOptions.useContentDetection ||
+ layer->getWindowType() == InputWindowInfo::Type::STATUS_BAR) {
voteType = scheduler::LayerHistory::LayerVoteType::NoVote;
- } else if (!mOptions.useContentDetection) {
- // If the content detection feature is off, all layers are registered at Max. We still keep
- // the layer history, since we use it for other features (like Frame Rate API), so layers
- // still need to be registered.
- voteType = scheduler::LayerHistory::LayerVoteType::Max;
} else if (layer->getWindowType() == InputWindowInfo::Type::WALLPAPER) {
// Running Wallpaper at Min is considered as part of content detection.
voteType = scheduler::LayerHistory::LayerVoteType::Min;
@@ -597,6 +593,9 @@
voteType = scheduler::LayerHistory::LayerVoteType::Heuristic;
}
+ // If the content detection feature is off, we still keep the layer history,
+ // since we use it for other features (like Frame Rate API), so layers
+ // still need to be registered.
mLayerHistory->registerLayer(layer, voteType);
}
diff --git a/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp b/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp
index a2291b2..dec0ff5 100644
--- a/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FpsReporterTest.cpp
@@ -28,6 +28,7 @@
#include "FpsReporter.h"
#include "Layer.h"
#include "TestableSurfaceFlinger.h"
+#include "fake/FakeClock.h"
#include "mock/DisplayHardware/MockComposer.h"
#include "mock/MockEventThread.h"
#include "mock/MockFrameTimeline.h"
@@ -91,7 +92,9 @@
sp<Layer> mUnrelated;
sp<TestableFpsListener> mFpsListener;
- sp<FpsReporter> mFpsReporter = new FpsReporter(mFrameTimeline, *(mFlinger.flinger()));
+ fake::FakeClock* mClock = new fake::FakeClock();
+ sp<FpsReporter> mFpsReporter =
+ new FpsReporter(mFrameTimeline, *(mFlinger.flinger()), std::unique_ptr<Clock>(mClock));
};
FpsReporterTest::FpsReporterTest() {
@@ -178,6 +181,7 @@
.WillOnce(Return(expectedFps));
mFpsReporter->addListener(mFpsListener, kTaskId);
+ mClock->advanceTime(600ms);
mFpsReporter->dispatchLayerFps();
EXPECT_EQ(expectedFps, mFpsListener->lastReportedFps);
mFpsReporter->removeListener(mFpsListener);
@@ -187,5 +191,34 @@
mFpsReporter->dispatchLayerFps();
}
+TEST_F(FpsReporterTest, rateLimits) {
+ const constexpr int32_t kTaskId = 12;
+ LayerMetadata targetMetadata;
+ targetMetadata.setInt32(METADATA_TASK_ID, kTaskId);
+ mTarget = createBufferStateLayer(targetMetadata);
+ mFlinger.mutableCurrentState().layersSortedByZ.add(mTarget);
+
+ float firstFps = 44.0;
+ float secondFps = 53.0;
+
+ EXPECT_CALL(mFrameTimeline, computeFps(UnorderedElementsAre(mTarget->getSequence())))
+ .WillOnce(Return(firstFps))
+ .WillOnce(Return(secondFps));
+
+ mFpsReporter->addListener(mFpsListener, kTaskId);
+ mClock->advanceTime(600ms);
+ mFpsReporter->dispatchLayerFps();
+ EXPECT_EQ(firstFps, mFpsListener->lastReportedFps);
+ mClock->advanceTime(200ms);
+ mFpsReporter->dispatchLayerFps();
+ EXPECT_EQ(firstFps, mFpsListener->lastReportedFps);
+ mClock->advanceTime(200ms);
+ mFpsReporter->dispatchLayerFps();
+ EXPECT_EQ(firstFps, mFpsListener->lastReportedFps);
+ mClock->advanceTime(200ms);
+ mFpsReporter->dispatchLayerFps();
+ EXPECT_EQ(secondFps, mFpsListener->lastReportedFps);
+}
+
} // namespace
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
index 8a3f561..6ed6148 100644
--- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
@@ -1561,13 +1561,22 @@
/*
* Case 1 - cpu time > vsync period but combined time > deadline > deadline -> cpudeadlinemissed
* Case 2 - cpu time < vsync period but combined time > deadline -> gpudeadlinemissed
+ * Case 3 - previous frame ran longer -> sf_stuffing
+ * Case 4 - Long cpu under SF stuffing -> cpudeadlinemissed
*/
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+ auto presentFence3 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+ auto presentFence4 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
auto gpuFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
auto gpuFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+ auto gpuFence3 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+ auto gpuFence4 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 40});
int64_t sfToken2 = mTokenManager->generateTokenForPredictions({52, 60, 60});
+ int64_t sfToken3 = mTokenManager->generateTokenForPredictions({82, 90, 90});
+ int64_t sfToken4 = mTokenManager->generateTokenForPredictions({112, 120, 120});
+
// case 1 - cpu time = 33 - 12 = 21, vsync period = 11
mFrameTimeline->setSfWakeUp(sfToken1, 12, Fps::fromPeriodNsecs(11));
mFrameTimeline->setSfPresent(33, presentFence1, gpuFence1);
@@ -1578,12 +1587,12 @@
// Fences haven't been flushed yet, so it should be 0
EXPECT_EQ(displayFrame0->getActuals().presentTime, 0);
- // case 2 - cpu time = 56 - 52 = 4, vsync period = 11
- mFrameTimeline->setSfWakeUp(sfToken2, 52, Fps::fromPeriodNsecs(11));
+ // case 2 - cpu time = 56 - 52 = 4, vsync period = 30
+ mFrameTimeline->setSfWakeUp(sfToken2, 52, Fps::fromPeriodNsecs(30));
mFrameTimeline->setSfPresent(56, presentFence2, gpuFence2);
auto displayFrame1 = getDisplayFrame(1);
- gpuFence2->signalForTest(66);
- presentFence2->signalForTest(71);
+ gpuFence2->signalForTest(76);
+ presentFence2->signalForTest(90);
EXPECT_EQ(displayFrame1->getActuals().presentTime, 0);
// Fences have flushed for first displayFrame, so the present timestamps should be updated
@@ -1592,35 +1601,41 @@
EXPECT_EQ(displayFrame0->getFrameReadyMetadata(), FrameReadyMetadata::LateFinish);
EXPECT_EQ(displayFrame0->getJankType(), JankType::SurfaceFlingerCpuDeadlineMissed);
- addEmptyDisplayFrame();
+ // case 3 - cpu time = 86 - 82 = 4, vsync period = 30
+ mFrameTimeline->setSfWakeUp(sfToken3, 106, Fps::fromPeriodNsecs(30));
+ mFrameTimeline->setSfPresent(112, presentFence3, gpuFence3);
+ auto displayFrame2 = getDisplayFrame(2);
+ gpuFence3->signalForTest(116);
+ presentFence3->signalForTest(120);
+ EXPECT_EQ(displayFrame2->getActuals().presentTime, 0);
// Fences have flushed for second displayFrame, so the present timestamps should be updated
- EXPECT_EQ(displayFrame1->getActuals().presentTime, 71);
+ EXPECT_EQ(displayFrame1->getActuals().presentTime, 90);
EXPECT_EQ(displayFrame1->getFramePresentMetadata(), FramePresentMetadata::LatePresent);
EXPECT_EQ(displayFrame1->getFrameReadyMetadata(), FrameReadyMetadata::LateFinish);
EXPECT_EQ(displayFrame1->getJankType(), JankType::SurfaceFlingerGpuDeadlineMissed);
-}
-TEST_F(FrameTimelineTest, jankClassification_displayFrameLateStartLateFinishLatePresent) {
- auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
- int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 40});
- mFrameTimeline->setSfWakeUp(sfToken1, 26, Fps::fromPeriodNsecs(11));
- mFrameTimeline->setSfPresent(36, presentFence1);
- auto displayFrame = getDisplayFrame(0);
- presentFence1->signalForTest(52);
+ // case 4 - cpu time = 86 - 82 = 4, vsync period = 30
+ mFrameTimeline->setSfWakeUp(sfToken4, 120, Fps::fromPeriodNsecs(30));
+ mFrameTimeline->setSfPresent(140, presentFence4, gpuFence4);
+ auto displayFrame3 = getDisplayFrame(3);
+ gpuFence4->signalForTest(156);
+ presentFence4->signalForTest(180);
- // Fences haven't been flushed yet, so it should be 0
- EXPECT_EQ(displayFrame->getActuals().presentTime, 0);
+ EXPECT_EQ(displayFrame3->getActuals().presentTime, 0);
+ // Fences have flushed for third displayFrame, so the present timestamps should be updated
+ EXPECT_EQ(displayFrame2->getActuals().presentTime, 120);
+ EXPECT_EQ(displayFrame2->getFramePresentMetadata(), FramePresentMetadata::LatePresent);
+ EXPECT_EQ(displayFrame2->getFrameReadyMetadata(), FrameReadyMetadata::LateFinish);
+ EXPECT_EQ(displayFrame2->getJankType(), JankType::SurfaceFlingerStuffing);
addEmptyDisplayFrame();
- displayFrame = getDisplayFrame(0);
- // Fences have flushed, so the present timestamps should be updated
- EXPECT_EQ(displayFrame->getActuals().presentTime, 52);
- EXPECT_EQ(displayFrame->getFrameStartMetadata(), FrameStartMetadata::LateStart);
- EXPECT_EQ(displayFrame->getFramePresentMetadata(), FramePresentMetadata::LatePresent);
- EXPECT_EQ(displayFrame->getFrameReadyMetadata(), FrameReadyMetadata::LateFinish);
- EXPECT_EQ(displayFrame->getJankType(), JankType::SurfaceFlingerScheduling);
+ // Fences have flushed for third displayFrame, so the present timestamps should be updated
+ EXPECT_EQ(displayFrame3->getActuals().presentTime, 180);
+ EXPECT_EQ(displayFrame3->getFramePresentMetadata(), FramePresentMetadata::LatePresent);
+ EXPECT_EQ(displayFrame3->getFrameReadyMetadata(), FrameReadyMetadata::LateFinish);
+ EXPECT_EQ(displayFrame3->getJankType(), JankType::SurfaceFlingerGpuDeadlineMissed);
}
TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishEarlyPresent) {
diff --git a/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp b/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp
index a1f0588..6916764 100644
--- a/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/OneShotTimerTest.cpp
@@ -23,23 +23,13 @@
#include "AsyncCallRecorder.h"
#include "Scheduler/OneShotTimer.h"
+#include "fake/FakeClock.h"
using namespace std::chrono_literals;
namespace android {
namespace scheduler {
-class FakeClock : public OneShotTimer::Clock {
-public:
- virtual ~FakeClock() = default;
- std::chrono::steady_clock::time_point now() const override { return mNow; }
-
- void advanceTime(std::chrono::nanoseconds delta) { mNow += delta; }
-
-private:
- std::chrono::steady_clock::time_point mNow;
-};
-
class OneShotTimerTest : public testing::Test {
protected:
OneShotTimerTest() = default;
@@ -58,17 +48,17 @@
namespace {
TEST_F(OneShotTimerTest, createAndDestroyTest) {
- FakeClock* clock = new FakeClock();
+ fake::FakeClock* clock = new fake::FakeClock();
mIdleTimer = std::make_unique<scheduler::OneShotTimer>(
- "TestTimer", 3ms, [] {}, [] {}, std::unique_ptr<FakeClock>(clock));
+ "TestTimer", 3ms, [] {}, [] {}, std::unique_ptr<fake::FakeClock>(clock));
}
TEST_F(OneShotTimerTest, startStopTest) {
- FakeClock* clock = new FakeClock();
+ fake::FakeClock* clock = new fake::FakeClock();
mIdleTimer = std::make_unique<scheduler::OneShotTimer>("TestTimer", 1ms,
mResetTimerCallback.getInvocable(),
mExpiredTimerCallback.getInvocable(),
- std::unique_ptr<FakeClock>(clock));
+ std::unique_ptr<fake::FakeClock>(clock));
mIdleTimer->start();
EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
EXPECT_FALSE(mExpiredTimerCallback.waitForUnexpectedCall().has_value());
@@ -83,11 +73,11 @@
}
TEST_F(OneShotTimerTest, resetTest) {
- FakeClock* clock = new FakeClock();
+ fake::FakeClock* clock = new fake::FakeClock();
mIdleTimer = std::make_unique<scheduler::OneShotTimer>("TestTimer", 1ms,
mResetTimerCallback.getInvocable(),
mExpiredTimerCallback.getInvocable(),
- std::unique_ptr<FakeClock>(clock));
+ std::unique_ptr<fake::FakeClock>(clock));
mIdleTimer->start();
EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
@@ -105,11 +95,11 @@
}
TEST_F(OneShotTimerTest, resetBackToBackTest) {
- FakeClock* clock = new FakeClock();
+ fake::FakeClock* clock = new fake::FakeClock();
mIdleTimer = std::make_unique<scheduler::OneShotTimer>("TestTimer", 1ms,
mResetTimerCallback.getInvocable(),
mExpiredTimerCallback.getInvocable(),
- std::unique_ptr<FakeClock>(clock));
+ std::unique_ptr<fake::FakeClock>(clock));
mIdleTimer->start();
EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
@@ -139,11 +129,11 @@
}
TEST_F(OneShotTimerTest, startNotCalledTest) {
- FakeClock* clock = new FakeClock();
+ fake::FakeClock* clock = new fake::FakeClock();
mIdleTimer = std::make_unique<scheduler::OneShotTimer>("TestTimer", 1ms,
mResetTimerCallback.getInvocable(),
mExpiredTimerCallback.getInvocable(),
- std::unique_ptr<FakeClock>(clock));
+ std::unique_ptr<fake::FakeClock>(clock));
// The start hasn't happened, so the callback does not happen.
EXPECT_FALSE(mExpiredTimerCallback.waitForUnexpectedCall().has_value());
EXPECT_FALSE(mResetTimerCallback.waitForUnexpectedCall().has_value());
@@ -155,11 +145,11 @@
}
TEST_F(OneShotTimerTest, idleTimerIdlesTest) {
- FakeClock* clock = new FakeClock();
+ fake::FakeClock* clock = new fake::FakeClock();
mIdleTimer = std::make_unique<scheduler::OneShotTimer>("TestTimer", 1ms,
mResetTimerCallback.getInvocable(),
mExpiredTimerCallback.getInvocable(),
- std::unique_ptr<FakeClock>(clock));
+ std::unique_ptr<fake::FakeClock>(clock));
mIdleTimer->start();
EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
clock->advanceTime(2ms);
@@ -180,11 +170,11 @@
}
TEST_F(OneShotTimerTest, timeoutCallbackExecutionTest) {
- FakeClock* clock = new FakeClock();
+ fake::FakeClock* clock = new fake::FakeClock();
mIdleTimer = std::make_unique<scheduler::OneShotTimer>("TestTimer", 1ms,
mResetTimerCallback.getInvocable(),
mExpiredTimerCallback.getInvocable(),
- std::unique_ptr<FakeClock>(clock));
+ std::unique_ptr<fake::FakeClock>(clock));
mIdleTimer->start();
EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
@@ -197,11 +187,11 @@
}
TEST_F(OneShotTimerTest, noCallbacksAfterStopAndResetTest) {
- FakeClock* clock = new FakeClock();
+ fake::FakeClock* clock = new fake::FakeClock();
mIdleTimer = std::make_unique<scheduler::OneShotTimer>("TestTimer", 1ms,
mResetTimerCallback.getInvocable(),
mExpiredTimerCallback.getInvocable(),
- std::unique_ptr<FakeClock>(clock));
+ std::unique_ptr<fake::FakeClock>(clock));
mIdleTimer->start();
EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
clock->advanceTime(2ms);
@@ -215,11 +205,11 @@
}
TEST_F(OneShotTimerTest, noCallbacksAfterStopTest) {
- FakeClock* clock = new FakeClock();
+ fake::FakeClock* clock = new fake::FakeClock();
mIdleTimer = std::make_unique<scheduler::OneShotTimer>("TestTimer", 1ms,
mResetTimerCallback.getInvocable(),
mExpiredTimerCallback.getInvocable(),
- std::unique_ptr<FakeClock>(clock));
+ std::unique_ptr<fake::FakeClock>(clock));
mIdleTimer->start();
EXPECT_TRUE(mResetTimerCallback.waitForCall().has_value());
EXPECT_FALSE(mExpiredTimerCallback.waitForUnexpectedCall().has_value());
diff --git a/services/surfaceflinger/tests/unittests/fake/FakeClock.h b/services/surfaceflinger/tests/unittests/fake/FakeClock.h
new file mode 100644
index 0000000..6d9c764
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/fake/FakeClock.h
@@ -0,0 +1,34 @@
+/*
+ * 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 "../../Clock.h"
+
+namespace android::fake {
+
+class FakeClock : public Clock {
+public:
+ virtual ~FakeClock() = default;
+ std::chrono::steady_clock::time_point now() const override { return mNow; }
+
+ void advanceTime(std::chrono::nanoseconds delta) { mNow += delta; }
+
+private:
+ std::chrono::steady_clock::time_point mNow;
+};
+
+} // namespace android::fake
\ No newline at end of file
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 67cd875..d4cb928 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -29,17 +29,14 @@
unversioned_until: "current",
}
-llndk_library {
- name: "libvulkan.llndk",
- symbol_file: "libvulkan.map.txt",
- export_llndk_headers: [
- "vulkan_headers_llndk",
- ],
-}
-
cc_library_shared {
name: "libvulkan",
- llndk_stubs: "libvulkan.llndk",
+ llndk: {
+ symbol_file: "libvulkan.map.txt",
+ export_llndk_headers: [
+ "vulkan_headers_llndk",
+ ],
+ },
clang: true,
sanitize: {
misc_undefined: ["integer"],