Merge "SF Buffer Stuffing" 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/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/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/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/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/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/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/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"],