Merge "Enable RenderEngine blur testing on more devices." into sc-dev
diff --git a/Android.bp b/Android.bp
index 9829c7f..298c01a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,3 +1,41 @@
+package {
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+//
+// large-scale-change filtered out the below license kinds as false-positives:
+// SPDX-license-identifier-LGPL
+// SPDX-license-identifier-LGPL-2.1
+// SPDX-license-identifier-LGPL-3.0
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ "SPDX-license-identifier-BSD",
+ "SPDX-license-identifier-MIT",
+ "SPDX-license-identifier-Unicode-DFS",
+ "legacy_notice",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
ndk_headers {
name: "libandroid_headers",
from: "include/android",
@@ -43,3 +81,8 @@
":framework_native_aidl_gui",
],
}
+
+cc_library_headers{
+ name: "libandroid_headers_private",
+ export_include_dirs: ["include/private"],
+}
\ No newline at end of file
diff --git a/cmds/atrace/Android.bp b/cmds/atrace/Android.bp
index e7d0ad0..aa0ef25 100644
--- a/cmds/atrace/Android.bp
+++ b/cmds/atrace/Android.bp
@@ -1,5 +1,22 @@
// Copyright 2012 The Android Open Source Project
+package {
+ default_applicable_licenses: ["frameworks_native_cmds_atrace_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_cmds_atrace_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_binary {
name: "atrace",
srcs: ["atrace.cpp"],
diff --git a/cmds/bugreport/Android.bp b/cmds/bugreport/Android.bp
index 24044a6..8262aed 100644
--- a/cmds/bugreport/Android.bp
+++ b/cmds/bugreport/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_binary {
name: "bugreport",
srcs: ["bugreport.cpp"],
diff --git a/cmds/bugreportz/Android.bp b/cmds/bugreportz/Android.bp
index 924a3a3..332f858 100644
--- a/cmds/bugreportz/Android.bp
+++ b/cmds/bugreportz/Android.bp
@@ -1,5 +1,14 @@
// bugreportz
// ==========
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_binary {
name: "bugreportz",
diff --git a/cmds/cmd/Android.bp b/cmds/cmd/Android.bp
index 8ea71cd..c900a24 100644
--- a/cmds/cmd/Android.bp
+++ b/cmds/cmd/Android.bp
@@ -1,3 +1,20 @@
+package {
+ default_applicable_licenses: ["frameworks_native_cmds_cmd_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_cmds_cmd_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_static {
name: "libcmd",
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index 34e9a85..f48f1fb 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -13,6 +13,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "dumpstate_cflag_defaults",
cflags: [
diff --git a/cmds/dumpsys/Android.bp b/cmds/dumpsys/Android.bp
index f99588f..91aa018 100644
--- a/cmds/dumpsys/Android.bp
+++ b/cmds/dumpsys/Android.bp
@@ -1,3 +1,20 @@
+package {
+ default_applicable_licenses: ["frameworks_native_cmds_dumpsys_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_cmds_dumpsys_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_defaults {
name: "dumpsys_defaults",
diff --git a/cmds/dumpsys/tests/Android.bp b/cmds/dumpsys/tests/Android.bp
index e182b9d..6854c75 100644
--- a/cmds/dumpsys/tests/Android.bp
+++ b/cmds/dumpsys/tests/Android.bp
@@ -1,4 +1,13 @@
// Build the unit tests for dumpsys
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_cmds_dumpsys_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_cmds_dumpsys_license"],
+}
+
cc_test {
name: "dumpsys_test",
test_suites: ["device-tests"],
diff --git a/cmds/flatland/Android.mk b/cmds/flatland/Android.mk
index 7aa111c..754a99c 100644
--- a/cmds/flatland/Android.mk
+++ b/cmds/flatland/Android.mk
@@ -11,6 +11,9 @@
LOCAL_CFLAGS := -Wall -Werror
LOCAL_MODULE:= flatland
+LOCAL_LICENSE_KINDS:= SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS:= notice
+LOCAL_NOTICE_FILE:= $(LOCAL_PATH)/../../NOTICE
LOCAL_MODULE_TAGS := tests
diff --git a/cmds/idlcli/Android.bp b/cmds/idlcli/Android.bp
index 72ffc94..c537fed 100644
--- a/cmds/idlcli/Android.bp
+++ b/cmds/idlcli/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "idlcli-defaults",
shared_libs: [
diff --git a/cmds/installd/Android.bp b/cmds/installd/Android.bp
index cbe857a..5c2211f 100644
--- a/cmds/installd/Android.bp
+++ b/cmds/installd/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "installd_defaults",
diff --git a/cmds/installd/tests/Android.bp b/cmds/installd/tests/Android.bp
index 7c9e3b2..f67ab81 100644
--- a/cmds/installd/tests/Android.bp
+++ b/cmds/installd/tests/Android.bp
@@ -1,4 +1,13 @@
// Build the unit tests for installd
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "installd_utils_test",
test_suites: ["device-tests"],
@@ -157,4 +166,3 @@
"libotapreoptparameters"
],
}
-
diff --git a/cmds/ip-up-vpn/Android.mk b/cmds/ip-up-vpn/Android.mk
index e1e2204..396ae9d 100644
--- a/cmds/ip-up-vpn/Android.mk
+++ b/cmds/ip-up-vpn/Android.mk
@@ -21,6 +21,9 @@
LOCAL_CFLAGS := -Wall -Werror
LOCAL_SHARED_LIBRARIES := libcutils liblog
LOCAL_MODULE := ip-up-vpn
+LOCAL_LICENSE_KINDS := SPDX-license-identifier-Apache-2.0
+LOCAL_LICENSE_CONDITIONS := notice
+LOCAL_NOTICE_FILE := $(LOCAL_PATH)/../../NOTICE
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/ppp
LOCAL_MODULE_TAGS := optional
diff --git a/cmds/lshal/Android.bp b/cmds/lshal/Android.bp
index 0cbb80f..649e53a 100644
--- a/cmds/lshal/Android.bp
+++ b/cmds/lshal/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_static {
name: "liblshal",
shared_libs: [
diff --git a/cmds/lshal/libprocpartition/Android.bp b/cmds/lshal/libprocpartition/Android.bp
index 9592111..cbfbdc9 100644
--- a/cmds/lshal/libprocpartition/Android.bp
+++ b/cmds/lshal/libprocpartition/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_static {
name: "libprocpartition",
shared_libs: [
diff --git a/cmds/rawbu/Android.bp b/cmds/rawbu/Android.bp
index 363ffc1..e34119d 100644
--- a/cmds/rawbu/Android.bp
+++ b/cmds/rawbu/Android.bp
@@ -1,5 +1,22 @@
// Copyright 2009 The Android Open Source Project
+package {
+ default_applicable_licenses: ["frameworks_native_cmds_rawbu_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_cmds_rawbu_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_binary {
name: "rawbu",
diff --git a/cmds/rss_hwm_reset/Android.bp b/cmds/rss_hwm_reset/Android.bp
index 15f10ef..cd335d4 100644
--- a/cmds/rss_hwm_reset/Android.bp
+++ b/cmds/rss_hwm_reset/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_binary {
name: "rss_hwm_reset",
diff --git a/cmds/service/Android.bp b/cmds/service/Android.bp
index a5b1ac5..3e8e3f6 100644
--- a/cmds/service/Android.bp
+++ b/cmds/service/Android.bp
@@ -1,3 +1,20 @@
+package {
+ default_applicable_licenses: ["frameworks_native_cmds_service_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_cmds_service_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_binary {
name: "service",
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index b139251..9de344a 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "servicemanager_defaults",
diff --git a/cmds/surfacereplayer/Android.bp b/cmds/surfacereplayer/Android.bp
index d4c037a..34fc8b1 100644
--- a/cmds/surfacereplayer/Android.bp
+++ b/cmds/surfacereplayer/Android.bp
@@ -1,4 +1,13 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
subdirs = [
"proto",
"replayer",
-]
\ No newline at end of file
+]
diff --git a/cmds/surfacereplayer/proto/Android.bp b/cmds/surfacereplayer/proto/Android.bp
index 71a5e23..dae976e 100644
--- a/cmds/surfacereplayer/proto/Android.bp
+++ b/cmds/surfacereplayer/proto/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_static {
name: "libtrace_proto",
srcs: [
diff --git a/cmds/surfacereplayer/replayer/Android.bp b/cmds/surfacereplayer/replayer/Android.bp
index 7632311..3985230 100644
--- a/cmds/surfacereplayer/replayer/Android.bp
+++ b/cmds/surfacereplayer/replayer/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libsurfacereplayer",
srcs: [
diff --git a/data/etc/android.hardware.keystore.app_attest_key.xml b/data/etc/android.hardware.keystore.app_attest_key.xml
new file mode 100644
index 0000000..8adc439
--- /dev/null
+++ b/data/etc/android.hardware.keystore.app_attest_key.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- Feature for devices that support app attestation keys (i.e. KeyMint 1.0). -->
+<permissions>
+ <feature name="android.hardware.keystore.app_attest_key" />
+</permissions>
diff --git a/headers/Android.bp b/headers/Android.bp
index 8f41c2b..7481a23 100644
--- a/headers/Android.bp
+++ b/headers/Android.bp
@@ -1,3 +1,13 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "media_plugin_headers",
vendor_available: true,
diff --git a/include/android/permission_manager.h b/include/android/permission_manager.h
index 2d5d060..753b6d1 100644
--- a/include/android/permission_manager.h
+++ b/include/android/permission_manager.h
@@ -14,6 +14,17 @@
* limitations under the License.
*/
+/**
+ * Structures and functions related to permission checks in native code.
+ *
+ * @addtogroup Permission
+ * @{
+ */
+
+/**
+ * @file permission_manager.h
+ */
+
#ifndef ANDROID_PERMISSION_MANAGER_H
#define ANDROID_PERMISSION_MANAGER_H
@@ -48,8 +59,8 @@
enum {
/**
* This is returned if the permission check completed without errors.
- * The output result is valid and contains one of {PERMISSION_MANAGER_PERMISSION_GRANTED,
- * PERMISSION_MANAGER_PERMISSION_DENIED}.
+ * The output result is valid and contains one of {::PERMISSION_MANAGER_PERMISSION_GRANTED,
+ * ::PERMISSION_MANAGER_PERMISSION_DENIED}.
*/
PERMISSION_MANAGER_STATUS_OK = 0,
/**
@@ -85,3 +96,5 @@
__END_DECLS
#endif // ANDROID_PERMISSION_MANAGER_H
+
+/** @} */
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index 98fd875..b836581 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -67,9 +67,21 @@
__INTRODUCED_IN(29);
/**
- * Releases the \a surface_control object. After releasing the ASurfaceControl the caller no longer
- * has ownership of the AsurfaceControl. The surface and it's children may remain on display as long
- * as their parent remains on display.
+ * Acquires a reference on the given ASurfaceControl object. This prevents the object
+ * from being deleted until the reference is removed.
+ *
+ * To release the reference, use the ASurfaceControl_release function.
+ *
+ * Available since API level 31.
+ */
+void ASurfaceControl_acquire(ASurfaceControl* surface_control) __INTRODUCED_IN(31);
+
+/**
+ * Removes a reference that was previously acquired with one of the following functions:
+ * ASurfaceControl_createFromWindow
+ * ASurfaceControl_create
+ * ANativeWindow_acquire
+ * The surface and its children may remain on display as long as their parent remains on display.
*
* Available since API level 29.
*/
diff --git a/include/private/surface_control_private.h b/include/private/surface_control_private.h
new file mode 100644
index 0000000..37a476e
--- /dev/null
+++ b/include/private/surface_control_private.h
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_PRIVATE_NATIVE_SURFACE_CONTROL_H
+#define ANDROID_PRIVATE_NATIVE_SURFACE_CONTROL_H
+
+#include <stdint.h>
+
+__BEGIN_DECLS
+
+struct ASurfaceControl;
+struct ASurfaceControlStats;
+
+typedef struct ASurfaceControlStats ASurfaceControlStats;
+
+/**
+ * Callback to be notified when surface stats for a specific surface control are available.
+ */
+typedef void (*ASurfaceControl_SurfaceStatsListener)(void* context,
+ ASurfaceControl* control, ASurfaceControlStats* stats);
+
+/**
+ * Registers a callback to be invoked when surface stats from a specific surface are available.
+ *
+ * \param context Optional context provided by the client that is passed into
+ * the callback.
+ *
+ * \param control The surface to retrieve callbacks for.
+ *
+ * \param func The callback to be invoked when surface stats are available.
+ */
+void ASurfaceControl_registerSurfaceStatsListener(ASurfaceControl* control, void* context,
+ ASurfaceControl_SurfaceStatsListener func);
+
+/**
+ * Unregisters a callback to be invoked when surface stats from a specific surface are available.
+ *
+ * \param context The context passed into ASurfaceControl_registerSurfaceStatsListener
+ *
+ * \param func The callback passed into ASurfaceControl_registerSurfaceStatsListener
+ */
+void ASurfaceControl_unregisterSurfaceStatsListener(void* context,
+ ASurfaceControl_SurfaceStatsListener func);
+
+/**
+ * Returns the timestamp of when the buffer was acquired for a specific frame with frame number
+ * obtained from ASurfaceControlStats_getFrameNumber.
+ */
+int64_t ASurfaceControlStats_getAcquireTime(ASurfaceControlStats* stats);
+
+/**
+ * Returns the frame number of the surface stats object passed into the callback.
+ */
+uint64_t ASurfaceControlStats_getFrameNumber(ASurfaceControlStats* stats);
+
+__END_DECLS
+
+#endif //ANDROID_PRIVATE_NATIVE_SURFACE_CONTROL_H
diff --git a/libs/adbd_auth/Android.bp b/libs/adbd_auth/Android.bp
index 8883c04..16cded8 100644
--- a/libs/adbd_auth/Android.bp
+++ b/libs/adbd_auth/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library {
name: "libadbd_auth",
cflags: [
diff --git a/libs/android_runtime_lazy/Android.bp b/libs/android_runtime_lazy/Android.bp
index cdd7764..b74923c 100644
--- a/libs/android_runtime_lazy/Android.bp
+++ b/libs/android_runtime_lazy/Android.bp
@@ -30,6 +30,15 @@
// instead of libandroid_runtime. When they are used by a vendor process,
// depending on libandroid_runtime is meaningless. In this case,
// they can depend on libandroid_runtime_lazy.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library {
name: "libandroid_runtime_lazy",
vendor_available: true,
diff --git a/libs/arect/Android.bp b/libs/arect/Android.bp
index 80aa891..bb40f51 100644
--- a/libs/arect/Android.bp
+++ b/libs/arect/Android.bp
@@ -12,6 +12,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ default_applicable_licenses: ["frameworks_native_libs_arect_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_libs_arect_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
ndk_headers {
name: "libarect_headers_for_ndk",
from: "include/android",
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index b585ad2..e9d866b 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "libbinder_headers",
export_include_dirs: ["include"],
diff --git a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
index 889e15a..a7a6563 100644
--- a/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
+++ b/libs/binder/aidl/android/content/pm/IPackageManagerNative.aidl
@@ -108,4 +108,10 @@
* has been set to {@link PackageManager#CERT_INPUT_SHA256}.
*/
boolean hasSha256SigningCertificate(in @utf8InCpp String packageName, in byte[] certificate);
+
+ /**
+ * Returns the debug flag for the given package.
+ * Unknown packages will cause the call to fail.
+ */
+ boolean isPackageDebuggable(in String packageName);
}
diff --git a/libs/binder/ndk/Android.bp b/libs/binder/ndk/Android.bp
index 897c72a..eb103d3 100644
--- a/libs/binder/ndk/Android.bp
+++ b/libs/binder/ndk/Android.bp
@@ -15,6 +15,23 @@
*/
// TODO(b/31559095): bionic on host should define this
+package {
+ default_applicable_licenses: ["frameworks_native_libs_binder_ndk_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_libs_binder_ndk_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_defaults {
name: "libbinder_ndk_host_user",
target: {
diff --git a/libs/binder/ndk/include_cpp/android/binder_to_string.h b/libs/binder/ndk/include_cpp/android/binder_to_string.h
index bd51b11..5842925 100644
--- a/libs/binder/ndk/include_cpp/android/binder_to_string.h
+++ b/libs/binder/ndk/include_cpp/android/binder_to_string.h
@@ -28,10 +28,22 @@
#include <codecvt>
#include <locale>
+#include <memory>
+#include <optional>
#include <sstream>
#include <string>
#include <type_traits>
+#if __has_include(<utils/StrongPointer.h>)
+#include <utils/StrongPointer.h>
+#define HAS_STRONG_POINTER
+#endif
+
+#if __has_include(<utils/String16.h>)
+#include <utils/String16.h>
+#define HAS_STRING16
+#endif
+
#if __has_include(<android/binder_ibinder.h>)
#include <android/binder_auto_utils.h>
#include <android/binder_interface_utils.h>
@@ -42,9 +54,6 @@
#include <binder/IInterface.h>
#include <binder/ParcelFileDescriptor.h>
#include <binder/ParcelableHolder.h>
-#include <utils/String16.h>
-#include <utils/StrongPointer.h>
-#define HAS_CPP_INTERFACE
#endif //_has_include
namespace android {
@@ -80,11 +89,28 @@
enum { value = decltype(_test<_T>(0))::value };
};
-// Truthy if _T is like a pointer
+template <typename T, template <typename...> typename U>
+struct IsInstantiationOf : std::false_type {};
+
+template <template <typename...> typename U, typename... Args>
+struct IsInstantiationOf<U<Args...>, U> : std::true_type {};
+
+// Truthy if _T is like a pointer: one of sp/optional/shared_ptr
template <typename _T>
class IsPointerLike {
template <typename _U>
- static auto _test(int) -> decltype(!std::declval<_U>(), *std::declval<_U>(), std::true_type());
+ static std::enable_if_t<
+#ifdef HAS_STRONG_POINTER
+ IsInstantiationOf<_U, sp>::value || // for IBinder and interface types in the C++
+ // backend
+#endif
+ IsInstantiationOf<_U, std::optional>::value || // for @nullable types in the
+ // C++/NDK backends
+ IsInstantiationOf<_U, std::shared_ptr>::value, // for interface types in the
+ // NDK backends
+
+ std::true_type>
+ _test(int);
template <typename _U>
static std::false_type _test(...);
@@ -142,12 +168,17 @@
return std::to_string(t);
} else if constexpr (std::is_same_v<std::string, _T>) {
return t;
-#ifdef HAS_CPP_INTERFACE
+#ifdef HAS_STRING16
} else if constexpr (std::is_same_v<String16, _T>) {
std::stringstream out;
out << t;
return out.str();
#endif
+ } else if constexpr (details::IsPointerLike<_T>::value) {
+ if (!t) return "(null)";
+ std::stringstream out;
+ out << ToString(*t);
+ return out.str();
} else if constexpr (details::HasToStringMethod<_T>::value) {
return t.toString();
} else if constexpr (details::HasToStringFunction<_T>::value) {
@@ -168,11 +199,6 @@
}
out << "]";
return out.str();
- } else if constexpr (details::IsPointerLike<_T>::value) {
- if (!t) return "(null)";
- std::stringstream out;
- out << ToString(*t);
- return out.str();
} else {
return "{no toString() implemented}";
}
diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
index 2784aa8..4580751 100644
--- a/libs/binder/ndk/include_platform/android/binder_manager.h
+++ b/libs/binder/ndk/include_platform/android/binder_manager.h
@@ -31,7 +31,8 @@
*
* \return EX_NONE on success.
*/
-binder_exception_t AServiceManager_addService(AIBinder* binder, const char* instance);
+__attribute__((warn_unused_result)) binder_exception_t AServiceManager_addService(
+ AIBinder* binder, const char* instance);
/**
* Gets a binder object with this specific instance name. Will return nullptr immediately if the
@@ -94,4 +95,52 @@
*/
bool AServiceManager_isDeclared(const char* instance) __INTRODUCED_IN(31);
+/**
+ * Prevent lazy services without client from shutting down their process
+ *
+ * \param persist 'true' if the process should not exit.
+ */
+void AServiceManager_forceLazyServicesPersist(bool persist) __INTRODUCED_IN(31);
+
+/**
+ * Set a callback that is invoked when the active service count (i.e. services with clients)
+ * registered with this process drops to zero (or becomes nonzero).
+ * The callback takes a boolean argument, which is 'true' if there is
+ * at least one service with clients.
+ *
+ * \param callback function to call when the number of services
+ * with clients changes.
+ * \param context opaque pointer passed back as second parameter to the
+ * callback.
+ *
+ * The callback takes two arguments. The first is a boolean that represents if there are
+ * services with clients (true) or not (false).
+ * The second is the 'context' pointer passed during the registration.
+ *
+ * Callback return value:
+ * - false: Default behavior for lazy services (shut down the process if there
+ * are no clients).
+ * - true: Don't shut down the process even if there are no clients.
+ *
+ * This callback gives a chance to:
+ * 1 - Perform some additional operations before exiting;
+ * 2 - Prevent the process from exiting by returning "true" from the callback.
+ */
+void AServiceManager_setActiveServicesCallback(bool (*callback)(bool, void*), void* context)
+ __INTRODUCED_IN(31);
+
+/**
+ * Try to unregister all services previously registered with 'registerService'.
+ *
+ * \return true on success.
+ */
+bool AServiceManager_tryUnregister() __INTRODUCED_IN(31);
+
+/**
+ * Re-register services that were unregistered by 'tryUnregister'.
+ * This method should be called in the case 'tryUnregister' fails
+ * (and should be called on the same thread).
+ */
+void AServiceManager_reRegister() __INTRODUCED_IN(31);
+
__END_DECLS
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 9a93bf3..cef0bf3 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -120,6 +120,10 @@
AServiceManager_isDeclared; # apex llndk
AServiceManager_registerLazyService; # llndk
AServiceManager_waitForService; # apex llndk
+ AServiceManager_forceLazyServicesPersist; # llndk
+ AServiceManager_setActiveServicesCallback; # llndk
+ AServiceManager_tryUnregister; # llndk
+ AServiceManager_reRegister; # llndk
AIBinder_Class_getDescriptor;
AIBinder_Weak_clone;
diff --git a/libs/binder/ndk/service_manager.cpp b/libs/binder/ndk/service_manager.cpp
index c782d47..cb0987e 100644
--- a/libs/binder/ndk/service_manager.cpp
+++ b/libs/binder/ndk/service_manager.cpp
@@ -92,3 +92,22 @@
sp<IServiceManager> sm = defaultServiceManager();
return sm->isDeclared(String16(instance));
}
+void AServiceManager_forceLazyServicesPersist(bool persist) {
+ auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
+ serviceRegistrar.forcePersist(persist);
+}
+void AServiceManager_setActiveServicesCallback(bool (*callback)(bool, void*), void* context) {
+ auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
+ std::function<bool(bool)> fn = [=](bool hasClients) -> bool {
+ return callback(hasClients, context);
+ };
+ serviceRegistrar.setActiveServicesCallback(fn);
+}
+bool AServiceManager_tryUnregister() {
+ auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
+ return serviceRegistrar.tryUnregister();
+}
+void AServiceManager_reRegister() {
+ auto serviceRegistrar = android::binder::LazyServiceRegistrar::getInstance();
+ serviceRegistrar.reRegister();
+}
\ No newline at end of file
diff --git a/libs/binder/ndk/tests/Android.bp b/libs/binder/ndk/tests/Android.bp
index 46e6270..bb51bf0 100644
--- a/libs/binder/ndk/tests/Android.bp
+++ b/libs/binder/ndk/tests/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_libs_binder_ndk_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_libs_binder_ndk_license"],
+}
+
cc_defaults {
name: "test_libbinder_ndk_defaults",
shared_libs: [
diff --git a/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl b/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl
index dc77467d..ecbd649 100644
--- a/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl
+++ b/libs/binder/ndk/tests/IBinderNdkUnitTest.aidl
@@ -28,4 +28,7 @@
void forceFlushCommands();
boolean getsRequestedSid();
+
+ void forcePersist(boolean persist);
+ void setCustomActiveServicesCallback();
}
diff --git a/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp b/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp
index ad78e31..f3cd218 100644
--- a/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp
+++ b/libs/binder/ndk/tests/binderVendorDoubleLoadTest.cpp
@@ -163,7 +163,8 @@
// LOCAL SERVERS
std::shared_ptr<NdkServer> ndkServer = SharedRefBase::make<NdkServer>();
- AServiceManager_addService(ndkServer->asBinder().get(), kLocalNdkServerName.c_str());
+ CHECK(STATUS_OK ==
+ AServiceManager_addService(ndkServer->asBinder().get(), kLocalNdkServerName.c_str()));
return RUN_ALL_TESTS();
}
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index 0d1989e..de1a48d 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -46,6 +46,11 @@
constexpr char kExistingNonNdkService[] = "SurfaceFlinger";
constexpr char kBinderNdkUnitTestService[] = "BinderNdkUnitTest";
constexpr char kLazyBinderNdkUnitTestService[] = "LazyBinderNdkUnitTest";
+constexpr char kForcePersistNdkUnitTestService[] = "ForcePersistNdkUnitTestService";
+constexpr char kActiveServicesNdkUnitTestService[] = "ActiveServicesNdkUnitTestService";
+
+constexpr unsigned int kShutdownWaitTime = 10;
+constexpr uint64_t kContextTestValue = 0xb4e42fb4d9a1d715;
class MyBinderNdkUnitTest : public aidl::BnBinderNdkUnitTest {
ndk::ScopedAStatus repeatInt(int32_t in, int32_t* out) {
@@ -76,6 +81,46 @@
fsync(out);
return STATUS_OK;
}
+ ndk::ScopedAStatus forcePersist(bool persist) {
+ AServiceManager_forceLazyServicesPersist(persist);
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus setCustomActiveServicesCallback() {
+ AServiceManager_setActiveServicesCallback(activeServicesCallback, this);
+ return ndk::ScopedAStatus::ok();
+ }
+ static bool activeServicesCallback(bool hasClients, void* context) {
+ if (hasClients) {
+ return false;
+ }
+
+ // Unregister all services
+ if (!AServiceManager_tryUnregister()) {
+ // Prevent shutdown (test will fail)
+ return false;
+ }
+
+ // Re-register all services
+ AServiceManager_reRegister();
+
+ // Unregister again before shutdown
+ if (!AServiceManager_tryUnregister()) {
+ // Prevent shutdown (test will fail)
+ return false;
+ }
+
+ // Check if the context was passed correctly
+ MyBinderNdkUnitTest* service = static_cast<MyBinderNdkUnitTest*>(context);
+ if (service->contextTestValue != kContextTestValue) {
+ // Prevent shutdown (test will fail)
+ return false;
+ }
+
+ exit(EXIT_SUCCESS);
+ // Unreachable
+ }
+
+ uint64_t contextTestValue = kContextTestValue;
};
int generatedService() {
@@ -168,6 +213,16 @@
return 1; // should not return
}
+bool isServiceRunning(const char* serviceName) {
+ AIBinder* binder = AServiceManager_checkService(serviceName);
+ if (binder == nullptr) {
+ return false;
+ }
+ AIBinder_decStrong(binder);
+
+ return true;
+}
+
TEST(NdkBinder, GetServiceThatDoesntExist) {
sp<IFoo> foo = IFoo::getService("asdfghkl;");
EXPECT_EQ(nullptr, foo.get());
@@ -238,10 +293,51 @@
service = nullptr;
IPCThreadState::self()->flushCommands();
// Make sure the service is dead after some time of no use
- sleep(10);
+ sleep(kShutdownWaitTime);
ASSERT_EQ(nullptr, AServiceManager_checkService(kLazyBinderNdkUnitTestService));
}
+TEST(NdkBinder, ForcedPersistenceTest) {
+ for (int i = 0; i < 2; i++) {
+ ndk::SpAIBinder binder(AServiceManager_waitForService(kForcePersistNdkUnitTestService));
+ std::shared_ptr<aidl::IBinderNdkUnitTest> service =
+ aidl::IBinderNdkUnitTest::fromBinder(binder);
+ ASSERT_NE(service, nullptr);
+ ASSERT_TRUE(service->forcePersist(i == 0).isOk());
+
+ binder = nullptr;
+ service = nullptr;
+ IPCThreadState::self()->flushCommands();
+
+ sleep(kShutdownWaitTime);
+
+ bool isRunning = isServiceRunning(kForcePersistNdkUnitTestService);
+
+ if (i == 0) {
+ ASSERT_TRUE(isRunning) << "Service shut down when it shouldn't have.";
+ } else {
+ ASSERT_FALSE(isRunning) << "Service failed to shut down.";
+ }
+ }
+}
+
+TEST(NdkBinder, ActiveServicesCallbackTest) {
+ ndk::SpAIBinder binder(AServiceManager_waitForService(kActiveServicesNdkUnitTestService));
+ std::shared_ptr<aidl::IBinderNdkUnitTest> service =
+ aidl::IBinderNdkUnitTest::fromBinder(binder);
+ ASSERT_NE(service, nullptr);
+ ASSERT_TRUE(service->setCustomActiveServicesCallback().isOk());
+
+ binder = nullptr;
+ service = nullptr;
+ IPCThreadState::self()->flushCommands();
+
+ sleep(kShutdownWaitTime);
+
+ ASSERT_FALSE(isServiceRunning(kActiveServicesNdkUnitTestService))
+ << "Service failed to shut down.";
+}
+
void LambdaOnDeath(void* cookie) {
auto onDeath = static_cast<std::function<void(void)>*>(cookie);
(*onDeath)();
@@ -564,10 +660,18 @@
}
if (fork() == 0) {
prctl(PR_SET_PDEATHSIG, SIGHUP);
+ return lazyService(kForcePersistNdkUnitTestService);
+ }
+ if (fork() == 0) {
+ prctl(PR_SET_PDEATHSIG, SIGHUP);
+ return lazyService(kActiveServicesNdkUnitTestService);
+ }
+ if (fork() == 0) {
+ prctl(PR_SET_PDEATHSIG, SIGHUP);
return generatedService();
}
- ABinderProcess_setThreadPoolMaxThreadCount(1); // to recieve death notifications/callbacks
+ ABinderProcess_setThreadPoolMaxThreadCount(1); // to receive death notifications/callbacks
ABinderProcess_startThreadPool();
return RUN_ALL_TESTS();
diff --git a/libs/binder/parcel_fuzzer/Android.bp b/libs/binder/parcel_fuzzer/Android.bp
index 3e6fe99..74b8eb8 100644
--- a/libs/binder/parcel_fuzzer/Android.bp
+++ b/libs/binder/parcel_fuzzer/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_fuzz {
name: "binder_parcel_fuzzer",
defaults: ["libbinder_ndk_host_user"],
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp
index fd5f2f5..e12a429 100644
--- a/libs/binder/rust/Android.bp
+++ b/libs/binder/rust/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
rust_library {
name: "libbinder_rs",
crate_name: "binder",
@@ -14,7 +23,11 @@
darwin: {
enabled: false,
}
- }
+ },
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.virt",
+ ],
}
rust_library {
@@ -32,7 +45,11 @@
darwin: {
enabled: false,
}
- }
+ },
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.virt",
+ ],
}
rust_bindgen {
@@ -78,6 +95,10 @@
enabled: false,
},
},
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.virt",
+ ],
}
rust_test {
diff --git a/libs/binder/rust/tests/Android.bp b/libs/binder/rust/tests/Android.bp
index 8810b5d..0bf76c6 100644
--- a/libs/binder/rust/tests/Android.bp
+++ b/libs/binder/rust/tests/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
rust_test {
name: "rustBinderTest",
srcs: ["integration.rs"],
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 259417a..3bbb0b5 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "binder_test_defaults",
cflags: [
diff --git a/libs/binder/tests/fuzzers/Android.bp b/libs/binder/tests/fuzzers/Android.bp
index 5531296..b1263e8 100644
--- a/libs/binder/tests/fuzzers/Android.bp
+++ b/libs/binder/tests/fuzzers/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "binder_fuzz_defaults",
host_supported: true,
diff --git a/libs/binderdebug/Android.bp b/libs/binderdebug/Android.bp
index 343246a..3eeaf3e 100644
--- a/libs/binderdebug/Android.bp
+++ b/libs/binderdebug/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library {
name: "libbinderdebug",
vendor_available: true,
diff --git a/libs/binderdebug/tests/Android.bp b/libs/binderdebug/tests/Android.bp
index 4c06b1d..d141a05 100644
--- a/libs/binderdebug/tests/Android.bp
+++ b/libs/binderdebug/tests/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "libbinderdebug_test",
test_suites: ["general-tests"],
diff --git a/libs/binderthreadstate/1.0/Android.bp b/libs/binderthreadstate/1.0/Android.bp
index ebdc932..99477d8 100644
--- a/libs/binderthreadstate/1.0/Android.bp
+++ b/libs/binderthreadstate/1.0/Android.bp
@@ -1,5 +1,14 @@
// This file is autogenerated by hidl-gen -Landroidbp.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
hidl_interface {
name: "binderthreadstateutilstest@1.0",
root: "binderthreadstateutilstest",
diff --git a/libs/binderthreadstate/Android.bp b/libs/binderthreadstate/Android.bp
index 08c62df..0a82463 100644
--- a/libs/binderthreadstate/Android.bp
+++ b/libs/binderthreadstate/Android.bp
@@ -14,6 +14,15 @@
// DO NOT ADD NEW USAGES OF THIS
// See comments in header file.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_static {
name: "libbinderthreadstateutils",
double_loadable: true,
diff --git a/libs/bufferqueueconverter/Android.bp b/libs/bufferqueueconverter/Android.bp
index bab2674..c5d3a32 100644
--- a/libs/bufferqueueconverter/Android.bp
+++ b/libs/bufferqueueconverter/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "libbufferqueueconverter_headers",
vendor_available: true,
diff --git a/libs/cputimeinstate/Android.bp b/libs/cputimeinstate/Android.bp
index e3cd085..570af71 100644
--- a/libs/cputimeinstate/Android.bp
+++ b/libs/cputimeinstate/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library {
name: "libtimeinstate",
srcs: ["cputimeinstate.cpp"],
@@ -35,4 +44,3 @@
],
require_root: true,
}
-
diff --git a/libs/diskusage/Android.bp b/libs/diskusage/Android.bp
index a826306..8684061 100644
--- a/libs/diskusage/Android.bp
+++ b/libs/diskusage/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_static {
name: "libdiskusage",
srcs: ["dirsize.c"],
diff --git a/libs/dumputils/Android.bp b/libs/dumputils/Android.bp
index e403d36..acda402 100644
--- a/libs/dumputils/Android.bp
+++ b/libs/dumputils/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library {
name: "libdumputils",
diff --git a/libs/fakeservicemanager/Android.bp b/libs/fakeservicemanager/Android.bp
index 76518c1..47c0657 100644
--- a/libs/fakeservicemanager/Android.bp
+++ b/libs/fakeservicemanager/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "fakeservicemanager_defaults",
host_supported: true,
diff --git a/libs/gralloc/types/Android.bp b/libs/gralloc/types/Android.bp
index dd0ae30..a0032ae 100644
--- a/libs/gralloc/types/Android.bp
+++ b/libs/gralloc/types/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library {
name: "libgralloctypes",
defaults: ["libbinder_ndk_host_user"],
diff --git a/libs/gralloc/types/fuzzer/Android.bp b/libs/gralloc/types/fuzzer/Android.bp
index 8933dc3..6689771 100644
--- a/libs/gralloc/types/fuzzer/Android.bp
+++ b/libs/gralloc/types/fuzzer/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_fuzz {
name: "libgralloctypes_fuzzer",
defaults: ["libbinder_ndk_host_user"],
diff --git a/libs/gralloc/types/tests/Android.bp b/libs/gralloc/types/tests/Android.bp
index b939c1d..66eb0aa 100644
--- a/libs/gralloc/types/tests/Android.bp
+++ b/libs/gralloc/types/tests/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "GrallocTypes_test",
shared_libs: [
diff --git a/libs/graphicsenv/Android.bp b/libs/graphicsenv/Android.bp
index 642c5f2..a96a07a 100644
--- a/libs/graphicsenv/Android.bp
+++ b/libs/graphicsenv/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libgraphicsenv",
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index fa5044c..debd664 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -11,6 +11,15 @@
// 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "libgui_headers",
vendor_available: true,
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 1e6fc2b..82c9268 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -55,7 +55,7 @@
ALOGE("[%s](f:%u,a:%u) " x, mName.c_str(), mNumFrameAvailable, mNumAcquired, ##__VA_ARGS__)
void BLASTBufferItemConsumer::onDisconnect() {
- Mutex::Autolock lock(mFrameEventHistoryMutex);
+ Mutex::Autolock lock(mMutex);
mPreviouslyConnected = mCurrentlyConnected;
mCurrentlyConnected = false;
if (mPreviouslyConnected) {
@@ -66,7 +66,7 @@
void BLASTBufferItemConsumer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
FrameEventHistoryDelta* outDelta) {
- Mutex::Autolock lock(mFrameEventHistoryMutex);
+ Mutex::Autolock lock(mMutex);
if (newTimestamps) {
// BufferQueueProducer only adds a new timestamp on
// queueBuffer
@@ -90,7 +90,7 @@
const sp<Fence>& prevReleaseFence,
CompositorTiming compositorTiming,
nsecs_t latchTime, nsecs_t dequeueReadyTime) {
- Mutex::Autolock lock(mFrameEventHistoryMutex);
+ Mutex::Autolock lock(mMutex);
// if the producer is not connected, don't bother updating,
// the next producer that connects won't access this frame event
@@ -108,7 +108,7 @@
void BLASTBufferItemConsumer::getConnectionEvents(uint64_t frameNumber, bool* needsDisconnect) {
bool disconnect = false;
- Mutex::Autolock lock(mFrameEventHistoryMutex);
+ Mutex::Autolock lock(mMutex);
while (!mDisconnectEvents.empty() && mDisconnectEvents.front() <= frameNumber) {
disconnect = true;
mDisconnectEvents.pop();
@@ -116,6 +116,19 @@
if (needsDisconnect != nullptr) *needsDisconnect = disconnect;
}
+void BLASTBufferItemConsumer::setBlastBufferQueue(BLASTBufferQueue* blastbufferqueue) {
+ Mutex::Autolock lock(mMutex);
+ mBLASTBufferQueue = blastbufferqueue;
+}
+
+void BLASTBufferItemConsumer::onSidebandStreamChanged() {
+ Mutex::Autolock lock(mMutex);
+ if (mBLASTBufferQueue != nullptr) {
+ sp<NativeHandle> stream = getSidebandStream();
+ mBLASTBufferQueue->setSidebandStream(stream);
+ }
+}
+
BLASTBufferQueue::BLASTBufferQueue(const std::string& name, const sp<SurfaceControl>& surface,
int width, int height, int32_t format,
bool enableTripleBuffering)
@@ -145,6 +158,7 @@
mBufferItemConsumer->setBufferFreedListener(this);
mBufferItemConsumer->setDefaultBufferSize(mSize.width, mSize.height);
mBufferItemConsumer->setDefaultBufferFormat(convertBufferFormat(format));
+ mBufferItemConsumer->setBlastBufferQueue(this);
mTransformHint = mSurfaceControl->getTransformHint();
mBufferItemConsumer->setTransformHint(mTransformHint);
@@ -160,6 +174,7 @@
}
BLASTBufferQueue::~BLASTBufferQueue() {
+ mBufferItemConsumer->setBlastBufferQueue(nullptr);
if (mPendingTransactions.empty()) {
return;
}
@@ -557,6 +572,13 @@
return OK;
}
+void BLASTBufferQueue::setSidebandStream(const sp<NativeHandle>& stream) {
+ std::unique_lock _lock{mMutex};
+ SurfaceComposerClient::Transaction t;
+
+ t.setSidebandStream(mSurfaceControl, stream).apply();
+}
+
sp<Surface> BLASTBufferQueue::getSurface(bool includeSurfaceControlHandle) {
std::unique_lock _lock{mMutex};
sp<IBinder> scHandle = nullptr;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 27fb2a8..d41da9b 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -194,6 +194,25 @@
}
}
+void TransactionCompletedListener::addSurfaceStatsListener(void* context, void* cookie,
+ sp<SurfaceControl> surfaceControl, SurfaceStatsCallback listener) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mSurfaceStatsListeners.insert({surfaceControl->getHandle(),
+ SurfaceStatsCallbackEntry(context, cookie, listener)});
+}
+
+void TransactionCompletedListener::removeSurfaceStatsListener(void* context, void* cookie) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ for (auto it = mSurfaceStatsListeners.begin(); it != mSurfaceStatsListeners.end();) {
+ auto [itContext, itCookie, itListener] = it->second;
+ if (itContext == context && itCookie == cookie) {
+ it = mSurfaceStatsListeners.erase(it);
+ } else {
+ it++;
+ }
+ }
+}
+
void TransactionCompletedListener::addSurfaceControlToCallbacks(
const sp<SurfaceControl>& surfaceControl,
const std::unordered_set<CallbackId>& callbackIds) {
@@ -210,6 +229,7 @@
void TransactionCompletedListener::onTransactionCompleted(ListenerStats listenerStats) {
std::unordered_map<CallbackId, CallbackTranslation> callbacksMap;
std::multimap<sp<IBinder>, sp<JankDataListener>> jankListenersMap;
+ std::multimap<sp<IBinder>, SurfaceStatsCallbackEntry> surfaceListeners;
{
std::lock_guard<std::mutex> lock(mMutex);
@@ -226,6 +246,7 @@
*/
callbacksMap = mCallbacks;
jankListenersMap = mJankListeners;
+ surfaceListeners = mSurfaceStatsListeners;
for (const auto& transactionStats : listenerStats.transactionStats) {
for (auto& callbackId : transactionStats.callbackIds) {
mCallbacks.erase(callbackId);
@@ -259,9 +280,16 @@
surfaceControlStats);
}
for (const auto& surfaceStats : transactionStats.surfaceStats) {
+ auto listenerRange = surfaceListeners.equal_range(surfaceStats.surfaceControl);
+ for (auto it = listenerRange.first; it != listenerRange.second; it++) {
+ auto entry = it->second;
+ entry.callback(entry.context, transactionStats.latchTime,
+ transactionStats.presentFence, surfaceStats);
+ }
+
if (surfaceStats.jankData.empty()) continue;
- for (auto it = jankListenersMap.find(surfaceStats.surfaceControl);
- it != jankListenersMap.end(); it++) {
+ auto jankRange = jankListenersMap.equal_range(surfaceStats.surfaceControl);
+ for (auto it = jankRange.first; it != jankRange.second; it++) {
it->second->onJankDataAvailable(surfaceStats.jankData);
}
}
diff --git a/libs/gui/include/gui/BLASTBufferQueue.h b/libs/gui/include/gui/BLASTBufferQueue.h
index bccb71b..dd8e714 100644
--- a/libs/gui/include/gui/BLASTBufferQueue.h
+++ b/libs/gui/include/gui/BLASTBufferQueue.h
@@ -32,6 +32,7 @@
namespace android {
+class BLASTBufferQueue;
class BufferItemConsumer;
class BLASTBufferItemConsumer : public BufferItemConsumer {
@@ -40,27 +41,32 @@
int bufferCount, bool controlledByApp)
: BufferItemConsumer(consumer, consumerUsage, bufferCount, controlledByApp),
mCurrentlyConnected(false),
- mPreviouslyConnected(false) {}
+ mPreviouslyConnected(false),
+ mBLASTBufferQueue(nullptr) {}
void onDisconnect() override;
void addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
- FrameEventHistoryDelta* outDelta) override
- REQUIRES(mFrameEventHistoryMutex);
+ FrameEventHistoryDelta* outDelta) override REQUIRES(mMutex);
void updateFrameTimestamps(uint64_t frameNumber, nsecs_t refreshStartTime,
const sp<Fence>& gpuCompositionDoneFence,
const sp<Fence>& presentFence, const sp<Fence>& prevReleaseFence,
CompositorTiming compositorTiming, nsecs_t latchTime,
- nsecs_t dequeueReadyTime) REQUIRES(mFrameEventHistoryMutex);
+ nsecs_t dequeueReadyTime) REQUIRES(mMutex);
void getConnectionEvents(uint64_t frameNumber, bool* needsDisconnect);
+ void setBlastBufferQueue(BLASTBufferQueue* blastbufferqueue) REQUIRES(mMutex);
+
+protected:
+ void onSidebandStreamChanged() override REQUIRES(mMutex);
private:
uint64_t mCurrentFrameNumber = 0;
- Mutex mFrameEventHistoryMutex;
- ConsumerFrameEventHistory mFrameEventHistory GUARDED_BY(mFrameEventHistoryMutex);
- std::queue<uint64_t> mDisconnectEvents GUARDED_BY(mFrameEventHistoryMutex);
- bool mCurrentlyConnected GUARDED_BY(mFrameEventHistoryMutex);
- bool mPreviouslyConnected GUARDED_BY(mFrameEventHistoryMutex);
+ Mutex mMutex;
+ ConsumerFrameEventHistory mFrameEventHistory GUARDED_BY(mMutex);
+ std::queue<uint64_t> mDisconnectEvents GUARDED_BY(mMutex);
+ bool mCurrentlyConnected GUARDED_BY(mMutex);
+ bool mPreviouslyConnected GUARDED_BY(mMutex);
+ BLASTBufferQueue* mBLASTBufferQueue GUARDED_BY(mMutex);
};
class BLASTBufferQueue
@@ -94,6 +100,8 @@
status_t setFrameRate(float frameRate, int8_t compatibility, bool shouldBeSeamless);
status_t setFrameTimelineInfo(const FrameTimelineInfo& info);
+ void setSidebandStream(const sp<NativeHandle>& stream);
+
virtual ~BLASTBufferQueue();
private:
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index e89f3a7..8de7574 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -80,6 +80,10 @@
using TransactionCompletedCallback =
std::function<void(nsecs_t /*latchTime*/, const sp<Fence>& /*presentFence*/,
const std::vector<SurfaceControlStats>& /*stats*/)>;
+using SurfaceStatsCallback =
+ std::function<void(void* /*context*/, nsecs_t /*latchTime*/,
+ const sp<Fence>& /*presentFence*/,
+ const SurfaceStats& /*stats*/)>;
// ---------------------------------------------------------------------------
@@ -650,8 +654,21 @@
surfaceControls;
};
+ struct SurfaceStatsCallbackEntry {
+ SurfaceStatsCallbackEntry(void* context, void* cookie, SurfaceStatsCallback callback)
+ : context(context),
+ cookie(cookie),
+ callback(callback) {}
+
+ void* context;
+ void* cookie;
+ SurfaceStatsCallback callback;
+ };
+
std::unordered_map<CallbackId, CallbackTranslation> mCallbacks GUARDED_BY(mMutex);
std::multimap<sp<IBinder>, sp<JankDataListener>> mJankListeners GUARDED_BY(mMutex);
+ std::multimap<sp<IBinder>, SurfaceStatsCallbackEntry>
+ mSurfaceStatsListeners GUARDED_BY(mMutex);
public:
static sp<TransactionCompletedListener> getInstance();
@@ -679,6 +696,10 @@
*/
void removeJankListener(const sp<JankDataListener>& listener);
+ void addSurfaceStatsListener(void* context, void* cookie, sp<SurfaceControl> surfaceControl,
+ SurfaceStatsCallback listener);
+ void removeSurfaceStatsListener(void* context, void* cookie);
+
// Overrides BnTransactionCompletedListener's onTransactionCompleted
void onTransactionCompleted(ListenerStats stats) override;
};
diff --git a/libs/gui/sysprop/Android.bp b/libs/gui/sysprop/Android.bp
index 64b1eac..bddb0ac 100644
--- a/libs/gui/sysprop/Android.bp
+++ b/libs/gui/sysprop/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
sysprop_library {
name: "LibGuiProperties",
srcs: ["*.sysprop"],
diff --git a/libs/gui/tests/Android.bp b/libs/gui/tests/Android.bp
index 53c13c8..c801c62 100644
--- a/libs/gui/tests/Android.bp
+++ b/libs/gui/tests/Android.bp
@@ -2,6 +2,15 @@
// Build the binary to $(TARGET_OUT_DATA_NATIVE_TESTS)/$(LOCAL_MODULE)
// to integrate with auto-test framework.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "libgui_test",
test_suites: ["device-tests"],
diff --git a/libs/gui/tests/BLASTBufferQueue_test.cpp b/libs/gui/tests/BLASTBufferQueue_test.cpp
index 5447b76..fb07a19 100644
--- a/libs/gui/tests/BLASTBufferQueue_test.cpp
+++ b/libs/gui/tests/BLASTBufferQueue_test.cpp
@@ -129,7 +129,11 @@
}
void setUpProducer(BLASTBufferQueueHelper adapter, sp<IGraphicBufferProducer>& producer) {
- auto igbProducer = adapter.getIGraphicBufferProducer();
+ producer = adapter.getIGraphicBufferProducer();
+ setUpProducer(producer);
+ }
+
+ void setUpProducer(sp<IGraphicBufferProducer>& igbProducer) {
ASSERT_NE(nullptr, igbProducer.get());
ASSERT_EQ(NO_ERROR, igbProducer->setMaxDequeuedBufferCount(2));
IGraphicBufferProducer::QueueBufferOutput qbOutput;
@@ -137,7 +141,6 @@
igbProducer->connect(new StubProducerListener, NATIVE_WINDOW_API_CPU, false,
&qbOutput));
ASSERT_NE(ui::Transform::ROT_INVALID, qbOutput.transformHint);
- producer = igbProducer;
}
void fillBuffer(uint32_t* bufData, Rect rect, uint32_t stride, uint8_t r, uint8_t g,
@@ -555,6 +558,8 @@
ASSERT_EQ(queuesToNativeWindow, 1);
}
+// Test a slow producer doesn't hold up a faster producer from the same client. Essentially tests
+// BBQ uses separate transaction queues.
TEST_F(BLASTBufferQueueTest, OutOfOrderTransactionTest) {
sp<SurfaceControl> bgSurface =
mClient->createSurface(String8("BGTest"), 0, 0, PIXEL_FORMAT_RGBA_8888,
@@ -781,7 +786,7 @@
void setUpAndQueueBuffer(const sp<IGraphicBufferProducer>& igbProducer,
nsecs_t* requestedPresentTime, nsecs_t* postedTime,
IGraphicBufferProducer::QueueBufferOutput* qbOutput,
- bool getFrameTimestamps) {
+ bool getFrameTimestamps, nsecs_t requestedPresentTimeDelay = 0) {
int slot;
sp<Fence> fence;
sp<GraphicBuffer> buf;
@@ -791,7 +796,7 @@
ASSERT_EQ(IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION, ret);
ASSERT_EQ(OK, igbProducer->requestBuffer(slot, &buf));
- nsecs_t requestedTime = systemTime();
+ nsecs_t requestedTime = systemTime() + requestedPresentTimeDelay;
if (requestedPresentTime) *requestedPresentTime = requestedTime;
IGraphicBufferProducer::QueueBufferInput input(requestedTime, false, HAL_DATASPACE_UNKNOWN,
Rect(mDisplayWidth, mDisplayHeight),
@@ -801,6 +806,27 @@
if (postedTime) *postedTime = systemTime();
igbProducer->queueBuffer(slot, input, qbOutput);
}
+
+ void createBufferQueueProducer(sp<IGraphicBufferProducer>* bqIgbp) {
+ mBufferQueueSurfaceControl =
+ mClient->createSurface(String8("BqSurface"), 0, 0, PIXEL_FORMAT_RGBA_8888,
+ ISurfaceComposerClient::eFXSurfaceBufferQueue);
+ ASSERT_NE(nullptr, mBufferQueueSurfaceControl.get());
+ Transaction()
+ .setLayerStack(mBufferQueueSurfaceControl, 0)
+ .show(mBufferQueueSurfaceControl)
+ .setDataspace(mBufferQueueSurfaceControl, ui::Dataspace::V0_SRGB)
+ .setSize(mBufferQueueSurfaceControl, mDisplayWidth, mDisplayHeight)
+ .setLayer(mBufferQueueSurfaceControl, std::numeric_limits<int32_t>::max())
+ .apply();
+
+ sp<Surface> bqSurface = mBufferQueueSurfaceControl->getSurface();
+ ASSERT_NE(nullptr, bqSurface.get());
+
+ *bqIgbp = bqSurface->getIGraphicBufferProducer();
+ setUpProducer(*bqIgbp);
+ }
+ sp<SurfaceControl> mBufferQueueSurfaceControl;
};
TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_Basic) {
@@ -853,4 +879,153 @@
// wait for any callbacks that have not been received
adapter.waitForCallbacks();
}
+
+// Runs the same Frame Event History test
+TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_Basic_BufferQueue) {
+ sp<IGraphicBufferProducer> bqIgbp;
+ createBufferQueueProducer(&bqIgbp);
+
+ ProducerFrameEventHistory history;
+ IGraphicBufferProducer::QueueBufferOutput qbOutput;
+ nsecs_t requestedPresentTimeA = 0;
+ nsecs_t postedTimeA = 0;
+ setUpAndQueueBuffer(bqIgbp, &requestedPresentTimeA, &postedTimeA, &qbOutput, true);
+ history.applyDelta(qbOutput.frameTimestamps);
+
+ FrameEvents* events = nullptr;
+ events = history.getFrame(1);
+ ASSERT_NE(nullptr, events);
+ ASSERT_EQ(1, events->frameNumber);
+ ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime);
+ ASSERT_GE(events->postedTime, postedTimeA);
+
+ // wait for buffer to be presented
+ std::this_thread::sleep_for(200ms);
+
+ nsecs_t requestedPresentTimeB = 0;
+ nsecs_t postedTimeB = 0;
+ setUpAndQueueBuffer(bqIgbp, &requestedPresentTimeB, &postedTimeB, &qbOutput, true);
+ history.applyDelta(qbOutput.frameTimestamps);
+ events = history.getFrame(1);
+ ASSERT_NE(nullptr, events);
+
+ // frame number, requestedPresentTime, and postTime should not have changed
+ ASSERT_EQ(1, events->frameNumber);
+ ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime);
+ ASSERT_GE(events->postedTime, postedTimeA);
+
+ ASSERT_GE(events->latchTime, postedTimeA);
+ ASSERT_FALSE(events->hasDequeueReadyInfo());
+
+ ASSERT_NE(nullptr, events->gpuCompositionDoneFence);
+ ASSERT_NE(nullptr, events->displayPresentFence);
+ ASSERT_NE(nullptr, events->releaseFence);
+
+ // we should also have gotten the initial values for the next frame
+ events = history.getFrame(2);
+ ASSERT_NE(nullptr, events);
+ ASSERT_EQ(2, events->frameNumber);
+ ASSERT_EQ(requestedPresentTimeB, events->requestedPresentTime);
+ ASSERT_GE(events->postedTime, postedTimeB);
+}
+
+TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_DroppedFrame) {
+ BLASTBufferQueueHelper adapter(mSurfaceControl, mDisplayWidth, mDisplayHeight);
+ sp<IGraphicBufferProducer> igbProducer;
+ setUpProducer(adapter, igbProducer);
+
+ ProducerFrameEventHistory history;
+ IGraphicBufferProducer::QueueBufferOutput qbOutput;
+ nsecs_t requestedPresentTimeA = 0;
+ nsecs_t postedTimeA = 0;
+ nsecs_t presentTimeDelay = std::chrono::nanoseconds(500ms).count();
+ setUpAndQueueBuffer(igbProducer, &requestedPresentTimeA, &postedTimeA, &qbOutput, true,
+ presentTimeDelay);
+ history.applyDelta(qbOutput.frameTimestamps);
+
+ FrameEvents* events = nullptr;
+ events = history.getFrame(1);
+ ASSERT_NE(nullptr, events);
+ ASSERT_EQ(1, events->frameNumber);
+ ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime);
+ ASSERT_GE(events->postedTime, postedTimeA);
+
+ // queue another buffer so the first can be dropped
+ nsecs_t requestedPresentTimeB = 0;
+ nsecs_t postedTimeB = 0;
+ setUpAndQueueBuffer(igbProducer, &requestedPresentTimeB, &postedTimeB, &qbOutput, true);
+ history.applyDelta(qbOutput.frameTimestamps);
+ events = history.getFrame(1);
+ ASSERT_NE(nullptr, events);
+
+ // frame number, requestedPresentTime, and postTime should not have changed
+ ASSERT_EQ(1, events->frameNumber);
+ ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime);
+ ASSERT_GE(events->postedTime, postedTimeA);
+
+ // a valid latchtime should not be set
+ ASSERT_FALSE(events->hasLatchInfo());
+ ASSERT_FALSE(events->hasDequeueReadyInfo());
+
+ ASSERT_NE(nullptr, events->gpuCompositionDoneFence);
+ ASSERT_NE(nullptr, events->displayPresentFence);
+ ASSERT_NE(nullptr, events->releaseFence);
+
+ // we should also have gotten the initial values for the next frame
+ events = history.getFrame(2);
+ ASSERT_NE(nullptr, events);
+ ASSERT_EQ(2, events->frameNumber);
+ ASSERT_EQ(requestedPresentTimeB, events->requestedPresentTime);
+ ASSERT_GE(events->postedTime, postedTimeB);
+}
+
+TEST_F(BLASTFrameEventHistoryTest, FrameEventHistory_DroppedFrame_BufferQueue) {
+ sp<IGraphicBufferProducer> bqIgbp;
+ createBufferQueueProducer(&bqIgbp);
+
+ ProducerFrameEventHistory history;
+ IGraphicBufferProducer::QueueBufferOutput qbOutput;
+ nsecs_t requestedPresentTimeA = 0;
+ nsecs_t postedTimeA = 0;
+ nsecs_t presentTimeDelay = std::chrono::nanoseconds(500ms).count();
+ setUpAndQueueBuffer(bqIgbp, &requestedPresentTimeA, &postedTimeA, &qbOutput, true,
+ presentTimeDelay);
+ history.applyDelta(qbOutput.frameTimestamps);
+
+ FrameEvents* events = nullptr;
+ events = history.getFrame(1);
+ ASSERT_NE(nullptr, events);
+ ASSERT_EQ(1, events->frameNumber);
+ ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime);
+ ASSERT_GE(events->postedTime, postedTimeA);
+
+ // queue another buffer so the first can be dropped
+ nsecs_t requestedPresentTimeB = 0;
+ nsecs_t postedTimeB = 0;
+ setUpAndQueueBuffer(bqIgbp, &requestedPresentTimeB, &postedTimeB, &qbOutput, true);
+ history.applyDelta(qbOutput.frameTimestamps);
+ events = history.getFrame(1);
+ ASSERT_NE(nullptr, events);
+
+ // frame number, requestedPresentTime, and postTime should not have changed
+ ASSERT_EQ(1, events->frameNumber);
+ ASSERT_EQ(requestedPresentTimeA, events->requestedPresentTime);
+ ASSERT_GE(events->postedTime, postedTimeA);
+
+ // a valid latchtime should not be set
+ ASSERT_FALSE(events->hasLatchInfo());
+ ASSERT_FALSE(events->hasDequeueReadyInfo());
+
+ ASSERT_NE(nullptr, events->gpuCompositionDoneFence);
+ ASSERT_NE(nullptr, events->displayPresentFence);
+ ASSERT_NE(nullptr, events->releaseFence);
+
+ // we should also have gotten the initial values for the next frame
+ events = history.getFrame(2);
+ ASSERT_NE(nullptr, events);
+ ASSERT_EQ(2, events->frameNumber);
+ ASSERT_EQ(requestedPresentTimeB, events->requestedPresentTime);
+ ASSERT_GE(events->postedTime, postedTimeB);
+}
+
} // namespace android
diff --git a/libs/incidentcompanion/Android.bp b/libs/incidentcompanion/Android.bp
index 63411b9..ef7f523 100644
--- a/libs/incidentcompanion/Android.bp
+++ b/libs/incidentcompanion/Android.bp
@@ -14,6 +14,15 @@
* limitations under the License.
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
filegroup {
name: "incidentcompanion_aidl",
srcs: [
@@ -49,4 +58,3 @@
"-Wunused-parameter",
],
}
-
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index fce3000..4253610 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -14,6 +14,15 @@
// libinput is partially built for the host (used by build time keymap validation tool)
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
filegroup {
name: "inputconstants_aidl",
srcs: [
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index b23aade..fe8a567 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -1,4 +1,13 @@
// Build the unit tests.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "libinput_tests",
srcs: [
diff --git a/libs/math/Android.bp b/libs/math/Android.bp
index 22d4712..3cf9f3f 100644
--- a/libs/math/Android.bp
+++ b/libs/math/Android.bp
@@ -12,6 +12,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ default_applicable_licenses: ["frameworks_native_libs_math_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_libs_math_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_static {
name: "libmath",
host_supported: true,
diff --git a/libs/math/tests/Android.bp b/libs/math/tests/Android.bp
index 0184f56..4a7c4dd 100644
--- a/libs/math/tests/Android.bp
+++ b/libs/math/tests/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_libs_math_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_libs_math_license"],
+}
+
cc_test {
name: "vec_test",
srcs: ["vec_test.cpp"],
diff --git a/libs/nativebase/Android.bp b/libs/nativebase/Android.bp
index 8399e8c..1a4729c 100644
--- a/libs/nativebase/Android.bp
+++ b/libs/nativebase/Android.bp
@@ -12,6 +12,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ default_applicable_licenses: ["frameworks_native_libs_nativebase_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_libs_nativebase_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_headers {
name: "libnativebase_headers",
vendor_available: true,
diff --git a/libs/nativedisplay/Android.bp b/libs/nativedisplay/Android.bp
index 6574ae6..ed728dc 100644
--- a/libs/nativedisplay/Android.bp
+++ b/libs/nativedisplay/Android.bp
@@ -12,6 +12,25 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ default_applicable_licenses: [
+ "frameworks_native_libs_nativedisplay_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_libs_nativedisplay_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_library_headers {
name: "libnativedisplay_headers",
export_include_dirs: ["include",],
diff --git a/libs/nativewindow/Android.bp b/libs/nativewindow/Android.bp
index 3011dcc..8675439 100644
--- a/libs/nativewindow/Android.bp
+++ b/libs/nativewindow/Android.bp
@@ -12,6 +12,25 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ default_applicable_licenses: [
+ "frameworks_native_libs_nativewindow_license",
+ ],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_libs_nativewindow_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
ndk_headers {
name: "libnativewindow_ndk_headers",
from: "include/android",
diff --git a/libs/nativewindow/tests/Android.bp b/libs/nativewindow/tests/Android.bp
index 2e4bd99..30737c1 100644
--- a/libs/nativewindow/tests/Android.bp
+++ b/libs/nativewindow/tests/Android.bp
@@ -14,6 +14,17 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_libs_nativewindow_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: [
+ "frameworks_native_libs_nativewindow_license",
+ ],
+}
+
cc_test {
name: "libnativewindow_test",
test_suites: [
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index 00540b8..eb3b434 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "renderengine_defaults",
cflags: [
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index b4a2d79..55ec6ad 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -337,7 +337,7 @@
if (useProtectedContext == mInProtectedContext) {
return true;
}
- if (useProtectedContext && supportsProtectedContent()) {
+ if (useProtectedContext && !supportsProtectedContent()) {
return false;
}
const EGLSurface surface =
@@ -518,7 +518,7 @@
}
void SkiaGLRenderEngine::initCanvas(SkCanvas* canvas, const DisplaySettings& display) {
- if (mCapture->isCaptureRunning()) {
+ if (CC_UNLIKELY(mCapture->isCaptureRunning())) {
// Record display settings when capture is running.
std::stringstream displaySettings;
PrintTo(display, &displaySettings);
@@ -626,6 +626,7 @@
// offscreen buffer and when to render to the native buffer.
sk_sp<SkSurface> activeSurface(dstSurface);
SkCanvas* canvas = dstCanvas;
+ SkiaCapture::OffscreenState offscreenCaptureState;
const LayerSettings* blurCompositionLayer = nullptr;
if (mBlurFilter) {
bool requiresCompositionLayer = false;
@@ -642,7 +643,7 @@
}
if (requiresCompositionLayer) {
activeSurface = dstSurface->makeSurface(dstSurface->imageInfo());
- canvas = activeSurface->getCanvas();
+ canvas = mCapture->tryOffscreenCapture(activeSurface.get(), &offscreenCaptureState);
blurCompositionLayer = layer;
break;
}
@@ -692,7 +693,15 @@
// blit the offscreen framebuffer into the destination AHB
SkPaint paint;
paint.setBlendMode(SkBlendMode::kSrc);
- activeSurface->draw(dstCanvas, 0, 0, SkSamplingOptions(), &paint);
+ if (CC_UNLIKELY(mCapture->isCaptureRunning())) {
+ uint64_t id = mCapture->endOffscreenCapture(&offscreenCaptureState);
+ dstCanvas->drawAnnotation(SkRect::Make(dstCanvas->imageInfo().dimensions()),
+ String8::format("SurfaceID|%" PRId64, id).c_str(),
+ nullptr);
+ dstCanvas->drawImage(blurInput, 0, 0, SkSamplingOptions(), &paint);
+ } else {
+ activeSurface->draw(dstCanvas, 0, 0, SkSamplingOptions(), &paint);
+ }
// assign dstCanvas to canvas and ensure that the canvas state is up to date
canvas = dstCanvas;
@@ -709,7 +718,7 @@
}
canvas->save();
- if (mCapture->isCaptureRunning()) {
+ if (CC_UNLIKELY(mCapture->isCaptureRunning())) {
// Record the name of the layer if the capture is running.
std::stringstream layerSettings;
PrintTo(*layer, &layerSettings);
diff --git a/libs/renderengine/skia/debug/SkiaCapture.cpp b/libs/renderengine/skia/debug/SkiaCapture.cpp
index e9cfead..40f5cf2 100644
--- a/libs/renderengine/skia/debug/SkiaCapture.cpp
+++ b/libs/renderengine/skia/debug/SkiaCapture.cpp
@@ -41,11 +41,11 @@
mTimer.stop();
}
-SkCanvas* SkiaCapture::tryCapture(SkSurface* surface) {
+SkCanvas* SkiaCapture::tryCapture(SkSurface* surface) NO_THREAD_SAFETY_ANALYSIS {
ATRACE_CALL();
// If we are not running yet, set up.
- if (!mCaptureRunning) {
+ if (CC_LIKELY(!mCaptureRunning)) {
mTimerInterval = std::chrono::milliseconds(
base::GetIntProperty(PROPERTY_DEBUG_RENDERENGINE_CAPTURE_SKIA_MS, 0));
// Set up the multi-frame capture. If we fail to set it up, then just return canvas.
@@ -56,7 +56,8 @@
// Start the new timer. When timer expires, write to file.
mTimer.setTimeout(
[this] {
- endCapture();
+ const std::scoped_lock lock(mMutex);
+ LOG_ALWAYS_FATAL_IF(mCurrentPageCanvas != nullptr);
writeToFile();
// To avoid going in circles, set the flag to 0. This way the capture can be
// restarted just by setting the flag and without restarting the process.
@@ -65,29 +66,82 @@
mTimerInterval);
}
+ mMutex.lock();
+
// Create a canvas pointer, fill it.
- SkCanvas* pictureCanvas = mMultiPic->beginPage(surface->width(), surface->height());
+ mCurrentPageCanvas = mMultiPic->beginPage(surface->width(), surface->height());
// Setting up an nway canvas is common to any kind of capture.
mNwayCanvas = std::make_unique<SkNWayCanvas>(surface->width(), surface->height());
mNwayCanvas->addCanvas(surface->getCanvas());
- mNwayCanvas->addCanvas(pictureCanvas);
+ mNwayCanvas->addCanvas(mCurrentPageCanvas);
return mNwayCanvas.get();
}
-void SkiaCapture::endCapture() {
+void SkiaCapture::endCapture() NO_THREAD_SAFETY_ANALYSIS {
ATRACE_CALL();
// Don't end anything if we are not running.
- if (!mCaptureRunning) {
+ if (CC_LIKELY(!mCaptureRunning)) {
return;
}
// Reset the canvas pointer.
+ mCurrentPageCanvas = nullptr;
mNwayCanvas.reset();
// End page.
if (mMultiPic) {
mMultiPic->endPage();
}
+ mMutex.unlock();
+}
+
+SkCanvas* SkiaCapture::tryOffscreenCapture(SkSurface* surface, OffscreenState* state) {
+ ATRACE_CALL();
+ // Don't start anything if we are not running.
+ if (CC_LIKELY(!mCaptureRunning)) {
+ return surface->getCanvas();
+ }
+
+ // Create a canvas pointer, fill it.
+ state->offscreenRecorder = std::make_unique<SkPictureRecorder>();
+ SkCanvas* pictureCanvas =
+ state->offscreenRecorder->beginRecording(surface->width(), surface->height());
+
+ // Setting up an nway canvas is common to any kind of capture.
+ state->offscreenCanvas = std::make_unique<SkNWayCanvas>(surface->width(), surface->height());
+ state->offscreenCanvas->addCanvas(surface->getCanvas());
+ state->offscreenCanvas->addCanvas(pictureCanvas);
+
+ return state->offscreenCanvas.get();
+}
+
+uint64_t SkiaCapture::endOffscreenCapture(OffscreenState* state) {
+ ATRACE_CALL();
+ // Don't end anything if we are not running.
+ if (CC_LIKELY(!mCaptureRunning)) {
+ return 0;
+ }
+
+ // compute the uniqueID for this capture
+ static std::atomic<uint64_t> nextID{1};
+ const uint64_t uniqueID = nextID.fetch_add(1, std::memory_order_relaxed);
+
+ // Reset the canvas pointer as we are no longer drawing into it
+ state->offscreenCanvas.reset();
+
+ // Record the offscreen as a picture in the currently active page.
+ SkRect bounds =
+ SkRect::Make(state->offscreenRecorder->getRecordingCanvas()->imageInfo().dimensions());
+ mCurrentPageCanvas
+ ->drawAnnotation(bounds,
+ String8::format("OffscreenLayerDraw|%" PRId64, uniqueID).c_str(),
+ nullptr);
+ mCurrentPageCanvas->drawPicture(state->offscreenRecorder->finishRecordingAsPicture());
+
+ // Reset the offscreen picture recorder
+ state->offscreenRecorder.reset();
+
+ return uniqueID;
}
void SkiaCapture::writeToFile() {
diff --git a/libs/renderengine/skia/debug/SkiaCapture.h b/libs/renderengine/skia/debug/SkiaCapture.h
index eaaf598..5e18e60 100644
--- a/libs/renderengine/skia/debug/SkiaCapture.h
+++ b/libs/renderengine/skia/debug/SkiaCapture.h
@@ -18,8 +18,12 @@
#include <SkDocument.h>
#include <SkNWayCanvas.h>
+#include <SkPictureRecorder.h>
#include <SkSurface.h>
+
#include <chrono>
+#include <mutex>
+
#include "CaptureTimer.h"
#include "tools/SkSharingProc.h"
@@ -48,6 +52,16 @@
// Returns whether the capture is running.
bool isCaptureRunning() { return mCaptureRunning; }
+ // Offscreen state member variables are private to SkiaCapture, but the allocation
+ // and lifetime is managed by the caller. This enables nested offscreen
+ // captures to occur.
+ struct OffscreenState {
+ std::unique_ptr<SkPictureRecorder> offscreenRecorder;
+ std::unique_ptr<SkNWayCanvas> offscreenCanvas;
+ };
+ SkCanvas* tryOffscreenCapture(SkSurface* surface, OffscreenState* state);
+ uint64_t endOffscreenCapture(OffscreenState* state);
+
private:
// Performs the first-frame work of a multi frame SKP capture. Returns true if successful.
bool setupMultiFrameCapture();
@@ -61,10 +75,16 @@
std::unique_ptr<SkSharingSerialContext> mSerialContext;
std::unique_ptr<SkNWayCanvas> mNwayCanvas;
+ SkCanvas* mCurrentPageCanvas = nullptr;
+
// Capturing and interval control.
bool mCaptureRunning = false;
CaptureTimer mTimer;
Interval mTimerInterval = 0ms;
+
+ // Mutex to ensure that a frame in progress when the timer fires is allowed to run to
+ // completion before we write the file to disk.
+ std::mutex mMutex;
};
} // namespace skia
diff --git a/libs/renderengine/skia/filters/BlurFilter.cpp b/libs/renderengine/skia/filters/BlurFilter.cpp
index 9d20e32..5960e48 100644
--- a/libs/renderengine/skia/filters/BlurFilter.cpp
+++ b/libs/renderengine/skia/filters/BlurFilter.cpp
@@ -20,6 +20,7 @@
#include <SkCanvas.h>
#include <SkData.h>
#include <SkPaint.h>
+#include <SkRRect.h>
#include <SkRuntimeEffect.h>
#include <SkSize.h>
#include <SkString.h>
diff --git a/libs/renderengine/tests/Android.bp b/libs/renderengine/tests/Android.bp
index 51c7028..d0e19dd 100644
--- a/libs/renderengine/tests/Android.bp
+++ b/libs/renderengine/tests/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "librenderengine_test",
defaults: ["skia_deps", "surfaceflinger_defaults"],
diff --git a/libs/sensor/Android.bp b/libs/sensor/Android.bp
index e8154a6..497c33c 100644
--- a/libs/sensor/Android.bp
+++ b/libs/sensor/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libsensor",
diff --git a/libs/sensor/Sensor.cpp b/libs/sensor/Sensor.cpp
index 9d817ae..240738d 100644
--- a/libs/sensor/Sensor.cpp
+++ b/libs/sensor/Sensor.cpp
@@ -468,6 +468,19 @@
mUuid.i64[1] = 0;
}
+void Sensor::capMinDelayMicros(int32_t cappedMinDelay) {
+ if (mMinDelay < cappedMinDelay) {
+ mMinDelay = cappedMinDelay;
+ }
+}
+
+void Sensor::capHighestDirectReportRateLevel(int32_t cappedRateLevel) {
+ if (cappedRateLevel < getHighestDirectReportRateLevel()) {
+ mFlags &= ~SENSOR_FLAG_MASK_DIRECT_REPORT;
+ mFlags |= cappedRateLevel << SENSOR_FLAG_SHIFT_DIRECT_REPORT;
+ }
+}
+
int32_t Sensor::getId() const {
return int32_t(mUuid.i64[0]);
}
diff --git a/libs/sensor/include/sensor/Sensor.h b/libs/sensor/include/sensor/Sensor.h
index 324d443..374b68f 100644
--- a/libs/sensor/include/sensor/Sensor.h
+++ b/libs/sensor/include/sensor/Sensor.h
@@ -104,6 +104,9 @@
int32_t getId() const;
void setId(int32_t id);
+ void capMinDelayMicros(int32_t cappedMinDelay);
+ void capHighestDirectReportRateLevel(int32_t cappedRateLevel);
+
// LightFlattenable protocol
inline bool isFixedSize() const { return false; }
size_t getFlattenedSize() const;
diff --git a/libs/sensor/tests/Android.bp b/libs/sensor/tests/Android.bp
index c9a7668..8fdb003 100644
--- a/libs/sensor/tests/Android.bp
+++ b/libs/sensor/tests/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "libsensor_test",
diff --git a/libs/sensorprivacy/Android.bp b/libs/sensorprivacy/Android.bp
index 4a606ff..00514c4 100644
--- a/libs/sensorprivacy/Android.bp
+++ b/libs/sensorprivacy/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libsensorprivacy",
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 714ee3e..3b024be 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -12,6 +12,23 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ default_applicable_licenses: ["frameworks_native_libs_ui_license"],
+}
+
+// Added automatically by a large-scale-change
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_libs_ui_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-Apache-2.0",
+ ],
+ license_text: [
+ "NOTICE",
+ ],
+}
+
cc_defaults {
name: "libui-defaults",
clang: true,
@@ -77,7 +94,6 @@
"libarect",
"libmath",
],
-
}
cc_library_shared {
diff --git a/libs/ui/tests/Android.bp b/libs/ui/tests/Android.bp
index d005ce8..516aad8 100644
--- a/libs/ui/tests/Android.bp
+++ b/libs/ui/tests/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_libs_ui_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_libs_ui_license"],
+}
+
cc_test {
name: "Region_test",
shared_libs: ["libui"],
diff --git a/libs/ui/tools/Android.bp b/libs/ui/tools/Android.bp
index fb46c2b..c28c303 100644
--- a/libs/ui/tools/Android.bp
+++ b/libs/ui/tools/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_libs_ui_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_libs_ui_license"],
+}
+
cc_defaults {
name: "libui_tools_default",
clang_cflags: [
diff --git a/libs/vibrator/Android.bp b/libs/vibrator/Android.bp
index 49bc6bf..83c250a 100644
--- a/libs/vibrator/Android.bp
+++ b/libs/vibrator/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library {
name: "libvibrator",
vendor_available: true,
diff --git a/libs/vibrator/fuzzer/Android.bp b/libs/vibrator/fuzzer/Android.bp
index 8020151..f2a313c 100644
--- a/libs/vibrator/fuzzer/Android.bp
+++ b/libs/vibrator/fuzzer/Android.bp
@@ -17,6 +17,15 @@
*****************************************************************************
*/
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_fuzz {
name: "vibrator_fuzzer",
diff --git a/libs/vr/Android.bp b/libs/vr/Android.bp
index e8176cf..b308895 100644
--- a/libs/vr/Android.bp
+++ b/libs/vr/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-BSD
+ // legacy_notice
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
subdirs = [
"*",
]
diff --git a/libs/vr/libbroadcastring/Android.bp b/libs/vr/libbroadcastring/Android.bp
index 13af470..2eb2f9f 100644
--- a/libs/vr/libbroadcastring/Android.bp
+++ b/libs/vr/libbroadcastring/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_static {
name: "libbroadcastring",
clang: true,
diff --git a/libs/vr/libbufferhub/Android.bp b/libs/vr/libbufferhub/Android.bp
index 37c19d4..45bdd35 100644
--- a/libs/vr/libbufferhub/Android.bp
+++ b/libs/vr/libbufferhub/Android.bp
@@ -12,6 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "libbufferhub_headers",
export_include_dirs: ["include"],
diff --git a/libs/vr/libbufferhubqueue/Android.bp b/libs/vr/libbufferhubqueue/Android.bp
index 77c7911..f372bd7 100644
--- a/libs/vr/libbufferhubqueue/Android.bp
+++ b/libs/vr/libbufferhubqueue/Android.bp
@@ -12,6 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
sourceFiles = [
"buffer_hub_queue_client.cpp",
"buffer_hub_queue_parcelable.cpp",
diff --git a/libs/vr/libbufferhubqueue/benchmarks/Android.bp b/libs/vr/libbufferhubqueue/benchmarks/Android.bp
index ef1eed6..fc1f376 100644
--- a/libs/vr/libbufferhubqueue/benchmarks/Android.bp
+++ b/libs/vr/libbufferhubqueue/benchmarks/Android.bp
@@ -1,4 +1,15 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_benchmark {
srcs: ["buffer_transport_benchmark.cpp"],
shared_libs: [
diff --git a/libs/vr/libbufferhubqueue/tests/Android.bp b/libs/vr/libbufferhubqueue/tests/Android.bp
index a337921..e883916 100644
--- a/libs/vr/libbufferhubqueue/tests/Android.bp
+++ b/libs/vr/libbufferhubqueue/tests/Android.bp
@@ -1,4 +1,15 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
header_libraries = [
"libdvr_headers",
]
diff --git a/libs/vr/libdisplay/Android.bp b/libs/vr/libdisplay/Android.bp
index 8c354fb..365a676 100644
--- a/libs/vr/libdisplay/Android.bp
+++ b/libs/vr/libdisplay/Android.bp
@@ -12,6 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
sourceFiles = [
"display_client.cpp",
"display_manager_client.cpp",
diff --git a/libs/vr/libdvr/Android.bp b/libs/vr/libdvr/Android.bp
index d5a19d3..83c30d7 100644
--- a/libs/vr/libdvr/Android.bp
+++ b/libs/vr/libdvr/Android.bp
@@ -13,6 +13,17 @@
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "libdvr_headers",
export_include_dirs: ["include"],
diff --git a/libs/vr/libdvr/tests/Android.bp b/libs/vr/libdvr/tests/Android.bp
index 3260447..4ed80a4 100644
--- a/libs/vr/libdvr/tests/Android.bp
+++ b/libs/vr/libdvr/tests/Android.bp
@@ -12,6 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
srcs: [
"dvr_display_manager-test.cpp",
diff --git a/libs/vr/libdvrcommon/Android.bp b/libs/vr/libdvrcommon/Android.bp
index e751768..9e1e516 100644
--- a/libs/vr/libdvrcommon/Android.bp
+++ b/libs/vr/libdvrcommon/Android.bp
@@ -12,6 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
localIncludeFiles = [
"include",
]
diff --git a/libs/vr/libpdx/Android.bp b/libs/vr/libpdx/Android.bp
index 24ba830..c1f6da3 100644
--- a/libs/vr/libpdx/Android.bp
+++ b/libs/vr/libpdx/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "libpdx_headers",
export_include_dirs: ["private"],
diff --git a/libs/vr/libpdx/fuzz/Android.bp b/libs/vr/libpdx/fuzz/Android.bp
index b36e0de..cc32b18 100644
--- a/libs/vr/libpdx/fuzz/Android.bp
+++ b/libs/vr/libpdx/fuzz/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_fuzz {
name: "libpdx_service_dispatcher_fuzzer",
clang: true,
diff --git a/libs/vr/libpdx_default_transport/Android.bp b/libs/vr/libpdx_default_transport/Android.bp
index b3534de..ea73d7a 100644
--- a/libs/vr/libpdx_default_transport/Android.bp
+++ b/libs/vr/libpdx_default_transport/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "pdx_default_transport_compiler_defaults",
clang: true,
@@ -75,4 +86,3 @@
"libpdx_default_transport",
],
}
-
diff --git a/libs/vr/libpdx_uds/Android.bp b/libs/vr/libpdx_uds/Android.bp
index 1d6eea2..532d1a7 100644
--- a/libs/vr/libpdx_uds/Android.bp
+++ b/libs/vr/libpdx_uds/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_static {
name: "libpdx_uds",
clang: true,
diff --git a/libs/vr/libperformance/Android.bp b/libs/vr/libperformance/Android.bp
index 35d3dea..5beee35 100644
--- a/libs/vr/libperformance/Android.bp
+++ b/libs/vr/libperformance/Android.bp
@@ -12,6 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
sourceFiles = [
"performance_client.cpp",
"performance_rpc.cpp",
diff --git a/libs/vr/libvr_manager/Android.bp b/libs/vr/libvr_manager/Android.bp
index 2cd6a28..6f2ada4 100644
--- a/libs/vr/libvr_manager/Android.bp
+++ b/libs/vr/libvr_manager/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_static {
name: "libvr_manager",
srcs: [
diff --git a/libs/vr/libvrflinger/Android.bp b/libs/vr/libvrflinger/Android.bp
index abc64bd..8aca9a5 100644
--- a/libs/vr/libvrflinger/Android.bp
+++ b/libs/vr/libvrflinger/Android.bp
@@ -12,6 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
sourceFiles = [
"acquired_buffer.cpp",
"epoll_event_dispatcher.cpp",
diff --git a/libs/vr/libvrflinger/tests/Android.bp b/libs/vr/libvrflinger/tests/Android.bp
index 7fafd3b..dafd354 100644
--- a/libs/vr/libvrflinger/tests/Android.bp
+++ b/libs/vr/libvrflinger/tests/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
shared_libs = [
"android.hardware.configstore-utils",
"android.hardware.configstore@1.0",
diff --git a/libs/vr/libvrsensor/Android.bp b/libs/vr/libvrsensor/Android.bp
index 8542790..8f566a0 100644
--- a/libs/vr/libvrsensor/Android.bp
+++ b/libs/vr/libvrsensor/Android.bp
@@ -12,6 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
sourceFiles = [
"pose_client.cpp",
"latency_model.cpp",
@@ -52,4 +63,3 @@
header_libs: ["libdvr_headers"],
name: "libvrsensor",
}
-
diff --git a/opengl/Android.bp b/opengl/Android.bp
index 8b94f61..3878cb1 100644
--- a/opengl/Android.bp
+++ b/opengl/Android.bp
@@ -12,6 +12,18 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-BSD
+ // SPDX-license-identifier-MIT
+ // legacy_notice
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
ndk_headers {
name: "libEGL_headers",
from: "include",
diff --git a/opengl/libs/Android.bp b/opengl/libs/Android.bp
index 5d17561..7861d62 100644
--- a/opengl/libs/Android.bp
+++ b/opengl/libs/Android.bp
@@ -1,4 +1,13 @@
// Build the ETC1 library
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library {
name: "libETC1",
srcs: ["ETC1/etc1.cpp"],
diff --git a/opengl/tests/Android.bp b/opengl/tests/Android.bp
index 639f351..da717bd 100644
--- a/opengl/tests/Android.bp
+++ b/opengl/tests/Android.bp
@@ -1,4 +1,16 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-BSD
+ // SPDX-license-identifier-MIT
+ // legacy_notice
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
subdirs = [
"angeles",
"configdump",
@@ -16,4 +28,3 @@
"hwc",
"lib",
]
-
diff --git a/opengl/tests/EGLTest/Android.bp b/opengl/tests/EGLTest/Android.bp
index e3912a8..51c9376 100644
--- a/opengl/tests/EGLTest/Android.bp
+++ b/opengl/tests/EGLTest/Android.bp
@@ -1,4 +1,13 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "EGL_test",
diff --git a/opengl/tests/angeles/Android.bp b/opengl/tests/angeles/Android.bp
index 5c398a6..5b81501 100644
--- a/opengl/tests/angeles/Android.bp
+++ b/opengl/tests/angeles/Android.bp
@@ -1,5 +1,50 @@
// Copyright 2006 The Android Open Source Project
+package {
+ default_applicable_licenses: [
+ "frameworks_native_opengl_tests_angeles_license",
+ ],
+}
+
+// Added automatically by a large-scale-change that took the approach of
+// 'apply every license found to every target'. While this makes sure we respect
+// every license restriction, it may not be entirely correct.
+//
+// e.g. GPL in an MIT project might only apply to the contrib/ directory.
+//
+// Please consider splitting the single license below into multiple licenses,
+// taking care not to lose any license_kind information, and overriding the
+// default license using the 'licenses: [...]' property on targets as needed.
+//
+// For unused files, consider creating a 'fileGroup' with "//visibility:private"
+// to attach the license to, and including a comment whether the files may be
+// used in the current project.
+//
+// large-scale-change included anything that looked like it might be a license
+// text as a license_text. e.g. LICENSE, NOTICE, COPYING etc.
+//
+// Please consider removing redundant or irrelevant files from 'license_text:'.
+//
+// large-scale-change filtered out the below license kinds as false-positives:
+// SPDX-license-identifier-LGPL
+// SPDX-license-identifier-LGPL-2.1
+// SPDX-license-identifier-LGPL-3.0
+// See: http://go/android-license-faq
+license {
+ name: "frameworks_native_opengl_tests_angeles_license",
+ visibility: [":__subpackages__"],
+ license_kinds: [
+ "SPDX-license-identifier-BSD",
+ "SPDX-license-identifier-MIT",
+ "legacy_notice",
+ ],
+ license_text: [
+ "license-BSD.txt",
+ "license-LGPL.txt",
+ "license.txt",
+ ],
+}
+
cc_test {
name: "angeles",
diff --git a/opengl/tests/configdump/Android.bp b/opengl/tests/configdump/Android.bp
index ee967970..ffb0c1f 100644
--- a/opengl/tests/configdump/Android.bp
+++ b/opengl/tests/configdump/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "test-opengl-configdump",
diff --git a/opengl/tests/fillrate/Android.bp b/opengl/tests/fillrate/Android.bp
index 689cee4..e4bff01 100644
--- a/opengl/tests/fillrate/Android.bp
+++ b/opengl/tests/fillrate/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "test-opengl-fillrate",
diff --git a/opengl/tests/filter/Android.bp b/opengl/tests/filter/Android.bp
index 23241e1..3b92b37 100644
--- a/opengl/tests/filter/Android.bp
+++ b/opengl/tests/filter/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "test-opengl-filter",
diff --git a/opengl/tests/finish/Android.bp b/opengl/tests/finish/Android.bp
index be20851..c2dfbc3 100644
--- a/opengl/tests/finish/Android.bp
+++ b/opengl/tests/finish/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "test-opengl-finish",
diff --git a/opengl/tests/gl2_basic/Android.bp b/opengl/tests/gl2_basic/Android.bp
index f4538ad..c54bdf3 100644
--- a/opengl/tests/gl2_basic/Android.bp
+++ b/opengl/tests/gl2_basic/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "test-opengl-gl2_basic",
diff --git a/opengl/tests/gl2_cameraeye/Android.bp b/opengl/tests/gl2_cameraeye/Android.bp
index 00e00df..6b8ee85 100644
--- a/opengl/tests/gl2_cameraeye/Android.bp
+++ b/opengl/tests/gl2_cameraeye/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
android_app {
name: "GL2CameraEye",
// Only compile source java files in this apk.
diff --git a/opengl/tests/gl2_copyTexImage/Android.bp b/opengl/tests/gl2_copyTexImage/Android.bp
index 87fa7ea..0a84d25 100644
--- a/opengl/tests/gl2_copyTexImage/Android.bp
+++ b/opengl/tests/gl2_copyTexImage/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "test-opengl-gl2_copyTexImage",
diff --git a/opengl/tests/gl2_java/Android.bp b/opengl/tests/gl2_java/Android.bp
index a8e5d7d..a33075e 100644
--- a/opengl/tests/gl2_java/Android.bp
+++ b/opengl/tests/gl2_java/Android.bp
@@ -1,6 +1,15 @@
//########################################################################
// OpenGL ES 2.0 Java sample
//########################################################################
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
android_app {
name: "GL2Java",
srcs: ["**/*.java"],
diff --git a/opengl/tests/gl2_jni/Android.bp b/opengl/tests/gl2_jni/Android.bp
index 8d4323f..79773cb 100644
--- a/opengl/tests/gl2_jni/Android.bp
+++ b/opengl/tests/gl2_jni/Android.bp
@@ -3,6 +3,15 @@
// This makefile builds both an activity and a shared library.
//########################################################################
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
android_app {
name: "GL2JNI",
srcs: ["**/*.java"],
diff --git a/opengl/tests/gl2_yuvtex/Android.bp b/opengl/tests/gl2_yuvtex/Android.bp
index b64d94d..fadf0e8 100644
--- a/opengl/tests/gl2_yuvtex/Android.bp
+++ b/opengl/tests/gl2_yuvtex/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "test-opengl-gl2_yuvtex",
diff --git a/opengl/tests/gl_basic/Android.bp b/opengl/tests/gl_basic/Android.bp
index 5eed17e..f777401 100644
--- a/opengl/tests/gl_basic/Android.bp
+++ b/opengl/tests/gl_basic/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "test-opengl-gl_basic",
diff --git a/opengl/tests/gl_jni/Android.bp b/opengl/tests/gl_jni/Android.bp
index 0cb129a..dc46483 100644
--- a/opengl/tests/gl_jni/Android.bp
+++ b/opengl/tests/gl_jni/Android.bp
@@ -4,6 +4,15 @@
//########################################################################
// Build activity
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
android_app {
name: "GLJNI",
srcs: ["**/*.java"],
diff --git a/opengl/tests/gl_perf/Android.bp b/opengl/tests/gl_perf/Android.bp
index 25a317c..ca0f7e8 100644
--- a/opengl/tests/gl_perf/Android.bp
+++ b/opengl/tests/gl_perf/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "test-opengl-gl2_perf",
diff --git a/opengl/tests/gl_perfapp/Android.bp b/opengl/tests/gl_perfapp/Android.bp
index 66afb6a..2f62346 100644
--- a/opengl/tests/gl_perfapp/Android.bp
+++ b/opengl/tests/gl_perfapp/Android.bp
@@ -2,6 +2,15 @@
// OpenGL ES Perf App
// This makefile builds both an activity and a shared library.
//########################################################################
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
android_app {
name: "GLPerf",
srcs: ["**/*.java"],
diff --git a/opengl/tests/gl_yuvtex/Android.bp b/opengl/tests/gl_yuvtex/Android.bp
index 9b4924a..7844186 100644
--- a/opengl/tests/gl_yuvtex/Android.bp
+++ b/opengl/tests/gl_yuvtex/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "test-opengl-gl_yuvtex",
diff --git a/opengl/tests/gldual/Android.bp b/opengl/tests/gldual/Android.bp
index 1006d44..3d6e677 100644
--- a/opengl/tests/gldual/Android.bp
+++ b/opengl/tests/gldual/Android.bp
@@ -4,6 +4,15 @@
//########################################################################
// Build activity
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
android_app {
name: "GLDual",
srcs: ["**/*.java"],
diff --git a/opengl/tests/gralloc/Android.bp b/opengl/tests/gralloc/Android.bp
index 33c3dba..5fb4556 100644
--- a/opengl/tests/gralloc/Android.bp
+++ b/opengl/tests/gralloc/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "test-opengl-gralloc",
diff --git a/opengl/tests/hwc/Android.bp b/opengl/tests/hwc/Android.bp
index 55f058f..719eb11 100644
--- a/opengl/tests/hwc/Android.bp
+++ b/opengl/tests/hwc/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "hwc_tests_defaults",
diff --git a/opengl/tests/lib/Android.bp b/opengl/tests/lib/Android.bp
index 2f6095d..05c9397 100644
--- a/opengl/tests/lib/Android.bp
+++ b/opengl/tests/lib/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_static {
name: "libglTest",
diff --git a/opengl/tests/lighting1709/Android.bp b/opengl/tests/lighting1709/Android.bp
index e734dd1..79daa26 100644
--- a/opengl/tests/lighting1709/Android.bp
+++ b/opengl/tests/lighting1709/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
android_test {
name: "LightingTest",
srcs: ["**/*.java"],
diff --git a/opengl/tests/linetex/Android.bp b/opengl/tests/linetex/Android.bp
index dbc2cdb..61976e5 100644
--- a/opengl/tests/linetex/Android.bp
+++ b/opengl/tests/linetex/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_binary {
name: "test-opengl-linetex",
srcs: ["linetex.cpp"],
diff --git a/opengl/tests/swapinterval/Android.bp b/opengl/tests/swapinterval/Android.bp
index eed4dff..a76f4cf 100644
--- a/opengl/tests/swapinterval/Android.bp
+++ b/opengl/tests/swapinterval/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_binary {
name: "test-opengl-swapinterval",
srcs: ["swapinterval.cpp"],
diff --git a/opengl/tests/testFramerate/Android.bp b/opengl/tests/testFramerate/Android.bp
index 5aa83b0..4334d88 100644
--- a/opengl/tests/testFramerate/Android.bp
+++ b/opengl/tests/testFramerate/Android.bp
@@ -2,6 +2,15 @@
// Test framerate and look for hiccups
//########################################################################
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
android_app {
name: "TestFramerate",
srcs: ["**/*.java"],
diff --git a/opengl/tests/testLatency/Android.bp b/opengl/tests/testLatency/Android.bp
index c516dc3..473cb42 100644
--- a/opengl/tests/testLatency/Android.bp
+++ b/opengl/tests/testLatency/Android.bp
@@ -1,6 +1,15 @@
//########################################################################
// Test end-to-end latency.
//########################################################################
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
android_app {
name: "TestLatency",
sdk_version: "8",
diff --git a/opengl/tests/testPauseResume/Android.bp b/opengl/tests/testPauseResume/Android.bp
index 810e895..8171e1f 100644
--- a/opengl/tests/testPauseResume/Android.bp
+++ b/opengl/tests/testPauseResume/Android.bp
@@ -1,4 +1,13 @@
// OpenGL ES JNI sample
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
android_app {
name: "TestEGL",
srcs: ["**/*.java"],
diff --git a/opengl/tests/testViewport/Android.bp b/opengl/tests/testViewport/Android.bp
index 629b573..13ce3ad 100644
--- a/opengl/tests/testViewport/Android.bp
+++ b/opengl/tests/testViewport/Android.bp
@@ -2,6 +2,15 @@
// OpenGL ES JNI sample
// This makefile builds both an activity and a shared library.
//########################################################################
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
android_app {
name: "TestViewport",
srcs: ["**/*.java"],
diff --git a/opengl/tests/textures/Android.bp b/opengl/tests/textures/Android.bp
index 84adda2..f113ff7 100644
--- a/opengl/tests/textures/Android.bp
+++ b/opengl/tests/textures/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_binary {
name: "test-opengl-textures",
srcs: ["textures.cpp"],
diff --git a/opengl/tests/tritex/Android.bp b/opengl/tests/tritex/Android.bp
index 390397b..759582c 100644
--- a/opengl/tests/tritex/Android.bp
+++ b/opengl/tests/tritex/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_binary {
name: "test-opengl-tritex",
srcs: ["tritex.cpp"],
diff --git a/services/audiomanager/Android.bp b/services/audiomanager/Android.bp
index 12ad47e..e6fb2c3 100644
--- a/services/audiomanager/Android.bp
+++ b/services/audiomanager/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libaudiomanager",
diff --git a/services/automotive/display/Android.bp b/services/automotive/display/Android.bp
index c3da216..72bd292 100644
--- a/services/automotive/display/Android.bp
+++ b/services/automotive/display/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_binary {
name: "android.frameworks.automotive.display@1.0-service",
defaults: ["hidl_defaults"],
diff --git a/services/batteryservice/Android.bp b/services/batteryservice/Android.bp
index 66ee8ff..1e37991 100644
--- a/services/batteryservice/Android.bp
+++ b/services/batteryservice/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "libbatteryservice_headers",
vendor_available: true,
diff --git a/services/displayservice/Android.bp b/services/displayservice/Android.bp
index 4d2d873..8681784 100644
--- a/services/displayservice/Android.bp
+++ b/services/displayservice/Android.bp
@@ -14,6 +14,15 @@
// limitations under the License.
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libdisplayservicehidl",
diff --git a/services/gpuservice/Android.bp b/services/gpuservice/Android.bp
index 9a9bca1..b9b6a19 100644
--- a/services/gpuservice/Android.bp
+++ b/services/gpuservice/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "gpuservice_defaults",
cflags: [
diff --git a/services/gpuservice/bpfprogs/Android.bp b/services/gpuservice/bpfprogs/Android.bp
index b875814..9842ed7 100644
--- a/services/gpuservice/bpfprogs/Android.bp
+++ b/services/gpuservice/bpfprogs/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
bpf {
name: "gpu_mem.o",
srcs: ["gpu_mem.c"],
diff --git a/services/gpuservice/gpumem/Android.bp b/services/gpuservice/gpumem/Android.bp
index b2230b6..830e53d 100644
--- a/services/gpuservice/gpumem/Android.bp
+++ b/services/gpuservice/gpumem/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libgpumem",
srcs: [
diff --git a/services/gpuservice/gpustats/Android.bp b/services/gpuservice/gpustats/Android.bp
index f52602a..54291ad 100644
--- a/services/gpuservice/gpustats/Android.bp
+++ b/services/gpuservice/gpustats/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libgfxstats",
srcs: [
diff --git a/services/gpuservice/tests/unittests/Android.bp b/services/gpuservice/tests/unittests/Android.bp
index 9606daa..6d87c45 100644
--- a/services/gpuservice/tests/unittests/Android.bp
+++ b/services/gpuservice/tests/unittests/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "gpuservice_unittest",
test_suites: ["device-tests"],
diff --git a/services/gpuservice/tracing/Android.bp b/services/gpuservice/tracing/Android.bp
index 919fed3..a1bc1ed 100644
--- a/services/gpuservice/tracing/Android.bp
+++ b/services/gpuservice/tracing/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libgpumemtracer",
srcs: [
diff --git a/services/inputflinger/Android.bp b/services/inputflinger/Android.bp
index b640e9c..9b98a17 100644
--- a/services/inputflinger/Android.bp
+++ b/services/inputflinger/Android.bp
@@ -13,6 +13,15 @@
// limitations under the License.
// Default flags to be used throughout all libraries in inputflinger.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "inputflinger_defaults",
cflags: [
diff --git a/services/inputflinger/benchmarks/Android.bp b/services/inputflinger/benchmarks/Android.bp
index bd275a7..ea37f4d 100644
--- a/services/inputflinger/benchmarks/Android.bp
+++ b/services/inputflinger/benchmarks/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_benchmark {
name: "inputflinger_benchmarks",
srcs: [
diff --git a/services/inputflinger/dispatcher/Android.bp b/services/inputflinger/dispatcher/Android.bp
index e5b131e..393f649 100644
--- a/services/inputflinger/dispatcher/Android.bp
+++ b/services/inputflinger/dispatcher/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "libinputdispatcher_headers",
export_include_dirs: [
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp
index e4237b5..9898e9d 100644
--- a/services/inputflinger/dispatcher/InputDispatcher.cpp
+++ b/services/inputflinger/dispatcher/InputDispatcher.cpp
@@ -1673,9 +1673,7 @@
if (!mKeyIsWaitingForEventsTimeout.has_value()) {
// Start the timer
- ALOGD("Waiting to send key to %s because there are unprocessed events that may cause "
- "focus to change",
- focusedWindowName);
+ // Wait to send key because there are unprocessed events that may cause focus to change
mKeyIsWaitingForEventsTimeout = currentTime +
std::chrono::duration_cast<std::chrono::nanoseconds>(KEY_WAITING_FOR_EVENTS_TIMEOUT)
.count();
@@ -2834,10 +2832,6 @@
* This includes situations like the soft BACK button key. When the user releases (lifts up the
* finger) the back button, then navigation bar will inject KEYCODE_BACK with ACTION_UP.
* Both of those ACTION_UP events would not be logged
- * Monitors (both gesture and global): any gesture monitors or global monitors receiving events
- * will not be logged. This is omitted to reduce the amount of data printed.
- * If you see <none>, it's likely that one of the gesture monitors pilfered the event, and therefore
- * gesture monitor is the only connection receiving the remainder of the gesture.
*/
void InputDispatcher::updateInteractionTokensLocked(const EventEntry& entry,
const std::vector<InputTarget>& targets) {
@@ -2867,8 +2861,8 @@
sp<IBinder> token = target.inputChannel->getConnectionToken();
sp<Connection> connection = getConnectionLocked(token);
- if (connection == nullptr || connection->monitor) {
- continue; // We only need to keep track of the non-monitor connections.
+ if (connection == nullptr) {
+ continue;
}
newConnectionTokens.insert(std::move(token));
newConnections.emplace_back(connection);
@@ -2878,12 +2872,12 @@
}
mInteractionConnectionTokens = newConnectionTokens;
- std::string windowList;
+ std::string targetList;
for (const sp<Connection>& connection : newConnections) {
- windowList += connection->getWindowName() + ", ";
+ targetList += connection->getWindowName() + ", ";
}
- std::string message = "Interaction with windows: " + windowList;
- if (windowList.empty()) {
+ std::string message = "Interaction with: " + targetList;
+ if (targetList.empty()) {
message += "<none>";
}
android_log_event_list(LOGTAG_INPUT_INTERACTION) << message << LOG_ID_EVENTS;
@@ -3221,8 +3215,7 @@
}
} else {
// Monitor channels are never explicitly unregistered.
- // We do it automatically when the remote endpoint is closed so don't warn
- // about them.
+ // We do it automatically when the remote endpoint is closed so don't warn about them.
const bool stillHaveWindowHandle =
d->getWindowHandleLocked(connection->inputChannel->getConnectionToken()) !=
nullptr;
@@ -4978,7 +4971,7 @@
bool notify) {
sp<Connection> connection = getConnectionLocked(connectionToken);
if (connection == nullptr) {
- ALOGW("Attempted to unregister already unregistered input channel");
+ // Connection can be removed via socket hang up or an explicit call to 'removeInputChannel'
return BAD_VALUE;
}
@@ -5042,9 +5035,11 @@
}
TouchState& state = stateIt->second;
+ std::shared_ptr<InputChannel> requestingChannel;
std::optional<int32_t> foundDeviceId;
for (const TouchedMonitor& touchedMonitor : state.gestureMonitors) {
if (touchedMonitor.monitor.inputChannel->getConnectionToken() == token) {
+ requestingChannel = touchedMonitor.monitor.inputChannel;
foundDeviceId = state.deviceId;
}
}
@@ -5060,13 +5055,19 @@
"gesture monitor stole pointer stream");
options.deviceId = deviceId;
options.displayId = displayId;
+ std::string canceledWindows = "[";
for (const TouchedWindow& window : state.windows) {
std::shared_ptr<InputChannel> channel =
getInputChannelLocked(window.windowHandle->getToken());
if (channel != nullptr) {
synthesizeCancelationEventsForInputChannelLocked(channel, options);
+ canceledWindows += channel->getName() + ", ";
}
}
+ canceledWindows += "]";
+ ALOGI("Monitor %s is stealing touch from %s", requestingChannel->getName().c_str(),
+ canceledWindows.c_str());
+
// Then clear the current touch state so we stop dispatching to them as well.
state.filterNonMonitors();
}
diff --git a/services/inputflinger/host/Android.bp b/services/inputflinger/host/Android.bp
index 9e797e4..18d0226 100644
--- a/services/inputflinger/host/Android.bp
+++ b/services/inputflinger/host/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libinputflingerhost",
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
index 7f979f2..518e295 100644
--- a/services/inputflinger/reader/Android.bp
+++ b/services/inputflinger/reader/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "libinputreader_headers",
export_include_dirs: [
diff --git a/services/inputflinger/reporter/Android.bp b/services/inputflinger/reporter/Android.bp
index fbc51da..7430731 100644
--- a/services/inputflinger/reporter/Android.bp
+++ b/services/inputflinger/reporter/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "libinputreporter_headers",
export_include_dirs: ["."],
@@ -46,4 +55,3 @@
"libinputreporter_headers",
],
}
-
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index 959dadc..42b54c7 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "inputflinger_tests",
defaults: [
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 01945db..f440f59 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -31,6 +31,7 @@
using android::base::StringPrintf;
using android::os::InputEventInjectionResult;
using android::os::InputEventInjectionSync;
+using android::os::TouchOcclusionMode;
using namespace android::flag_operators;
namespace android::inputdispatcher {
@@ -727,8 +728,9 @@
ASSERT_EQ(OK, status) << mName.c_str() << ": consumer sendFinishedSignal should return OK.";
}
- void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
- int32_t expectedFlags) {
+ void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
+ std::optional<int32_t> expectedDisplayId,
+ std::optional<int32_t> expectedFlags) {
InputEvent* event = consume();
ASSERT_NE(nullptr, event) << mName.c_str()
@@ -737,19 +739,25 @@
<< mName.c_str() << " expected " << inputEventTypeToString(expectedEventType)
<< " event, got " << inputEventTypeToString(event->getType()) << " event";
- EXPECT_EQ(expectedDisplayId, event->getDisplayId());
+ if (expectedDisplayId.has_value()) {
+ EXPECT_EQ(expectedDisplayId, event->getDisplayId());
+ }
switch (expectedEventType) {
case AINPUT_EVENT_TYPE_KEY: {
const KeyEvent& keyEvent = static_cast<const KeyEvent&>(*event);
EXPECT_EQ(expectedAction, keyEvent.getAction());
- EXPECT_EQ(expectedFlags, keyEvent.getFlags());
+ if (expectedFlags.has_value()) {
+ EXPECT_EQ(expectedFlags.value(), keyEvent.getFlags());
+ }
break;
}
case AINPUT_EVENT_TYPE_MOTION: {
const MotionEvent& motionEvent = static_cast<const MotionEvent&>(*event);
EXPECT_EQ(expectedAction, motionEvent.getAction());
- EXPECT_EQ(expectedFlags, motionEvent.getFlags());
+ if (expectedFlags.has_value()) {
+ EXPECT_EQ(expectedFlags.value(), motionEvent.getFlags());
+ }
break;
}
case AINPUT_EVENT_TYPE_FOCUS: {
@@ -854,6 +862,7 @@
mInfo.name = name;
mInfo.type = InputWindowInfo::Type::APPLICATION;
mInfo.dispatchingTimeout = DISPATCHING_TIMEOUT;
+ mInfo.alpha = 1.0;
mInfo.frameLeft = 0;
mInfo.frameTop = 0;
mInfo.frameRight = WIDTH;
@@ -883,6 +892,12 @@
void setPaused(bool paused) { mInfo.paused = paused; }
+ void setAlpha(float alpha) { mInfo.alpha = alpha; }
+
+ void setTouchOcclusionMode(android::os::TouchOcclusionMode mode) {
+ mInfo.touchOcclusionMode = mode;
+ }
+
void setFrame(const Rect& frame) {
mInfo.frameLeft = frame.left;
mInfo.frameTop = frame.top;
@@ -928,6 +943,11 @@
void consumeMotionDown(int32_t expectedDisplayId = ADISPLAY_ID_DEFAULT,
int32_t expectedFlags = 0) {
+ consumeAnyMotionDown(expectedDisplayId, expectedFlags);
+ }
+
+ void consumeAnyMotionDown(std::optional<int32_t> expectedDisplayId = std::nullopt,
+ std::optional<int32_t> expectedFlags = std::nullopt) {
consumeEvent(AINPUT_EVENT_TYPE_MOTION, AMOTION_EVENT_ACTION_DOWN, expectedDisplayId,
expectedFlags);
}
@@ -971,8 +991,9 @@
mInputReceiver->consumeCaptureEvent(hasCapture);
}
- void consumeEvent(int32_t expectedEventType, int32_t expectedAction, int32_t expectedDisplayId,
- int32_t expectedFlags) {
+ void consumeEvent(int32_t expectedEventType, int32_t expectedAction,
+ std::optional<int32_t> expectedDisplayId,
+ std::optional<int32_t> expectedFlags) {
ASSERT_NE(mInputReceiver, nullptr) << "Invalid consume event on window with no receiver";
mInputReceiver->consumeEvent(expectedEventType, expectedAction, expectedDisplayId,
expectedFlags);
@@ -4240,4 +4261,183 @@
mSecondWindow->consumeCaptureEvent(true);
}
+class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
+protected:
+ constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
+ static const int32_t APP_A_UID = 10001;
+ static const int32_t APP_B_UID = 10002;
+ static const int32_t APP_C_UID = 10003;
+
+ sp<FakeWindowHandle> mTouchWindow;
+
+ virtual void SetUp() override {
+ InputDispatcherTest::SetUp();
+ mTouchWindow = getWindow(APP_A_UID, "Touched");
+ mDispatcher->setBlockUntrustedTouchesMode(android::os::BlockUntrustedTouchesMode::BLOCK);
+ mDispatcher->setMaximumObscuringOpacityForTouch(MAXIMUM_OBSCURING_OPACITY);
+ }
+
+ virtual void TearDown() override {
+ InputDispatcherTest::TearDown();
+ mTouchWindow.clear();
+ }
+
+ sp<FakeWindowHandle> getOccludingWindow(int32_t uid, std::string name,
+ os::TouchOcclusionMode mode, float alpha = 1.0f) {
+ sp<FakeWindowHandle> window = getWindow(uid, name);
+ window->setFlags(InputWindowInfo::Flag::NOT_TOUCHABLE);
+ window->setTouchOcclusionMode(mode);
+ window->setAlpha(alpha);
+ return window;
+ }
+
+ sp<FakeWindowHandle> getWindow(int32_t uid, std::string name) {
+ std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
+ sp<FakeWindowHandle> window =
+ new FakeWindowHandle(app, mDispatcher, name, ADISPLAY_ID_DEFAULT);
+ // Generate an arbitrary PID based on the UID
+ window->setOwnerInfo(1777 + (uid % 10000), uid);
+ return window;
+ }
+
+ void touch(const std::vector<PointF>& points = {PointF{100, 200}}) {
+ NotifyMotionArgs args =
+ generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
+ ADISPLAY_ID_DEFAULT, points);
+ mDispatcher->notifyMotion(&args);
+ }
+};
+
+TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithBlockUntrustedOcclusionMode_BlocksTouch) {
+ const sp<FakeWindowHandle>& w =
+ getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
+
+ touch();
+
+ mTouchWindow->assertNoEvents();
+}
+
+TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithAllowOcclusionMode_AllowsTouch) {
+ const sp<FakeWindowHandle>& w = getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::ALLOW);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
+
+ touch();
+
+ mTouchWindow->consumeAnyMotionDown();
+}
+
+TEST_F(InputDispatcherUntrustedTouchesTest, TouchOutsideOccludingWindow_AllowsTouch) {
+ const sp<FakeWindowHandle>& w =
+ getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED);
+ w->setFrame(Rect(0, 0, 50, 50));
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
+
+ touch({PointF{100, 100}});
+
+ mTouchWindow->consumeAnyMotionDown();
+}
+
+TEST_F(InputDispatcherUntrustedTouchesTest, WindowFromSameUid_AllowsTouch) {
+ const sp<FakeWindowHandle>& w =
+ getOccludingWindow(APP_A_UID, "A", TouchOcclusionMode::BLOCK_UNTRUSTED);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
+
+ touch();
+
+ mTouchWindow->consumeAnyMotionDown();
+}
+
+TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithZeroOpacity_AllowsTouch) {
+ const sp<FakeWindowHandle>& w =
+ getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::BLOCK_UNTRUSTED, 0.0f);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
+
+ touch();
+
+ mTouchWindow->consumeAnyMotionDown();
+}
+
+TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityBelowThreshold_AllowsTouch) {
+ const sp<FakeWindowHandle>& w =
+ getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.7f);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
+
+ touch();
+
+ mTouchWindow->consumeAnyMotionDown();
+}
+
+TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAtThreshold_AllowsTouch) {
+ const sp<FakeWindowHandle>& w =
+ getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY,
+ MAXIMUM_OBSCURING_OPACITY);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
+
+ touch();
+
+ mTouchWindow->consumeAnyMotionDown();
+}
+
+TEST_F(InputDispatcherUntrustedTouchesTest, WindowWithOpacityAboveThreshold_BlocksTouch) {
+ const sp<FakeWindowHandle>& w =
+ getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.9f);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w, mTouchWindow}}});
+
+ touch();
+
+ mTouchWindow->assertNoEvents();
+}
+
+TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityAboveThreshold_BlocksTouch) {
+ // Resulting opacity = 1 - (1 - 0.7)*(1 - 0.7) = .91
+ const sp<FakeWindowHandle>& w1 =
+ getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY, 0.7f);
+ const sp<FakeWindowHandle>& w2 =
+ getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY, 0.7f);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
+
+ touch();
+
+ mTouchWindow->assertNoEvents();
+}
+
+TEST_F(InputDispatcherUntrustedTouchesTest, WindowsWithCombinedOpacityBelowThreshold_AllowsTouch) {
+ // Resulting opacity = 1 - (1 - 0.5)*(1 - 0.5) = .75
+ const sp<FakeWindowHandle>& w1 =
+ getOccludingWindow(APP_B_UID, "B1", TouchOcclusionMode::USE_OPACITY, 0.5f);
+ const sp<FakeWindowHandle>& w2 =
+ getOccludingWindow(APP_B_UID, "B2", TouchOcclusionMode::USE_OPACITY, 0.5f);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {w1, w2, mTouchWindow}}});
+
+ touch();
+
+ mTouchWindow->consumeAnyMotionDown();
+}
+
+TEST_F(InputDispatcherUntrustedTouchesTest,
+ WindowsFromDifferentAppsEachBelowThreshold_AllowsTouch) {
+ const sp<FakeWindowHandle>& wB =
+ getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.7f);
+ const sp<FakeWindowHandle>& wC =
+ getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY, 0.7f);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
+
+ touch();
+
+ mTouchWindow->consumeAnyMotionDown();
+}
+
+TEST_F(InputDispatcherUntrustedTouchesTest, WindowsFromDifferentAppsOneAboveThreshold_BlocksTouch) {
+ const sp<FakeWindowHandle>& wB =
+ getOccludingWindow(APP_B_UID, "B", TouchOcclusionMode::USE_OPACITY, 0.7f);
+ const sp<FakeWindowHandle>& wC =
+ getOccludingWindow(APP_C_UID, "C", TouchOcclusionMode::USE_OPACITY, 0.9f);
+ mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {wB, wC, mTouchWindow}}});
+
+ touch();
+
+ mTouchWindow->assertNoEvents();
+}
+
} // namespace android::inputdispatcher
diff --git a/services/powermanager/Android.bp b/services/powermanager/Android.bp
index 68f4f28..1d3e5b5 100644
--- a/services/powermanager/Android.bp
+++ b/services/powermanager/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libpowermanager",
diff --git a/services/schedulerservice/Android.bp b/services/schedulerservice/Android.bp
index 73802db..4ef72d0 100644
--- a/services/schedulerservice/Android.bp
+++ b/services/schedulerservice/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libschedulerservicehidl",
srcs: [
diff --git a/services/sensorservice/Android.bp b/services/sensorservice/Android.bp
index 532a2e5..ca9ff7c 100644
--- a/services/sensorservice/Android.bp
+++ b/services/sensorservice/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
subdirs = [
"hidl"
]
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 2810bff..23893ea 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -914,6 +914,21 @@
return mActivationCount.valueAt(activationIndex).numActiveClients() > 0;
}
+void SensorDevice::onMicSensorAccessChanged(void* ident, int handle, nsecs_t samplingPeriodNs) {
+ Mutex::Autolock _l(mLock);
+ ssize_t activationIndex = mActivationCount.indexOfKey(handle);
+ if (activationIndex < 0) {
+ ALOGW("Handle %d cannot be found in activation record", handle);
+ return;
+ }
+ Info& info(mActivationCount.editValueAt(activationIndex));
+ if (info.hasBatchParamsForIdent(ident)) {
+ ssize_t index = info.batchParams.indexOfKey(ident);
+ BatchParams& params = info.batchParams.editValueAt(index);
+ params.mTSample = samplingPeriodNs;
+ }
+}
+
void SensorDevice::enableAllSensors() {
if (mSensors == nullptr) return;
Mutex::Autolock _l(mLock);
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index 5e7d3da..75da7bb 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -125,6 +125,10 @@
bool isSensorActive(int handle) const;
+ // To update the BatchParams of a SensorEventConnection when the mic toggle changes its state
+ // while the Sensors Off toggle is on.
+ void onMicSensorAccessChanged(void* ident, int handle, nsecs_t samplingPeriodNs);
+
// Dumpable
virtual std::string dump() const override;
virtual void dump(util::ProtoOutputStream* proto) const override;
diff --git a/services/sensorservice/SensorDirectConnection.cpp b/services/sensorservice/SensorDirectConnection.cpp
index e4c33da..af86d09 100644
--- a/services/sensorservice/SensorDirectConnection.cpp
+++ b/services/sensorservice/SensorDirectConnection.cpp
@@ -32,6 +32,8 @@
: mService(service), mUid(uid), mMem(*mem),
mHalChannelHandle(halChannelHandle),
mOpPackageName(opPackageName), mDestroyed(false) {
+ mIsRateCappedBasedOnPermission = mService->isRateCappedBasedOnPermission(mOpPackageName);
+ mUserId = multiuser_get_user_id(mUid);
ALOGD_IF(DEBUG_CONNECTIONS, "Created SensorDirectConnection");
}
@@ -101,6 +103,14 @@
}
}
+void SensorService::SensorDirectConnection::onMicSensorAccessChanged(bool isMicToggleOn) {
+ if (isMicToggleOn) {
+ capRates();
+ } else {
+ uncapRates();
+ }
+}
+
bool SensorService::SensorDirectConnection::hasSensorAccess() const {
return mService->hasSensorAccess(mUid, mOpPackageName);
}
@@ -134,6 +144,7 @@
if (handle == -1 && rateLevel == SENSOR_DIRECT_RATE_STOP) {
stopAll();
+ mMicRateBackup.clear();
return NO_ERROR;
}
@@ -157,6 +168,14 @@
return INVALID_OPERATION;
}
+ int requestedRateLevel = rateLevel;
+ if (mService->isSensorInCappedSet(s.getType()) && rateLevel != SENSOR_DIRECT_RATE_STOP) {
+ status_t err = mService->adjustRateLevelBasedOnMicAndPermission(&rateLevel, mOpPackageName);
+ if (err != OK) {
+ return err;
+ }
+ }
+
struct sensors_direct_cfg_t config = {
.rate_level = rateLevel
};
@@ -168,18 +187,100 @@
if (rateLevel == SENSOR_DIRECT_RATE_STOP) {
if (ret == NO_ERROR) {
mActivated.erase(handle);
+ mMicRateBackup.erase(handle);
} else if (ret > 0) {
ret = UNKNOWN_ERROR;
}
} else {
if (ret > 0) {
mActivated[handle] = rateLevel;
+ if (mService->isSensorInCappedSet(s.getType())) {
+ // Back up the rates that the app is allowed to have if the mic toggle is off
+ // This is used in the uncapRates() function.
+ if (!mIsRateCappedBasedOnPermission ||
+ requestedRateLevel <= SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL) {
+ mMicRateBackup[handle] = requestedRateLevel;
+ } else {
+ mMicRateBackup[handle] = SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL;
+ }
+ }
}
}
return ret;
}
+void SensorService::SensorDirectConnection::capRates() {
+ Mutex::Autolock _l(mConnectionLock);
+ const struct sensors_direct_cfg_t capConfig = {
+ .rate_level = SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL
+ };
+
+ const struct sensors_direct_cfg_t stopConfig = {
+ .rate_level = SENSOR_DIRECT_RATE_STOP
+ };
+
+ // If our requests are in the backup, then we shouldn't activate sensors from here
+ bool temporarilyStopped = mActivated.empty() && !mActivatedBackup.empty();
+ std::unordered_map<int, int>& existingConnections =
+ (!temporarilyStopped) ? mActivated : mActivatedBackup;
+
+ SensorDevice& dev(SensorDevice::getInstance());
+ for (auto &i : existingConnections) {
+ int handle = i.first;
+ int rateLevel = i.second;
+ sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
+ if (si != nullptr) {
+ const Sensor& s = si->getSensor();
+ if (mService->isSensorInCappedSet(s.getType()) &&
+ rateLevel > SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL) {
+ mMicRateBackup[handle] = rateLevel;
+ // Modify the rate kept by the existing map
+ existingConnections[handle] = SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL;
+ // Only reconfigure the channel if it's ongoing
+ if (!temporarilyStopped) {
+ // Stopping before reconfiguring is the well-tested path in CTS
+ dev.configureDirectChannel(handle, getHalChannelHandle(), &stopConfig);
+ dev.configureDirectChannel(handle, getHalChannelHandle(), &capConfig);
+ }
+ }
+ }
+ }
+}
+
+void SensorService::SensorDirectConnection::uncapRates() {
+ Mutex::Autolock _l(mConnectionLock);
+
+ // If our requests are in the backup, then we shouldn't activate sensors from here
+ bool temporarilyStopped = mActivated.empty() && !mActivatedBackup.empty();
+ std::unordered_map<int, int>& existingConnections =
+ (!temporarilyStopped) ? mActivated : mActivatedBackup;
+
+ const struct sensors_direct_cfg_t stopConfig = {
+ .rate_level = SENSOR_DIRECT_RATE_STOP
+ };
+ SensorDevice& dev(SensorDevice::getInstance());
+ for (auto &i : mMicRateBackup) {
+ int handle = i.first;
+ int rateLevel = i.second;
+
+ const struct sensors_direct_cfg_t config = {
+ .rate_level = rateLevel
+ };
+
+ // Modify the rate kept by the existing map
+ existingConnections[handle] = rateLevel;
+
+ // Only reconfigure the channel if it's ongoing
+ if (!temporarilyStopped) {
+ // Stopping before reconfiguring is the well-tested path in CTS
+ dev.configureDirectChannel(handle, getHalChannelHandle(), &stopConfig);
+ dev.configureDirectChannel(handle, getHalChannelHandle(), &config);
+ }
+ }
+ mMicRateBackup.clear();
+}
+
void SensorService::SensorDirectConnection::stopAll(bool backupRecord) {
Mutex::Autolock _l(mConnectionLock);
stopAllLocked(backupRecord);
diff --git a/services/sensorservice/SensorDirectConnection.h b/services/sensorservice/SensorDirectConnection.h
index 4181b65..a3f348b 100644
--- a/services/sensorservice/SensorDirectConnection.h
+++ b/services/sensorservice/SensorDirectConnection.h
@@ -50,6 +50,8 @@
// regained due to changes in the sensor restricted/privacy mode or the
// app changed to idle/active status.
void onSensorAccessChanged(bool hasAccess);
+ void onMicSensorAccessChanged(bool isMicToggleOn);
+ userid_t getUserId() const { return mUserId; }
protected:
virtual ~SensorDirectConnection();
@@ -82,6 +84,11 @@
// If no requests are backed up by stopAll(), this method is no-op.
void recoverAll();
+ // Limits all active sensor direct report requests when the mic toggle is flipped to on.
+ void capRates();
+ // Recover sensor requests previously capped by capRates().
+ void uncapRates();
+
const sp<SensorService> mService;
const uid_t mUid;
const sensors_direct_mem_t mMem;
@@ -91,9 +98,12 @@
mutable Mutex mConnectionLock;
std::unordered_map<int, int> mActivated;
std::unordered_map<int, int> mActivatedBackup;
+ std::unordered_map<int, int> mMicRateBackup;
+ std::atomic_bool mIsRateCappedBasedOnPermission;
mutable Mutex mDestroyLock;
bool mDestroyed;
+ userid_t mUserId;
};
} // namepsace android
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index 6810c1b7..a2e7f23 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -44,6 +44,8 @@
mCacheSize(0), mMaxCacheSize(0), mTimeOfLastEventDrop(0), mEventsDropped(0),
mPackageName(packageName), mOpPackageName(opPackageName), mTargetSdk(kTargetSdkUnknown),
mDestroyed(false) {
+ mIsRateCappedBasedOnPermission = mService->isRateCappedBasedOnPermission(mOpPackageName);
+ mUserId = multiuser_get_user_id(mUid);
mChannel = new BitTube(mService->mSocketBufferSize);
#if DEBUG_CONNECTIONS
mEventsReceived = mEventsSentFromCache = mEventsSent = 0;
@@ -285,6 +287,29 @@
}
}
+// TODO(b/179649922): A better algorithm to guarantee that capped connections will get a sampling
+// rate close to 200 Hz. With the current algorithm, apps might be punished unfairly: E.g.,two apps
+// make requests to the sensor service at the same time, one is not capped and uses 250 Hz, and one
+//is capped, the capped connection will only get 125 Hz.
+void SensorService::SensorEventConnection::addSensorEventsToBuffer(bool shouldResample,
+ const sensors_event_t& sensorEvent, sensors_event_t* buffer, int* index) {
+ if (!shouldResample || !mService->isSensorInCappedSet(sensorEvent.type)) {
+ buffer[(*index)++] = sensorEvent;
+ } else {
+ int64_t lastTimestamp = -1;
+ auto entry = mSensorLastTimestamp.find(sensorEvent.sensor);
+ if (entry != mSensorLastTimestamp.end()) {
+ lastTimestamp = entry->second;
+ }
+ // Allow 10% headroom here because the clocks are not perfect.
+ if (lastTimestamp == -1 || sensorEvent.timestamp - lastTimestamp
+ >= 0.9 * SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS) {
+ mSensorLastTimestamp[sensorEvent.sensor] = sensorEvent.timestamp;
+ buffer[(*index)++] = sensorEvent;
+ }
+ }
+}
+
status_t SensorService::SensorEventConnection::sendEvents(
sensors_event_t const* buffer, size_t numEvents,
sensors_event_t* scratch,
@@ -293,6 +318,8 @@
std::unique_ptr<sensors_event_t[]> sanitizedBuffer;
+ bool shouldResample = mService->isMicSensorPrivacyEnabledForUid(mUid) ||
+ mIsRateCappedBasedOnPermission;
int count = 0;
Mutex::Autolock _l(mConnectionLock);
if (scratch) {
@@ -346,7 +373,7 @@
// Regular sensor event, just copy it to the scratch buffer after checking
// the AppOp.
if (hasSensorAccess() && noteOpIfRequired(buffer[i])) {
- scratch[count++] = buffer[i];
+ addSensorEventsToBuffer(shouldResample, buffer[i], scratch, &count);
}
}
i++;
@@ -356,12 +383,13 @@
buffer[i].meta_data.sensor == sensor_handle)));
}
} else {
+ sanitizedBuffer.reset(new sensors_event_t[numEvents]);
+ scratch = sanitizedBuffer.get();
if (hasSensorAccess()) {
- scratch = const_cast<sensors_event_t *>(buffer);
- count = numEvents;
+ for (size_t i = 0; i < numEvents; i++) {
+ addSensorEventsToBuffer(shouldResample, buffer[i], scratch, &count);
+ }
} else {
- sanitizedBuffer.reset(new sensors_event_t[numEvents]);
- scratch = sanitizedBuffer.get();
for (size_t i = 0; i < numEvents; i++) {
if (buffer[i].type == SENSOR_TYPE_META_DATA) {
scratch[count++] = buffer[i++];
@@ -684,24 +712,118 @@
status_t err;
if (enabled) {
+ nsecs_t requestedSamplingPeriodNs = samplingPeriodNs;
+ bool isSensorCapped = false;
+ sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
+ if (si != nullptr) {
+ const Sensor& s = si->getSensor();
+ if (mService->isSensorInCappedSet(s.getType())) {
+ isSensorCapped = true;
+ }
+ }
+ if (isSensorCapped) {
+ err = mService->adjustSamplingPeriodBasedOnMicAndPermission(&samplingPeriodNs,
+ String16(mOpPackageName));
+ if (err != OK) {
+ return err;
+ }
+ }
err = mService->enable(this, handle, samplingPeriodNs, maxBatchReportLatencyNs,
reservedFlags, mOpPackageName);
+ if (err == OK && isSensorCapped) {
+ if (!mIsRateCappedBasedOnPermission ||
+ requestedSamplingPeriodNs >= SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS) {
+ mMicSamplingPeriodBackup[handle] = requestedSamplingPeriodNs;
+ } else {
+ mMicSamplingPeriodBackup[handle] = SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS;
+ }
+ }
} else {
err = mService->disable(this, handle);
+ mMicSamplingPeriodBackup.erase(handle);
}
return err;
}
-status_t SensorService::SensorEventConnection::setEventRate(
- int handle, nsecs_t samplingPeriodNs)
-{
+status_t SensorService::SensorEventConnection::setEventRate(int handle, nsecs_t samplingPeriodNs) {
if (mDestroyed) {
android_errorWriteLog(0x534e4554, "168211968");
return DEAD_OBJECT;
}
- return mService->setEventRate(this, handle, samplingPeriodNs, mOpPackageName);
+ nsecs_t requestedSamplingPeriodNs = samplingPeriodNs;
+ bool isSensorCapped = false;
+ sp<SensorInterface> si = mService->getSensorInterfaceFromHandle(handle);
+ if (si != nullptr) {
+ const Sensor& s = si->getSensor();
+ if (mService->isSensorInCappedSet(s.getType())) {
+ isSensorCapped = true;
+ }
+ }
+ if (isSensorCapped) {
+ status_t err = mService->adjustSamplingPeriodBasedOnMicAndPermission(&samplingPeriodNs,
+ String16(mOpPackageName));
+ if (err != OK) {
+ return err;
+ }
+ }
+ status_t ret = mService->setEventRate(this, handle, samplingPeriodNs, mOpPackageName);
+ if (ret == OK && isSensorCapped) {
+ if (!mIsRateCappedBasedOnPermission ||
+ requestedSamplingPeriodNs >= SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS) {
+ mMicSamplingPeriodBackup[handle] = requestedSamplingPeriodNs;
+ } else {
+ mMicSamplingPeriodBackup[handle] = SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS;
+ }
+ }
+ return ret;
+}
+
+void SensorService::SensorEventConnection::onMicSensorAccessChanged(bool isMicToggleOn) {
+ if (isMicToggleOn) {
+ capRates();
+ } else {
+ uncapRates();
+ }
+}
+
+void SensorService::SensorEventConnection::capRates() {
+ Mutex::Autolock _l(mConnectionLock);
+ SensorDevice& dev(SensorDevice::getInstance());
+ for (auto &i : mMicSamplingPeriodBackup) {
+ int handle = i.first;
+ nsecs_t samplingPeriodNs = i.second;
+ if (samplingPeriodNs < SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS) {
+ if (hasSensorAccess()) {
+ mService->setEventRate(this, handle, SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS,
+ mOpPackageName);
+ } else {
+ // Update SensorDevice with the capped rate so that when sensor access is restored,
+ // the correct event rate is used.
+ dev.onMicSensorAccessChanged(this, handle,
+ SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS);
+ }
+ }
+ }
+}
+
+void SensorService::SensorEventConnection::uncapRates() {
+ Mutex::Autolock _l(mConnectionLock);
+ SensorDevice& dev(SensorDevice::getInstance());
+ for (auto &i : mMicSamplingPeriodBackup) {
+ int handle = i.first;
+ nsecs_t samplingPeriodNs = i.second;
+ if (samplingPeriodNs < SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS) {
+ if (hasSensorAccess()) {
+ mService->setEventRate(this, handle, samplingPeriodNs, mOpPackageName);
+ } else {
+ // Update SensorDevice with the uncapped rate so that when sensor access is
+ // restored, the correct event rate is used.
+ dev.onMicSensorAccessChanged(this, handle, samplingPeriodNs);
+ }
+ }
+ }
}
status_t SensorService::SensorEventConnection::flush() {
diff --git a/services/sensorservice/SensorEventConnection.h b/services/sensorservice/SensorEventConnection.h
index 9487a39..7bd9d47 100644
--- a/services/sensorservice/SensorEventConnection.h
+++ b/services/sensorservice/SensorEventConnection.h
@@ -68,6 +68,9 @@
String8 getPackageName() const;
uid_t getUid() const { return mUid; }
+ // cap/uncap existing connection depending on the state of the mic toggle.
+ void onMicSensorAccessChanged(bool isMicToggleOn);
+ userid_t getUserId() const { return mUserId; }
private:
virtual ~SensorEventConnection();
@@ -137,10 +140,20 @@
// Call noteOp for the sensor if the sensor requires a permission
bool noteOpIfRequired(const sensors_event_t& event);
+ // Limits all active connections when the mic toggle is flipped to on.
+ void capRates();
+ // Recover sensor connection previously capped by capRates().
+ void uncapRates();
+ // Add sensorEvent to buffer at position index if the sensorEvent satisfies throttling rules.
+ void addSensorEventsToBuffer(bool shouldResample, const sensors_event_t& sensorEvent,
+ sensors_event_t* buffer, int* index);
sp<SensorService> const mService;
sp<BitTube> mChannel;
uid_t mUid;
+ std::atomic_bool mIsRateCappedBasedOnPermission;
+ // Store a mapping of sensor to the timestamp of their last sensor event.
+ std::unordered_map<int, int64_t> mSensorLastTimestamp;
mutable Mutex mConnectionLock;
// Number of events from wake up sensors which are still pending and haven't been delivered to
// the corresponding application. It is incremented by one unit for each write to the socket.
@@ -189,6 +202,9 @@
// Store a mapping of sensor handles to required AppOp for a sensor. This map only contains a
// valid mapping for sensors that require a permission in order to reduce the lookup time.
std::unordered_map<int32_t, int32_t> mHandleToAppOp;
+ // Mapping of sensor handles to its rate before being capped by the mic toggle.
+ std::unordered_map<int, nsecs_t> mMicSamplingPeriodBackup;
+ userid_t mUserId;
};
} // namepsace android
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 8f25bdb..89d1c42 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include <android-base/strings.h>
#include <android/content/pm/IPackageManagerNative.h>
#include <android/util/ProtoOutputStream.h>
#include <frameworks/base/core/proto/android/service/sensor_service.proto.h>
@@ -88,6 +89,8 @@
#define SENSOR_SERVICE_SCHED_FIFO_PRIORITY 10
// Permissions.
+static const String16 sAccessHighSensorSamplingRatePermission(
+ "android.permission.HIGH_SAMPLING_RATE_SENSORS");
static const String16 sDumpPermission("android.permission.DUMP");
static const String16 sLocationHardwarePermission("android.permission.LOCATION_HARDWARE");
static const String16 sManageSensorsPermission("android.permission.MANAGE_SENSORS");
@@ -366,6 +369,9 @@
}
mUidPolicy->unregisterSelf();
mSensorPrivacyPolicy->unregisterSelf();
+ for (auto const& [userId, policy] : mMicSensorPrivacyPolicies) {
+ policy->unregisterSelf();
+ }
}
status_t SensorService::dump(int fd, const Vector<String16>& args) {
@@ -695,6 +701,35 @@
}
}
+void SensorService::capRates(userid_t userId) {
+ ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
+ for (const sp<SensorDirectConnection>& conn : connLock.getDirectConnections()) {
+ if (conn->getUserId() == userId) {
+ conn->onMicSensorAccessChanged(true);
+ }
+ }
+
+ for (const sp<SensorEventConnection>& conn : connLock.getActiveConnections()) {
+ if (conn->getUserId() == userId) {
+ conn->onMicSensorAccessChanged(true);
+ }
+ }
+}
+
+void SensorService::uncapRates(userid_t userId) {
+ ConnectionSafeAutolock connLock = mConnectionHolder.lock(mLock);
+ for (const sp<SensorDirectConnection>& conn : connLock.getDirectConnections()) {
+ if (conn->getUserId() == userId) {
+ conn->onMicSensorAccessChanged(false);
+ }
+ }
+
+ for (const sp<SensorEventConnection>& conn : connLock.getActiveConnections()) {
+ if (conn->getUserId() == userId) {
+ conn->onMicSensorAccessChanged(false);
+ }
+ }
+}
// NOTE: This is a remote API - make sure all args are validated
status_t SensorService::shellCommand(int in, int out, int err, Vector<String16>& args) {
@@ -1209,14 +1244,20 @@
}
}
-Vector<Sensor> SensorService::getSensorList(const String16& /* opPackageName */) {
+Vector<Sensor> SensorService::getSensorList(const String16& opPackageName) {
char value[PROPERTY_VALUE_MAX];
property_get("debug.sensors", value, "0");
const Vector<Sensor>& initialSensorList = (atoi(value)) ?
mSensors.getUserDebugSensors() : mSensors.getUserSensors();
Vector<Sensor> accessibleSensorList;
+
+ bool isCapped = isRateCappedBasedOnPermission(opPackageName);
for (size_t i = 0; i < initialSensorList.size(); i++) {
Sensor sensor = initialSensorList[i];
+ if (isCapped && isSensorInCappedSet(sensor.getType())) {
+ sensor.capMinDelayMicros(SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS / 1000);
+ sensor.capHighestDirectReportRateLevel(SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL);
+ }
accessibleSensorList.add(sensor);
}
makeUuidsIntoIdsForSensorList(accessibleSensorList);
@@ -2024,6 +2065,69 @@
return mUidPolicy->isUidActive(uid);
}
+bool SensorService::isRateCappedBasedOnPermission(const String16& opPackageName) {
+ int targetSdk = getTargetSdkVersion(opPackageName);
+ bool hasSamplingRatePermission = PermissionCache::checkCallingPermission(
+ sAccessHighSensorSamplingRatePermission);
+ if (targetSdk < __ANDROID_API_S__ ||
+ (targetSdk >= __ANDROID_API_S__ && hasSamplingRatePermission)) {
+ return false;
+ }
+ return true;
+}
+
+bool SensorService::isSensorInCappedSet(int sensorType) {
+ return (sensorType == SENSOR_TYPE_ACCELEROMETER
+ || sensorType == SENSOR_TYPE_ACCELEROMETER_UNCALIBRATED
+ || sensorType == SENSOR_TYPE_GYROSCOPE
+ || sensorType == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED
+ || sensorType == SENSOR_TYPE_MAGNETIC_FIELD
+ || sensorType == SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED);
+}
+
+status_t SensorService::adjustSamplingPeriodBasedOnMicAndPermission(nsecs_t* requestedPeriodNs,
+ const String16& opPackageName) {
+ uid_t uid = IPCThreadState::self()->getCallingUid();
+ bool shouldCapBasedOnPermission = isRateCappedBasedOnPermission(opPackageName);
+ if (*requestedPeriodNs >= SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS) {
+ return OK;
+ }
+ if (shouldCapBasedOnPermission) {
+ *requestedPeriodNs = SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS;
+ if (isPackageDebuggable(opPackageName)) {
+ return PERMISSION_DENIED;
+ }
+ return OK;
+ }
+ if (isMicSensorPrivacyEnabledForUid(uid)) {
+ *requestedPeriodNs = SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS;
+ return OK;
+ }
+ return OK;
+}
+
+status_t SensorService::adjustRateLevelBasedOnMicAndPermission(int* requestedRateLevel,
+ const String16& opPackageName) {
+ uid_t uid = IPCThreadState::self()->getCallingUid();
+ bool shouldCapBasedOnPermission = isRateCappedBasedOnPermission(opPackageName);
+
+ if (*requestedRateLevel <= SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL) {
+ return OK;
+ }
+ if (shouldCapBasedOnPermission) {
+ *requestedRateLevel = SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL;
+ if (isPackageDebuggable(opPackageName)) {
+ return PERMISSION_DENIED;
+ }
+ return OK;
+ }
+ if (isMicSensorPrivacyEnabledForUid(uid)) {
+ *requestedRateLevel = SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL;
+ return OK;
+ }
+ return OK;
+}
+
void SensorService::SensorPrivacyPolicy::registerSelf() {
SensorPrivacyManager spm;
mSensorPrivacyEnabled = spm.isSensorPrivacyEnabled();
@@ -2042,16 +2146,56 @@
binder::Status SensorService::SensorPrivacyPolicy::onSensorPrivacyChanged(bool enabled) {
mSensorPrivacyEnabled = enabled;
sp<SensorService> service = mService.promote();
+
if (service != nullptr) {
- if (enabled) {
- service->disableAllSensors();
+ if (mIsIndividualMic) {
+ if (enabled) {
+ service->capRates(mUserId);
+ } else {
+ service->uncapRates(mUserId);
+ }
} else {
- service->enableAllSensors();
+ if (enabled) {
+ service->disableAllSensors();
+ } else {
+ service->enableAllSensors();
+ }
}
}
return binder::Status::ok();
}
+status_t SensorService::SensorPrivacyPolicy::registerSelfForIndividual(int userId) {
+ Mutex::Autolock _l(mSensorPrivacyLock);
+
+ SensorPrivacyManager spm;
+ status_t err = spm.addIndividualSensorPrivacyListener(userId,
+ SensorPrivacyManager::INDIVIDUAL_SENSOR_MICROPHONE, this);
+
+ if (err != OK) {
+ ALOGE("Cannot register a mic listener.");
+ return err;
+ }
+ mSensorPrivacyEnabled = spm.isIndividualSensorPrivacyEnabled(userId,
+ SensorPrivacyManager::INDIVIDUAL_SENSOR_MICROPHONE);
+
+ mIsIndividualMic = true;
+ mUserId = userId;
+ return OK;
+}
+
+bool SensorService::isMicSensorPrivacyEnabledForUid(uid_t uid) {
+ userid_t userId = multiuser_get_user_id(uid);
+ if (mMicSensorPrivacyPolicies.find(userId) == mMicSensorPrivacyPolicies.end()) {
+ sp<SensorPrivacyPolicy> userPolicy = new SensorPrivacyPolicy(this);
+ if (userPolicy->registerSelfForIndividual(userId) != OK) {
+ return false;
+ }
+ mMicSensorPrivacyPolicies[userId] = userPolicy;
+ }
+ return mMicSensorPrivacyPolicies[userId]->isSensorPrivacyEnabled();
+}
+
SensorService::ConnectionSafeAutolock::ConnectionSafeAutolock(
SensorService::SensorConnectionHolder& holder, Mutex& mutex)
: mConnectionHolder(holder), mAutolock(mutex) {}
@@ -2109,4 +2253,17 @@
return ConnectionSafeAutolock(*this, mutex);
}
+bool SensorService::isPackageDebuggable(const String16& opPackageName) {
+ bool debugMode = false;
+ sp<IBinder> binder = defaultServiceManager()->getService(String16("package_native"));
+ if (binder != nullptr) {
+ sp<content::pm::IPackageManagerNative> packageManager =
+ interface_cast<content::pm::IPackageManagerNative>(binder);
+ if (packageManager != nullptr) {
+ binder::Status status = packageManager->isPackageDebuggable(
+ opPackageName, &debugMode);
+ }
+ }
+ return debugMode;
+}
} // namespace android
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 50c7c2f..5b198d8 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -61,6 +61,15 @@
#define SENSOR_REGISTRATIONS_BUF_SIZE 200
+// Apps that targets S+ and do not have HIGH_SAMPLING_RATE_SENSORS permission will be capped
+// at 200 Hz. The cap also applies to all requests when the mic toggle is flipped to on, regardless
+// of their target SDKs and permission.
+// Capped sampling periods for apps that have non-direct sensor connections.
+#define SENSOR_SERVICE_CAPPED_SAMPLING_PERIOD_NS (5 * 1000 * 1000)
+// Capped sampling rate level for apps that have direct sensor connections.
+// The enum SENSOR_DIRECT_RATE_NORMAL corresponds to a rate value of at most 110 Hz.
+#define SENSOR_SERVICE_CAPPED_SAMPLING_RATE_LEVEL SENSOR_DIRECT_RATE_NORMAL
+
namespace android {
// ---------------------------------------------------------------------------
class SensorInterface;
@@ -95,6 +104,8 @@
status_t flushSensor(const sp<SensorEventConnection>& connection,
const String16& opPackageName);
+ // Returns true if a sensor should be throttled according to our rate-throttling rules.
+ static bool isSensorInCappedSet(int sensorType);
virtual status_t shellCommand(int in, int out, int err, Vector<String16>& args);
@@ -212,17 +223,23 @@
// connections will be allowed again.
class SensorPrivacyPolicy : public hardware::BnSensorPrivacyListener {
public:
- explicit SensorPrivacyPolicy(wp<SensorService> service) : mService(service) {}
+ explicit SensorPrivacyPolicy(wp<SensorService> service)
+ : mService(service), mIsIndividualMic(false), mUserId(0) {}
void registerSelf();
void unregisterSelf();
+ status_t registerSelfForIndividual(int userId);
+
bool isSensorPrivacyEnabled();
binder::Status onSensorPrivacyChanged(bool enabled);
private:
wp<SensorService> mService;
+ Mutex mSensorPrivacyLock;
std::atomic_bool mSensorPrivacyEnabled;
+ bool mIsIndividualMic;
+ userid_t mUserId;
};
enum Mode {
@@ -346,6 +363,13 @@
// whitelisted). mLock must be held to invoke this method.
bool isOperationRestrictedLocked(const String16& opPackageName);
+ status_t adjustSamplingPeriodBasedOnMicAndPermission(nsecs_t* requestedPeriodNs,
+ const String16& opPackageName);
+ status_t adjustRateLevelBasedOnMicAndPermission(int* requestedRateLevel,
+ const String16& opPackageName);
+ bool isRateCappedBasedOnPermission(const String16& opPackageName);
+ bool isPackageDebuggable(const String16& opPackageName);
+
// Reset the state of SensorService to NORMAL mode.
status_t resetToNormalMode();
status_t resetToNormalModeLocked();
@@ -385,6 +409,11 @@
void enableAllSensors();
void enableAllSensorsLocked(ConnectionSafeAutolock* connLock);
+ // Caps active direct connections (when the mic toggle is flipped to on)
+ void capRates(userid_t userId);
+ // Removes the capped rate on active direct connections (when the mic toggle is flipped to off)
+ void uncapRates(userid_t userId);
+
static uint8_t sHmacGlobalKey[128];
static bool sHmacGlobalKeyIsValid;
@@ -426,6 +455,11 @@
static std::map<String16, int> sPackageTargetVersion;
static Mutex sPackageTargetVersionLock;
static String16 sSensorInterfaceDescriptorPrefix;
+
+ // Map from user to SensorPrivacyPolicy
+ std::map<userid_t, sp<SensorPrivacyPolicy>> mMicSensorPrivacyPolicies;
+ // Checks if the mic sensor privacy is enabled for the uid
+ bool isMicSensorPrivacyEnabledForUid(uid_t uid);
};
} // namespace android
diff --git a/services/sensorservice/hidl/Android.bp b/services/sensorservice/hidl/Android.bp
index 0e1af59..9bafb3c 100644
--- a/services/sensorservice/hidl/Android.bp
+++ b/services/sensorservice/hidl/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libsensorservicehidl",
srcs: [
diff --git a/services/sensorservice/tests/Android.bp b/services/sensorservice/tests/Android.bp
index d33c0ca..ddc03a1 100644
--- a/services/sensorservice/tests/Android.bp
+++ b/services/sensorservice/tests/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_binary {
name: "test-sensorservice",
srcs: ["sensorservicetest.cpp"],
diff --git a/services/stats/Android.bp b/services/stats/Android.bp
index 1ce0524..58e5993 100644
--- a/services/stats/Android.bp
+++ b/services/stats/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libstatshidl",
srcs: [
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 8d1258a..c39c983 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "surfaceflinger_defaults",
cflags: [
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index ec81ff7..097f7de 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -366,8 +366,11 @@
mFrameTracker.setFrameReadyTime(desiredPresentTime);
}
+ const Fps refreshRate = mFlinger->mRefreshRateConfigs->getCurrentRefreshRate().getFps();
+ const std::optional<Fps> renderRate = mFlinger->mScheduler->getFrameRateOverride(getOwnerUid());
if (presentFence->isValid()) {
- mFlinger->mTimeStats->setPresentFence(layerId, mCurrentFrameNumber, presentFence);
+ mFlinger->mTimeStats->setPresentFence(layerId, mCurrentFrameNumber, presentFence,
+ refreshRate, renderRate);
mFlinger->mFrameTracer->traceFence(layerId, getCurrentBufferId(), mCurrentFrameNumber,
presentFence, FrameTracer::FrameEvent::PRESENT_FENCE);
mFrameTracker.setActualPresentFence(std::shared_ptr<FenceTime>(presentFence));
@@ -378,7 +381,8 @@
// The HWC doesn't support present fences, so use the refresh
// timestamp instead.
const nsecs_t actualPresentTime = display->getRefreshTimestamp();
- mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime);
+ mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime,
+ refreshRate, renderRate);
mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(), mCurrentFrameNumber,
actualPresentTime,
FrameTracer::FrameEvent::PRESENT_FENCE);
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 579130a..f30e1eb 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -236,10 +236,6 @@
bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) {
mCurrentStateModified = mCurrentState.modified;
bool stateUpdateAvailable = Layer::applyPendingStates(stateToCommit);
- if (stateUpdateAvailable && mCallbackHandleAcquireTime != -1) {
- // Update the acquire fence time if we have a buffer
- mSurfaceFrame->setAcquireFenceTime(mCallbackHandleAcquireTime);
- }
mCurrentStateModified = stateUpdateAvailable && mCurrentStateModified;
mCurrentState.modified = false;
return stateUpdateAvailable;
@@ -612,11 +608,12 @@
}
std::optional<nsecs_t> BufferStateLayer::nextPredictedPresentTime() const {
- if (!getDrawingState().isAutoTimestamp || !mSurfaceFrame) {
+ const State& drawingState(getDrawingState());
+ if (!drawingState.isAutoTimestamp || !drawingState.bufferSurfaceFrameTX) {
return std::nullopt;
}
- return mSurfaceFrame->getPredictions().presentTime;
+ return drawingState.bufferSurfaceFrameTX->getPredictions().presentTime;
}
status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime,
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index 57dc60b..50bc5ed 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "libcompositionengine_defaults",
defaults: ["surfaceflinger_defaults"],
diff --git a/services/surfaceflinger/Fps.h b/services/surfaceflinger/Fps.h
index 38a9af0..e9f06e5 100644
--- a/services/surfaceflinger/Fps.h
+++ b/services/surfaceflinger/Fps.h
@@ -27,7 +27,7 @@
// Value which represents "frames per second". This class is a wrapper around
// float, providing some useful utilities, such as comparisons with tolerance
-// and converting between period duruation and frequency.
+// and converting between period duration and frequency.
class Fps {
public:
static constexpr Fps fromPeriodNsecs(nsecs_t period) { return Fps(1e9f / period, period); }
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
index 3f833f4..0a40388 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.cpp
@@ -320,9 +320,19 @@
mLastLatchTime = lastLatchTime;
}
+void SurfaceFrame::setRenderRate(Fps renderRate) {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mRenderRate = renderRate;
+}
+
std::optional<int32_t> SurfaceFrame::getJankType() const {
std::scoped_lock lock(mMutex);
+ if (mPresentState == PresentState::Dropped) {
+ // Return no jank if it's a dropped frame since we cannot attribute a jank to a it.
+ return JankType::None;
+ }
if (mActuals.presentTime == 0) {
+ // Frame hasn't been presented yet.
return std::nullopt;
}
return mJankType;
@@ -367,6 +377,9 @@
StringAppendF(&result, "%s", indent.c_str());
StringAppendF(&result, "Owner Pid : %d\n", mOwnerPid);
StringAppendF(&result, "%s", indent.c_str());
+ StringAppendF(&result, "Scheduled rendering rate: %d fps\n",
+ mRenderRate ? mRenderRate->getIntValue() : 0);
+ StringAppendF(&result, "%s", indent.c_str());
StringAppendF(&result, "Present State : %s\n", toString(mPresentState).c_str());
StringAppendF(&result, "%s", indent.c_str());
StringAppendF(&result, "Prediction State : %s\n", toString(mPredictionState).c_str());
@@ -391,9 +404,10 @@
dumpTable(result, mPredictions, mActuals, indent, mPredictionState, baseTime);
}
-void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType,
- nsecs_t vsyncPeriod) {
+void SurfaceFrame::onPresent(nsecs_t presentTime, int32_t displayFrameJankType, Fps refreshRate,
+ nsecs_t displayDeadlineDelta, nsecs_t displayPresentDelta) {
std::scoped_lock lock(mMutex);
+
if (mPresentState != PresentState::Presented) {
// No need to update dropped buffers
return;
@@ -412,13 +426,16 @@
mJankType = JankType::Unknown;
mFramePresentMetadata = FramePresentMetadata::UnknownPresent;
mFrameReadyMetadata = FrameReadyMetadata::UnknownFinish;
- mTimeStats->incrementJankyFrames(mOwnerUid, mLayerName, mJankType);
+ const constexpr nsecs_t kAppDeadlineDelta = -1;
+ mTimeStats->incrementJankyFrames({refreshRate, mRenderRate, mOwnerUid, mLayerName,
+ mJankType, displayDeadlineDelta, displayPresentDelta,
+ kAppDeadlineDelta});
return;
}
const nsecs_t presentDelta = mActuals.presentTime - mPredictions.presentTime;
const nsecs_t deadlineDelta = mActuals.endTime - mPredictions.endTime;
- const nsecs_t deltaToVsync = std::abs(presentDelta) % vsyncPeriod;
+ const nsecs_t deltaToVsync = std::abs(presentDelta) % refreshRate.getPeriodNsecs();
if (deadlineDelta > mJankClassificationThresholds.deadlineThreshold) {
mFrameReadyMetadata = FrameReadyMetadata::LateFinish;
@@ -440,7 +457,8 @@
if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
// Finish on time, Present early
if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
- deltaToVsync >= vsyncPeriod - mJankClassificationThresholds.presentThreshold) {
+ deltaToVsync >= refreshRate.getPeriodNsecs() -
+ mJankClassificationThresholds.presentThreshold) {
// Delta factor of vsync
mJankType = JankType::SurfaceFlingerScheduling;
} else {
@@ -463,7 +481,8 @@
mJankType |= displayFrameJankType;
} else {
if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
- deltaToVsync >= vsyncPeriod - mJankClassificationThresholds.presentThreshold) {
+ deltaToVsync >= refreshRate.getPeriodNsecs() -
+ mJankClassificationThresholds.presentThreshold) {
// Delta factor of vsync
mJankType |= JankType::SurfaceFlingerScheduling;
} else {
@@ -482,7 +501,8 @@
}
}
}
- mTimeStats->incrementJankyFrames(mOwnerUid, mLayerName, mJankType);
+ mTimeStats->incrementJankyFrames({refreshRate, mRenderRate, mOwnerUid, mLayerName, mJankType,
+ displayDeadlineDelta, displayPresentDelta, deadlineDelta});
}
/**
@@ -684,10 +704,10 @@
mCurrentDisplayFrame->addSurfaceFrame(surfaceFrame);
}
-void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, nsecs_t vsyncPeriod) {
+void FrameTimeline::setSfWakeUp(int64_t token, nsecs_t wakeUpTime, Fps refreshRate) {
ATRACE_CALL();
std::scoped_lock lock(mMutex);
- mCurrentDisplayFrame->onSfWakeUp(token, vsyncPeriod,
+ mCurrentDisplayFrame->onSfWakeUp(token, refreshRate,
mTokenManager.getPredictionsForToken(token), wakeUpTime);
}
@@ -705,11 +725,11 @@
mSurfaceFrames.push_back(surfaceFrame);
}
-void FrameTimeline::DisplayFrame::onSfWakeUp(int64_t token, nsecs_t vsyncPeriod,
+void FrameTimeline::DisplayFrame::onSfWakeUp(int64_t token, Fps refreshRate,
std::optional<TimelineItem> predictions,
nsecs_t wakeUpTime) {
mToken = token;
- mVsyncPeriod = vsyncPeriod;
+ mRefreshRate = refreshRate;
if (!predictions) {
mPredictionState = PredictionState::Expired;
} else {
@@ -719,11 +739,6 @@
mSurfaceFlingerActuals.startTime = wakeUpTime;
}
-void FrameTimeline::DisplayFrame::setTokenAndVsyncPeriod(int64_t token, nsecs_t vsyncPeriod) {
- mToken = token;
- mVsyncPeriod = vsyncPeriod;
-}
-
void FrameTimeline::DisplayFrame::setPredictions(PredictionState predictionState,
TimelineItem predictions) {
mPredictionState = predictionState;
@@ -740,14 +755,16 @@
void FrameTimeline::DisplayFrame::onPresent(nsecs_t signalTime) {
mSurfaceFlingerActuals.presentTime = signalTime;
- int32_t totalJankReasons = JankType::None;
// Delta between the expected present and the actual present
const nsecs_t presentDelta =
mSurfaceFlingerActuals.presentTime - mSurfaceFlingerPredictions.presentTime;
+ const nsecs_t deadlineDelta =
+ mSurfaceFlingerActuals.endTime - mSurfaceFlingerPredictions.endTime;
+
// How far off was the presentDelta when compared to the vsyncPeriod. Used in checking if there
// was a prediction error or not.
- nsecs_t deltaToVsync = std::abs(presentDelta) % mVsyncPeriod;
+ nsecs_t deltaToVsync = std::abs(presentDelta) % mRefreshRate.getPeriodNsecs();
if (std::abs(presentDelta) > mJankClassificationThresholds.presentThreshold) {
mFramePresentMetadata = presentDelta > 0 ? FramePresentMetadata::LatePresent
: FramePresentMetadata::EarlyPresent;
@@ -776,8 +793,8 @@
if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
// Finish on time, Present early
if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
- deltaToVsync >=
- (mVsyncPeriod - mJankClassificationThresholds.presentThreshold)) {
+ deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
+ mJankClassificationThresholds.presentThreshold)) {
// Delta is a factor of vsync if its within the presentTheshold on either side
// of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
// of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
@@ -797,8 +814,8 @@
if (mFrameReadyMetadata == FrameReadyMetadata::OnTimeFinish) {
// Finish on time, Present late
if (deltaToVsync < mJankClassificationThresholds.presentThreshold ||
- deltaToVsync >=
- (mVsyncPeriod - mJankClassificationThresholds.presentThreshold)) {
+ deltaToVsync >= (mRefreshRate.getPeriodNsecs() -
+ mJankClassificationThresholds.presentThreshold)) {
// Delta is a factor of vsync if its within the presentTheshold on either side
// of the vsyncPeriod. Example: 0-2ms and 9-11ms are both within the threshold
// of the vsyncPeriod if the threshold was 2ms and the vsyncPeriod was 11ms.
@@ -819,16 +836,9 @@
mJankType = JankType::Unknown;
}
}
- totalJankReasons |= mJankType;
-
for (auto& surfaceFrame : mSurfaceFrames) {
- surfaceFrame->onPresent(signalTime, mJankType, mVsyncPeriod);
- auto surfaceFrameJankType = surfaceFrame->getJankType();
- if (surfaceFrameJankType != std::nullopt) {
- totalJankReasons |= *surfaceFrameJankType;
- }
+ surfaceFrame->onPresent(signalTime, mJankType, mRefreshRate, deadlineDelta, deltaToVsync);
}
- mTimeStats->incrementJankyFrames(totalJankReasons);
}
void FrameTimeline::DisplayFrame::trace(pid_t surfaceFlingerPid) const {
@@ -988,7 +998,7 @@
StringAppendF(&result, "Present Metadata : %s\n", toString(mFramePresentMetadata).c_str());
StringAppendF(&result, "Finish Metadata: %s\n", toString(mFrameReadyMetadata).c_str());
StringAppendF(&result, "Start Metadata: %s\n", toString(mFrameStartMetadata).c_str());
- std::chrono::nanoseconds vsyncPeriod(mVsyncPeriod);
+ std::chrono::nanoseconds vsyncPeriod(mRefreshRate.getPeriodNsecs());
StringAppendF(&result, "Vsync Period: %10f\n",
std::chrono::duration<double, std::milli>(vsyncPeriod).count());
nsecs_t presentDelta =
@@ -996,7 +1006,7 @@
std::chrono::nanoseconds presentDeltaNs(std::abs(presentDelta));
StringAppendF(&result, "Present delta: %10f\n",
std::chrono::duration<double, std::milli>(presentDeltaNs).count());
- std::chrono::nanoseconds deltaToVsync(std::abs(presentDelta) % mVsyncPeriod);
+ std::chrono::nanoseconds deltaToVsync(std::abs(presentDelta) % mRefreshRate.getPeriodNsecs());
StringAppendF(&result, "Present delta %% refreshrate: %10f\n",
std::chrono::duration<double, std::milli>(deltaToVsync).count());
dumpTable(result, mSurfaceFlingerPredictions, mSurfaceFlingerActuals, "", mPredictionState,
diff --git a/services/surfaceflinger/FrameTimeline/FrameTimeline.h b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
index 54e8efb..4739106 100644
--- a/services/surfaceflinger/FrameTimeline/FrameTimeline.h
+++ b/services/surfaceflinger/FrameTimeline/FrameTimeline.h
@@ -16,6 +16,7 @@
#pragma once
+#include <../Fps.h>
#include <../TimeStats/TimeStats.h>
#include <gui/ISurfaceComposer.h>
#include <gui/JankInfo.h>
@@ -175,13 +176,17 @@
void setActualQueueTime(nsecs_t actualQueueTime);
void setAcquireFenceTime(nsecs_t acquireFenceTime);
void setPresentState(PresentState presentState, nsecs_t lastLatchTime = 0);
+ void setRenderRate(Fps renderRate);
// Functions called by FrameTimeline
// BaseTime is the smallest timestamp in this SurfaceFrame.
// Used for dumping all timestamps relative to the oldest, making it easy to read.
nsecs_t getBaseTime() const;
// Sets the actual present time, appropriate metadata and classifies the jank.
- void onPresent(nsecs_t presentTime, int32_t displayFrameJankType, nsecs_t vsyncPeriod);
+ // displayRefreshRate, displayDeadlineDelta, and displayPresentDelta are propagated from the
+ // display frame.
+ void onPresent(nsecs_t presentTime, int32_t displayFrameJankType, Fps refreshRate,
+ nsecs_t displayDeadlineDelta, nsecs_t displayPresentDelta);
// All the timestamps are dumped relative to the baseTime
void dump(std::string& result, const std::string& indent, nsecs_t baseTime) const;
// Emits a packet for perfetto tracing. The function body will be executed only if tracing is
@@ -216,6 +221,8 @@
int32_t mJankType GUARDED_BY(mMutex) = JankType::None;
// Indicates if this frame was composited by the GPU or not
bool mGpuComposition GUARDED_BY(mMutex) = false;
+ // Rendering rate for this frame.
+ std::optional<Fps> mRenderRate GUARDED_BY(mMutex);
// Enum for the type of present
FramePresentMetadata mFramePresentMetadata GUARDED_BY(mMutex) =
FramePresentMetadata::UnknownPresent;
@@ -255,7 +262,7 @@
// The first function called by SF for the current DisplayFrame. Fetches SF predictions based on
// the token and sets the actualSfWakeTime for the current DisplayFrame.
- virtual void setSfWakeUp(int64_t token, nsecs_t wakeupTime, nsecs_t vsyncPeriod) = 0;
+ virtual void setSfWakeUp(int64_t token, nsecs_t wakeupTime, Fps refreshRate) = 0;
// Sets the sfPresentTime and finalizes the current DisplayFrame. Tracks the given present fence
// until it's signaled, and updates the present timestamps of all presented SurfaceFrames in
@@ -325,14 +332,13 @@
// is enabled.
void trace(pid_t surfaceFlingerPid) const;
// Sets the token, vsyncPeriod, predictions and SF start time.
- void onSfWakeUp(int64_t token, nsecs_t vsyncPeriod, std::optional<TimelineItem> predictions,
+ void onSfWakeUp(int64_t token, Fps refreshRate, std::optional<TimelineItem> predictions,
nsecs_t wakeUpTime);
// Sets the appropriate metadata, classifies the jank and returns the classified jankType.
void onPresent(nsecs_t signalTime);
// Adds the provided SurfaceFrame to the current display frame.
void addSurfaceFrame(std::shared_ptr<SurfaceFrame> surfaceFrame);
- void setTokenAndVsyncPeriod(int64_t token, nsecs_t vsyncPeriod);
void setPredictions(PredictionState predictionState, TimelineItem predictions);
void setActualStartTime(nsecs_t actualStartTime);
void setActualEndTime(nsecs_t actualEndTime);
@@ -382,7 +388,7 @@
FrameStartMetadata mFrameStartMetadata = FrameStartMetadata::UnknownStart;
// The refresh rate (vsync period) in nanoseconds as seen by SF during this DisplayFrame's
// timeline
- nsecs_t mVsyncPeriod = 0;
+ Fps mRefreshRate;
// TraceCookieCounter is used to obtain the cookie for sendig trace packets to perfetto.
// Using a reference here because the counter is owned by FrameTimeline, which outlives
// DisplayFrame.
@@ -398,7 +404,7 @@
const FrameTimelineInfo& frameTimelineInfo, pid_t ownerPid, uid_t ownerUid,
std::string layerName, std::string debugName) override;
void addSurfaceFrame(std::shared_ptr<frametimeline::SurfaceFrame> surfaceFrame) override;
- void setSfWakeUp(int64_t token, nsecs_t wakeupTime, nsecs_t vsyncPeriod) override;
+ void setSfWakeUp(int64_t token, nsecs_t wakeupTime, Fps refreshRate) override;
void setSfPresent(nsecs_t sfPresentTime,
const std::shared_ptr<FenceTime>& presentFence) override;
void parseArgs(const Vector<String16>& args, std::string& result) override;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 27b2b87..237aaff 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1581,6 +1581,10 @@
// For Transactions, the post time is considered to be both queue and acquire fence time.
surfaceFrame->setActualQueueTime(postTime);
surfaceFrame->setAcquireFenceTime(postTime);
+ const auto fps = mFlinger->mScheduler->getFrameRateOverride(getOwnerUid());
+ if (fps) {
+ surfaceFrame->setRenderRate(*fps);
+ }
onSurfaceFrameCreated(surfaceFrame);
return surfaceFrame;
}
@@ -1592,6 +1596,10 @@
debugName);
// For buffers, acquire fence time will set during latch.
surfaceFrame->setActualQueueTime(queueTime);
+ const auto fps = mFlinger->mScheduler->getFrameRateOverride(getOwnerUid());
+ if (fps) {
+ surfaceFrame->setRenderRate(*fps);
+ }
// TODO(b/178542907): Implement onSurfaceFrameCreated for BQLayer as well.
onSurfaceFrameCreated(surfaceFrame);
return surfaceFrame;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index a1fdc3c..687f473 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -1145,9 +1145,6 @@
// Window types from WindowManager.LayoutParams
const InputWindowInfo::Type mWindowType;
- // Can only be accessed with the SF state lock held.
- std::shared_ptr<frametimeline::SurfaceFrame> mSurfaceFrame;
-
// The owner of the layer. If created from a non system process, it will be the calling uid.
// If created from a system process, the value can be passed in.
uid_t mOwnerUid;
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index 49ffc81..b29c624 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -125,6 +125,9 @@
GRALLOC_USAGE_SW_WRITE_RARELY | GRALLOC_USAGE_HW_COMPOSER |
GRALLOC_USAGE_HW_TEXTURE,
"RefreshRateOverlayBuffer");
+ const status_t bufferStatus = buffer->initCheck();
+ LOG_ALWAYS_FATAL_IF(bufferStatus != OK, "RefreshRateOverlay: Buffer failed to allocate: %d",
+ bufferStatus);
uint8_t* pixels;
buffer->lock(GRALLOC_USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&pixels));
// Clear buffer content
diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp
index 9186538..09615f9 100644
--- a/services/surfaceflinger/RegionSamplingThread.cpp
+++ b/services/surfaceflinger/RegionSamplingThread.cpp
@@ -447,6 +447,9 @@
GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
buffer = new GraphicBuffer(sampledBounds.getWidth(), sampledBounds.getHeight(),
PIXEL_FORMAT_RGBA_8888, 1, usage, "RegionSamplingThread");
+ const status_t bufferStatus = buffer->initCheck();
+ LOG_ALWAYS_FATAL_IF(bufferStatus != OK, "captureSample: Buffer failed to allocate: %d",
+ bufferStatus);
}
const sp<SyncScreenCaptureListener> captureListener = new SyncScreenCaptureListener();
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index e7a44a7..a03f793 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -627,6 +627,8 @@
std::vector<const RefreshRate*> sortedModes;
getSortedRefreshRateListLocked([](const RefreshRate&) { return true; }, &sortedModes);
+ // Reset the policy because the old one may no longer be valid.
+ mDisplayManagerPolicy = {};
mDisplayManagerPolicy.defaultMode = currentModeId;
mMinSupportedRefreshRate = sortedModes.front();
mMaxSupportedRefreshRate = sortedModes.back();
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 5237516..0e9eba7 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -174,6 +174,8 @@
// Stores the preferred refresh rate that an app should run at.
// FrameRateOverride.refreshRateHz == 0 means no preference.
void setPreferredRefreshRateForUid(FrameRateOverride) EXCLUDES(mFrameRateOverridesMutex);
+ // Retrieves the overridden refresh rate for a given uid.
+ std::optional<Fps> getFrameRateOverride(uid_t uid) const EXCLUDES(mFrameRateOverridesMutex);
private:
friend class TestableScheduler;
@@ -236,7 +238,6 @@
Fps displayRefreshRate) REQUIRES(mFeatureStateLock)
EXCLUDES(mFrameRateOverridesMutex);
- std::optional<Fps> getFrameRateOverride(uid_t uid) const EXCLUDES(mFrameRateOverridesMutex);
impl::EventThread::ThrottleVsyncCallback makeThrottleVsyncCallback() const;
// Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection.
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a36502c..cb9fae3 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1899,7 +1899,7 @@
const bool tracePreComposition = mTracingEnabled && !mTracePostComposition;
ConditionalLockGuard<std::mutex> lock(mTracingLock, tracePreComposition);
- mFrameTimeline->setSfWakeUp(vsyncId, frameStart, stats.vsyncPeriod);
+ mFrameTimeline->setSfWakeUp(vsyncId, frameStart, Fps::fromPeriodNsecs(stats.vsyncPeriod));
refreshNeeded = handleMessageTransaction();
refreshNeeded |= handleMessageInvalidate();
@@ -5851,6 +5851,10 @@
getFactory().createGraphicBuffer(bufferSize.getWidth(), bufferSize.getHeight(),
static_cast<android_pixel_format>(reqPixelFormat),
1 /* layerCount */, usage, "screenshot");
+
+ const status_t bufferStatus = buffer->initCheck();
+ LOG_ALWAYS_FATAL_IF(bufferStatus != OK, "captureScreenCommon: Buffer failed to allocate: %d",
+ bufferStatus);
return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer,
false /* regionSampling */, grayscale, captureListener);
}
diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp
index 1d1f0c5..b4d8a9a 100644
--- a/services/surfaceflinger/SurfaceTracing.cpp
+++ b/services/surfaceflinger/SurfaceTracing.cpp
@@ -71,12 +71,14 @@
}
void SurfaceTracing::notify(const char* where) {
+ std::scoped_lock lock(mTraceLock);
if (mEnabled) {
runner->notify(where);
}
}
void SurfaceTracing::notifyLocked(const char* where) {
+ std::scoped_lock lock(mTraceLock);
if (mEnabled) {
runner->notifyLocked(where);
}
diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h
index 497ebd3..15a503d 100644
--- a/services/surfaceflinger/SurfaceTracing.h
+++ b/services/surfaceflinger/SurfaceTracing.h
@@ -81,8 +81,8 @@
SurfaceFlinger& mFlinger;
mutable std::mutex mTraceLock;
- bool mEnabled = false;
- std::unique_ptr<Runner> runner;
+ bool mEnabled GUARDED_BY(mTraceLock) = false;
+ std::unique_ptr<Runner> runner GUARDED_BY(mTraceLock);
struct Config {
uint32_t flags = TRACE_CRITICAL | TRACE_INPUT | TRACE_SYNC;
diff --git a/services/surfaceflinger/TimeStats/Android.bp b/services/surfaceflinger/TimeStats/Android.bp
index 0a23da2..62fddb4 100644
--- a/services/surfaceflinger/TimeStats/Android.bp
+++ b/services/surfaceflinger/TimeStats/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library {
name: "libtimestats",
srcs: [
diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp
index 5d387d6..b93f30e 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.cpp
+++ b/services/surfaceflinger/TimeStats/TimeStats.cpp
@@ -105,53 +105,63 @@
AStatsManager_PullAtomCallbackReturn TimeStats::populateGlobalAtom(AStatsEventList* data) {
std::lock_guard<std::mutex> lock(mMutex);
- if (mTimeStats.statsStart == 0) {
+ if (mTimeStats.statsStartLegacy == 0) {
return AStatsManager_PULL_SKIP;
}
flushPowerTimeLocked();
- AStatsEvent* event = mStatsDelegate->addStatsEventToPullData(data);
- mStatsDelegate->statsEventSetAtomId(event, android::util::SURFACEFLINGER_STATS_GLOBAL_INFO);
- mStatsDelegate->statsEventWriteInt64(event, mTimeStats.totalFrames);
- mStatsDelegate->statsEventWriteInt64(event, mTimeStats.missedFrames);
- mStatsDelegate->statsEventWriteInt64(event, mTimeStats.clientCompositionFrames);
- mStatsDelegate->statsEventWriteInt64(event, mTimeStats.displayOnTime);
- mStatsDelegate->statsEventWriteInt64(event, mTimeStats.presentToPresent.totalTime());
- mStatsDelegate->statsEventWriteInt32(event, mTimeStats.displayEventConnectionsCount);
- std::string frameDurationBytes =
- histogramToProtoByteString(mTimeStats.frameDuration.hist, mMaxPulledHistogramBuckets);
- mStatsDelegate->statsEventWriteByteArray(event, (const uint8_t*)frameDurationBytes.c_str(),
- frameDurationBytes.size());
- std::string renderEngineTimingBytes =
- histogramToProtoByteString(mTimeStats.renderEngineTiming.hist,
- mMaxPulledHistogramBuckets);
- mStatsDelegate->statsEventWriteByteArray(event, (const uint8_t*)renderEngineTimingBytes.c_str(),
- renderEngineTimingBytes.size());
+ for (const auto& globalSlice : mTimeStats.stats) {
+ AStatsEvent* event = mStatsDelegate->addStatsEventToPullData(data);
+ mStatsDelegate->statsEventSetAtomId(event, android::util::SURFACEFLINGER_STATS_GLOBAL_INFO);
+ mStatsDelegate->statsEventWriteInt64(event, mTimeStats.totalFramesLegacy);
+ mStatsDelegate->statsEventWriteInt64(event, mTimeStats.missedFramesLegacy);
+ mStatsDelegate->statsEventWriteInt64(event, mTimeStats.clientCompositionFramesLegacy);
+ mStatsDelegate->statsEventWriteInt64(event, mTimeStats.displayOnTimeLegacy);
+ mStatsDelegate->statsEventWriteInt64(event, mTimeStats.presentToPresentLegacy.totalTime());
+ mStatsDelegate->statsEventWriteInt32(event, mTimeStats.displayEventConnectionsCountLegacy);
+ std::string frameDurationBytes =
+ histogramToProtoByteString(mTimeStats.frameDurationLegacy.hist,
+ mMaxPulledHistogramBuckets);
+ mStatsDelegate->statsEventWriteByteArray(event, (const uint8_t*)frameDurationBytes.c_str(),
+ frameDurationBytes.size());
+ std::string renderEngineTimingBytes =
+ histogramToProtoByteString(mTimeStats.renderEngineTimingLegacy.hist,
+ mMaxPulledHistogramBuckets);
+ mStatsDelegate->statsEventWriteByteArray(event,
+ (const uint8_t*)renderEngineTimingBytes.c_str(),
+ renderEngineTimingBytes.size());
- mStatsDelegate->statsEventWriteInt32(event, mTimeStats.jankPayload.totalFrames);
- mStatsDelegate->statsEventWriteInt32(event, mTimeStats.jankPayload.totalJankyFrames);
- mStatsDelegate->statsEventWriteInt32(event, mTimeStats.jankPayload.totalSFLongCpu);
- mStatsDelegate->statsEventWriteInt32(event, mTimeStats.jankPayload.totalSFLongGpu);
- mStatsDelegate->statsEventWriteInt32(event, mTimeStats.jankPayload.totalSFUnattributed);
- mStatsDelegate->statsEventWriteInt32(event, mTimeStats.jankPayload.totalAppUnattributed);
+ mStatsDelegate->statsEventWriteInt32(event, globalSlice.second.jankPayload.totalFrames);
+ mStatsDelegate->statsEventWriteInt32(event,
+ globalSlice.second.jankPayload.totalJankyFrames);
+ mStatsDelegate->statsEventWriteInt32(event, globalSlice.second.jankPayload.totalSFLongCpu);
+ mStatsDelegate->statsEventWriteInt32(event, globalSlice.second.jankPayload.totalSFLongGpu);
+ mStatsDelegate->statsEventWriteInt32(event,
+ globalSlice.second.jankPayload.totalSFUnattributed);
+ mStatsDelegate->statsEventWriteInt32(event,
+ globalSlice.second.jankPayload.totalAppUnattributed);
- // TODO: populate these with real values
- mStatsDelegate->statsEventWriteInt32(event, 0); // total_janky_frames_sf_scheduling
- mStatsDelegate->statsEventWriteInt32(event, 0); // total_jank_frames_sf_prediction_error
- mStatsDelegate->statsEventWriteInt32(event, 0); // total_jank_frames_app_buffer_stuffing
- mStatsDelegate->statsEventWriteInt32(event, 0); // display_refresh_rate_bucket
- std::string sfDeadlineMissedBytes =
- histogramToProtoByteString(std::unordered_map<int32_t, int32_t>(),
- mMaxPulledHistogramBuckets);
- mStatsDelegate->statsEventWriteByteArray(event, (const uint8_t*)sfDeadlineMissedBytes.c_str(),
- sfDeadlineMissedBytes.size()); // sf_deadline_misses
- std::string sfPredictionErrorBytes =
- histogramToProtoByteString(std::unordered_map<int32_t, int32_t>(),
- mMaxPulledHistogramBuckets);
- mStatsDelegate->statsEventWriteByteArray(event, (const uint8_t*)sfPredictionErrorBytes.c_str(),
- sfPredictionErrorBytes.size()); // sf_prediction_errors
- mStatsDelegate->statsEventWriteInt32(event, 0); // render_rate_bucket
- mStatsDelegate->statsEventBuild(event);
+ // TODO: populate these with real values
+ mStatsDelegate->statsEventWriteInt32(event, 0); // total_janky_frames_sf_scheduling
+ mStatsDelegate->statsEventWriteInt32(event, 0); // total_jank_frames_sf_prediction_error
+ mStatsDelegate->statsEventWriteInt32(event, 0); // total_jank_frames_app_buffer_stuffing
+ mStatsDelegate->statsEventWriteInt32(event, globalSlice.first.displayRefreshRateBucket);
+ std::string sfDeadlineMissedBytes =
+ histogramToProtoByteString(globalSlice.second.displayDeadlineDeltas.hist,
+ mMaxPulledHistogramBuckets);
+ mStatsDelegate->statsEventWriteByteArray(event,
+ (const uint8_t*)sfDeadlineMissedBytes.c_str(),
+ sfDeadlineMissedBytes.size());
+ std::string sfPredictionErrorBytes =
+ histogramToProtoByteString(globalSlice.second.displayPresentDeltas.hist,
+ mMaxPulledHistogramBuckets);
+ mStatsDelegate->statsEventWriteByteArray(event,
+ (const uint8_t*)sfPredictionErrorBytes.c_str(),
+ sfPredictionErrorBytes.size());
+ mStatsDelegate->statsEventWriteInt32(event, globalSlice.first.renderRateBucket);
+ mStatsDelegate->statsEventBuild(event);
+ }
+
clearGlobalLocked();
return AStatsManager_PULL_SUCCESS;
@@ -160,9 +170,18 @@
AStatsManager_PullAtomCallbackReturn TimeStats::populateLayerAtom(AStatsEventList* data) {
std::lock_guard<std::mutex> lock(mMutex);
- std::vector<TimeStatsHelper::TimeStatsLayer const*> dumpStats;
- for (const auto& ele : mTimeStats.stats) {
- dumpStats.push_back(&ele.second);
+ std::vector<TimeStatsHelper::TimeStatsLayer*> dumpStats;
+ uint32_t numLayers = 0;
+ for (const auto& globalSlice : mTimeStats.stats) {
+ numLayers += globalSlice.second.stats.size();
+ }
+
+ dumpStats.reserve(numLayers);
+
+ for (auto& globalSlice : mTimeStats.stats) {
+ for (auto& layerSlice : globalSlice.second.stats) {
+ dumpStats.push_back(&layerSlice.second);
+ }
}
std::sort(dumpStats.begin(), dumpStats.end(),
@@ -175,7 +194,7 @@
dumpStats.resize(mMaxPulledLayers);
}
- for (const auto& layer : dumpStats) {
+ for (auto& layer : dumpStats) {
AStatsEvent* event = mStatsDelegate->addStatsEventToPullData(data);
mStatsDelegate->statsEventSetAtomId(event, android::util::SURFACEFLINGER_STATS_LAYER_INFO);
mStatsDelegate->statsEventWriteString8(event, layer->layerName.c_str());
@@ -208,17 +227,18 @@
mStatsDelegate->statsEventWriteInt32(event, 0); // total_janky_frames_sf_scheduling
mStatsDelegate->statsEventWriteInt32(event, 0); // total_jank_frames_sf_prediction_error
mStatsDelegate->statsEventWriteInt32(event, 0); // total_jank_frames_app_buffer_stuffing
- mStatsDelegate->statsEventWriteInt32(event, 0); // display_refresh_rate_bucket
- mStatsDelegate->statsEventWriteInt32(event, 0); // render_rate_bucket
+ mStatsDelegate->statsEventWriteInt32(
+ event, layer->displayRefreshRateBucket); // display_refresh_rate_bucket
+ mStatsDelegate->statsEventWriteInt32(event, layer->renderRateBucket); // render_rate_bucket
std::string frameRateVoteBytes = frameRateVoteToProtoByteString(0.0, 0, 0);
mStatsDelegate->statsEventWriteByteArray(event, (const uint8_t*)frameRateVoteBytes.c_str(),
frameRateVoteBytes.size()); // set_frame_rate_vote
std::string appDeadlineMissedBytes =
- histogramToProtoByteString(std::unordered_map<int32_t, int32_t>(),
+ histogramToProtoByteString(layer->deltas["appDeadlineDeltas"].hist,
mMaxPulledHistogramBuckets);
- mStatsDelegate
- ->statsEventWriteByteArray(event, (const uint8_t*)appDeadlineMissedBytes.c_str(),
- appDeadlineMissedBytes.size()); // app_deadline_misses
+ mStatsDelegate->statsEventWriteByteArray(event,
+ (const uint8_t*)appDeadlineMissedBytes.c_str(),
+ appDeadlineMissedBytes.size());
mStatsDelegate->statsEventBuild(event);
}
@@ -310,7 +330,7 @@
ATRACE_CALL();
std::lock_guard<std::mutex> lock(mMutex);
- mTimeStats.totalFrames++;
+ mTimeStats.totalFramesLegacy++;
}
void TimeStats::incrementMissedFrames() {
@@ -319,7 +339,7 @@
ATRACE_CALL();
std::lock_guard<std::mutex> lock(mMutex);
- mTimeStats.missedFrames++;
+ mTimeStats.missedFramesLegacy++;
}
void TimeStats::incrementClientCompositionFrames() {
@@ -328,7 +348,7 @@
ATRACE_CALL();
std::lock_guard<std::mutex> lock(mMutex);
- mTimeStats.clientCompositionFrames++;
+ mTimeStats.clientCompositionFramesLegacy++;
}
void TimeStats::incrementClientCompositionReusedFrames() {
@@ -337,7 +357,7 @@
ATRACE_CALL();
std::lock_guard<std::mutex> lock(mMutex);
- mTimeStats.clientCompositionReusedFrames++;
+ mTimeStats.clientCompositionReusedFramesLegacy++;
}
void TimeStats::incrementRefreshRateSwitches() {
@@ -346,7 +366,7 @@
ATRACE_CALL();
std::lock_guard<std::mutex> lock(mMutex);
- mTimeStats.refreshRateSwitches++;
+ mTimeStats.refreshRateSwitchesLegacy++;
}
void TimeStats::incrementCompositionStrategyChanges() {
@@ -355,7 +375,7 @@
ATRACE_CALL();
std::lock_guard<std::mutex> lock(mMutex);
- mTimeStats.compositionStrategyChanges++;
+ mTimeStats.compositionStrategyChangesLegacy++;
}
void TimeStats::recordDisplayEventConnectionCount(int32_t count) {
@@ -364,8 +384,8 @@
ATRACE_CALL();
std::lock_guard<std::mutex> lock(mMutex);
- mTimeStats.displayEventConnectionsCount =
- std::max(mTimeStats.displayEventConnectionsCount, count);
+ mTimeStats.displayEventConnectionsCountLegacy =
+ std::max(mTimeStats.displayEventConnectionsCountLegacy, count);
}
static int32_t msBetween(nsecs_t start, nsecs_t end) {
@@ -381,7 +401,7 @@
std::lock_guard<std::mutex> lock(mMutex);
if (mPowerTime.powerMode == PowerMode::ON) {
- mTimeStats.frameDuration.insert(msBetween(startTime, endTime));
+ mTimeStats.frameDurationLegacy.insert(msBetween(startTime, endTime));
}
}
@@ -444,12 +464,22 @@
return true;
}
-void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerId) {
+static int32_t clampToSmallestBucket(Fps fps, size_t bucketWidth) {
+ return (fps.getIntValue() / bucketWidth) * bucketWidth;
+}
+
+void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerId, Fps displayRefreshRate,
+ std::optional<Fps> renderRate) {
ATRACE_CALL();
LayerRecord& layerRecord = mTimeStatsTracker[layerId];
TimeRecord& prevTimeRecord = layerRecord.prevTimeRecord;
std::deque<TimeRecord>& timeRecords = layerRecord.timeRecords;
+ const int32_t refreshRateBucket =
+ clampToSmallestBucket(displayRefreshRate, REFRESH_RATE_BUCKET_WIDTH);
+ const int32_t renderRateBucket =
+ clampToSmallestBucket(renderRate ? *renderRate : displayRefreshRate,
+ RENDER_RATE_BUCKET_WIDTH);
while (!timeRecords.empty()) {
if (!recordReadyLocked(layerId, &timeRecords[0])) break;
ALOGV("[%d]-[%" PRIu64 "]-presentFenceTime[%" PRId64 "]", layerId,
@@ -458,11 +488,21 @@
if (prevTimeRecord.ready) {
uid_t uid = layerRecord.uid;
const std::string& layerName = layerRecord.layerName;
- if (!mTimeStats.stats.count({uid, layerName})) {
- mTimeStats.stats[{uid, layerName}].uid = uid;
- mTimeStats.stats[{uid, layerName}].layerName = layerName;
+ TimeStatsHelper::TimelineStatsKey timelineKey = {refreshRateBucket, renderRateBucket};
+ if (!mTimeStats.stats.count(timelineKey)) {
+ mTimeStats.stats[timelineKey].key = timelineKey;
}
- TimeStatsHelper::TimeStatsLayer& timeStatsLayer = mTimeStats.stats[{uid, layerName}];
+
+ TimeStatsHelper::TimelineStats& displayStats = mTimeStats.stats[timelineKey];
+
+ TimeStatsHelper::LayerStatsKey layerKey = {uid, layerName};
+ if (!displayStats.stats.count(layerKey)) {
+ displayStats.stats[layerKey].displayRefreshRateBucket = refreshRateBucket;
+ displayStats.stats[layerKey].renderRateBucket = renderRateBucket;
+ displayStats.stats[layerKey].uid = uid;
+ displayStats.stats[layerKey].layerName = layerName;
+ }
+ TimeStatsHelper::TimeStatsLayer& timeStatsLayer = displayStats.stats[layerKey];
timeStatsLayer.totalFrames++;
timeStatsLayer.droppedFrames += layerRecord.droppedFrames;
timeStatsLayer.lateAcquireFrames += layerRecord.lateAcquireFrames;
@@ -524,8 +564,16 @@
}
bool TimeStats::canAddNewAggregatedStats(uid_t uid, const std::string& layerName) {
- return mTimeStats.stats.count({uid, layerName}) > 0 ||
- mTimeStats.stats.size() < MAX_NUM_LAYER_STATS;
+ uint32_t layerRecords = 0;
+ for (const auto& record : mTimeStats.stats) {
+ if (record.second.stats.count({uid, layerName}) > 0) {
+ return true;
+ }
+
+ layerRecords += record.second.stats.size();
+ }
+
+ return mTimeStats.stats.size() < MAX_NUM_LAYER_STATS;
}
void TimeStats::setPostTime(int32_t layerId, uint64_t frameNumber, const std::string& layerName,
@@ -676,7 +724,8 @@
}
}
-void TimeStats::setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime) {
+void TimeStats::setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime,
+ Fps displayRefreshRate, std::optional<Fps> renderRate) {
if (!mEnabled.load()) return;
ATRACE_CALL();
@@ -695,11 +744,12 @@
layerRecord.waitData++;
}
- flushAvailableRecordsToStatsLocked(layerId);
+ flushAvailableRecordsToStatsLocked(layerId, displayRefreshRate, renderRate);
}
void TimeStats::setPresentFence(int32_t layerId, uint64_t frameNumber,
- const std::shared_ptr<FenceTime>& presentFence) {
+ const std::shared_ptr<FenceTime>& presentFence,
+ Fps displayRefreshRate, std::optional<Fps> renderRate) {
if (!mEnabled.load()) return;
ATRACE_CALL();
@@ -719,16 +769,17 @@
layerRecord.waitData++;
}
- flushAvailableRecordsToStatsLocked(layerId);
+ flushAvailableRecordsToStatsLocked(layerId, displayRefreshRate, renderRate);
}
+static const constexpr int32_t kValidJankyReason = JankType::SurfaceFlingerCpuDeadlineMissed |
+ JankType::SurfaceFlingerGpuDeadlineMissed | JankType::AppDeadlineMissed |
+ JankType::DisplayHAL;
+
template <class T>
static void updateJankPayload(T& t, int32_t reasons) {
t.jankPayload.totalFrames++;
- static const constexpr int32_t kValidJankyReason = JankType::SurfaceFlingerCpuDeadlineMissed |
- JankType::SurfaceFlingerGpuDeadlineMissed | JankType::AppDeadlineMissed |
- JankType::DisplayHAL;
if (reasons & kValidJankyReason) {
t.jankPayload.totalJankyFrames++;
if ((reasons & JankType::SurfaceFlingerCpuDeadlineMissed) != 0) {
@@ -746,16 +797,7 @@
}
}
-void TimeStats::incrementJankyFrames(int32_t reasons) {
- if (!mEnabled.load()) return;
-
- ATRACE_CALL();
- std::lock_guard<std::mutex> lock(mMutex);
-
- updateJankPayload<TimeStatsHelper::TimeStatsGlobal>(mTimeStats, reasons);
-}
-
-void TimeStats::incrementJankyFrames(uid_t uid, const std::string& layerName, int32_t reasons) {
+void TimeStats::incrementJankyFrames(const JankyFramesInfo& info) {
if (!mEnabled.load()) return;
ATRACE_CALL();
@@ -772,17 +814,44 @@
// TimeStats will flush the first present fence for a layer *before* FrameTimeline does so that
// the first jank record is not dropped.
- bool useDefaultLayerKey = false;
static const std::string kDefaultLayerName = "none";
- if (!mTimeStats.stats.count({uid, layerName})) {
- mTimeStats.stats[{uid, kDefaultLayerName}].uid = uid;
- mTimeStats.stats[{uid, kDefaultLayerName}].layerName = kDefaultLayerName;
- useDefaultLayerKey = true;
+
+ const int32_t refreshRateBucket =
+ clampToSmallestBucket(info.refreshRate, REFRESH_RATE_BUCKET_WIDTH);
+ const int32_t renderRateBucket =
+ clampToSmallestBucket(info.renderRate ? *info.renderRate : info.refreshRate,
+ RENDER_RATE_BUCKET_WIDTH);
+ const TimeStatsHelper::TimelineStatsKey timelineKey = {refreshRateBucket, renderRateBucket};
+
+ if (!mTimeStats.stats.count(timelineKey)) {
+ mTimeStats.stats[timelineKey].key = timelineKey;
}
- TimeStatsHelper::TimeStatsLayer& timeStatsLayer =
- mTimeStats.stats[{uid, useDefaultLayerKey ? kDefaultLayerName : layerName}];
- updateJankPayload<TimeStatsHelper::TimeStatsLayer>(timeStatsLayer, reasons);
+ TimeStatsHelper::TimelineStats& timelineStats = mTimeStats.stats[timelineKey];
+
+ updateJankPayload<TimeStatsHelper::TimelineStats>(timelineStats, info.reasons);
+
+ TimeStatsHelper::LayerStatsKey layerKey = {info.uid, info.layerName};
+ if (!timelineStats.stats.count(layerKey)) {
+ layerKey = {info.uid, kDefaultLayerName};
+ timelineStats.stats[layerKey].displayRefreshRateBucket = refreshRateBucket;
+ timelineStats.stats[layerKey].renderRateBucket = renderRateBucket;
+ timelineStats.stats[layerKey].uid = info.uid;
+ timelineStats.stats[layerKey].layerName = kDefaultLayerName;
+ }
+
+ TimeStatsHelper::TimeStatsLayer& timeStatsLayer = timelineStats.stats[layerKey];
+ updateJankPayload<TimeStatsHelper::TimeStatsLayer>(timeStatsLayer, info.reasons);
+
+ if (info.reasons & kValidJankyReason) {
+ // TimeStats Histograms only retain positive values, so we don't need to check if these
+ // deadlines were really missed if we know that the frame had jank, since deadlines
+ // that were met will be dropped.
+ timelineStats.displayDeadlineDeltas.insert(static_cast<int32_t>(info.displayDeadlineDelta));
+ timelineStats.displayPresentDeltas.insert(static_cast<int32_t>(info.displayPresentJitter));
+ timeStatsLayer.deltas["appDeadlineDeltas"].insert(
+ static_cast<int32_t>(info.appDeadlineDelta));
+ }
}
void TimeStats::onDestroy(int32_t layerId) {
@@ -823,7 +892,7 @@
switch (mPowerTime.powerMode) {
case PowerMode::ON:
- mTimeStats.displayOnTime += elapsedTime;
+ mTimeStats.displayOnTimeLegacy += elapsedTime;
break;
case PowerMode::OFF:
case PowerMode::DOZE:
@@ -852,10 +921,10 @@
void TimeStats::recordRefreshRate(uint32_t fps, nsecs_t duration) {
std::lock_guard<std::mutex> lock(mMutex);
- if (mTimeStats.refreshRateStats.count(fps)) {
- mTimeStats.refreshRateStats[fps] += duration;
+ if (mTimeStats.refreshRateStatsLegacy.count(fps)) {
+ mTimeStats.refreshRateStatsLegacy[fps] += duration;
} else {
- mTimeStats.refreshRateStats.insert({fps, duration});
+ mTimeStats.refreshRateStatsLegacy.insert({fps, duration});
}
}
@@ -881,7 +950,7 @@
msBetween(mGlobalRecord.prevPresentTime, curPresentTime);
ALOGV("Global present2present[%d] prev[%" PRId64 "] curr[%" PRId64 "]",
presentToPresentMs, mGlobalRecord.prevPresentTime, curPresentTime);
- mTimeStats.presentToPresent.insert(presentToPresentMs);
+ mTimeStats.presentToPresentLegacy.insert(presentToPresentMs);
}
mGlobalRecord.prevPresentTime = curPresentTime;
@@ -908,7 +977,7 @@
}
const int32_t renderEngineMs = msBetween(duration.startTime, endNs);
- mTimeStats.renderEngineTiming.insert(renderEngineMs);
+ mTimeStats.renderEngineTimingLegacy.insert(renderEngineMs);
mGlobalRecord.renderEngineDurations.pop_front();
}
@@ -951,7 +1020,7 @@
std::lock_guard<std::mutex> lock(mMutex);
mEnabled.store(true);
- mTimeStats.statsStart = static_cast<int64_t>(std::time(0));
+ mTimeStats.statsStartLegacy = static_cast<int64_t>(std::time(0));
mPowerTime.prevTime = systemTime();
ALOGD("Enabled");
}
@@ -964,7 +1033,7 @@
std::lock_guard<std::mutex> lock(mMutex);
flushPowerTimeLocked();
mEnabled.store(false);
- mTimeStats.statsEnd = static_cast<int64_t>(std::time(0));
+ mTimeStats.statsEndLegacy = static_cast<int64_t>(std::time(0));
ALOGD("Disabled");
}
@@ -977,21 +1046,20 @@
void TimeStats::clearGlobalLocked() {
ATRACE_CALL();
- mTimeStats.statsStart = (mEnabled.load() ? static_cast<int64_t>(std::time(0)) : 0);
- mTimeStats.statsEnd = 0;
- mTimeStats.totalFrames = 0;
- mTimeStats.missedFrames = 0;
- mTimeStats.clientCompositionFrames = 0;
- mTimeStats.clientCompositionReusedFrames = 0;
- mTimeStats.refreshRateSwitches = 0;
- mTimeStats.compositionStrategyChanges = 0;
- mTimeStats.displayEventConnectionsCount = 0;
- mTimeStats.displayOnTime = 0;
- mTimeStats.presentToPresent.hist.clear();
- mTimeStats.frameDuration.hist.clear();
- mTimeStats.renderEngineTiming.hist.clear();
- mTimeStats.jankPayload = TimeStatsHelper::JankPayload();
- mTimeStats.refreshRateStats.clear();
+ mTimeStats.statsStartLegacy = (mEnabled.load() ? static_cast<int64_t>(std::time(0)) : 0);
+ mTimeStats.statsEndLegacy = 0;
+ mTimeStats.totalFramesLegacy = 0;
+ mTimeStats.missedFramesLegacy = 0;
+ mTimeStats.clientCompositionFramesLegacy = 0;
+ mTimeStats.clientCompositionReusedFramesLegacy = 0;
+ mTimeStats.refreshRateSwitchesLegacy = 0;
+ mTimeStats.compositionStrategyChangesLegacy = 0;
+ mTimeStats.displayEventConnectionsCountLegacy = 0;
+ mTimeStats.displayOnTimeLegacy = 0;
+ mTimeStats.presentToPresentLegacy.hist.clear();
+ mTimeStats.frameDurationLegacy.hist.clear();
+ mTimeStats.renderEngineTimingLegacy.hist.clear();
+ mTimeStats.refreshRateStatsLegacy.clear();
mPowerTime.prevTime = systemTime();
mGlobalRecord.prevPresentTime = 0;
mGlobalRecord.presentFences.clear();
@@ -1014,11 +1082,11 @@
ATRACE_CALL();
std::lock_guard<std::mutex> lock(mMutex);
- if (mTimeStats.statsStart == 0) {
+ if (mTimeStats.statsStartLegacy == 0) {
return;
}
- mTimeStats.statsEnd = static_cast<int64_t>(std::time(0));
+ mTimeStats.statsEndLegacy = static_cast<int64_t>(std::time(0));
flushPowerTimeLocked();
diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h
index df40ef6..fd112b9 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.h
+++ b/services/surfaceflinger/TimeStats/TimeStats.h
@@ -27,12 +27,13 @@
// TODO(b/129481165): remove the #pragma below and fix conversion issues
#pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
+#include <../Fps.h>
+#include <gui/JankInfo.h>
#include <stats_event.h>
#include <stats_pull_atom_callback.h>
#include <statslog.h>
#include <timestatsproto/TimeStatsHelper.h>
#include <timestatsproto/TimeStatsProtoHeader.h>
-#include <gui/JankInfo.h>
#include <ui/FenceTime.h>
#include <utils/String16.h>
#include <utils/Vector.h>
@@ -108,23 +109,60 @@
const std::shared_ptr<FenceTime>& acquireFence) = 0;
// SetPresent{Time, Fence} are not expected to be called in the critical
// rendering path, as they flush prior fences if those fences have fired.
- virtual void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime) = 0;
+ virtual void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime,
+ Fps displayRefreshRate, std::optional<Fps> renderRate) = 0;
virtual void setPresentFence(int32_t layerId, uint64_t frameNumber,
- const std::shared_ptr<FenceTime>& presentFence) = 0;
+ const std::shared_ptr<FenceTime>& presentFence,
+ Fps displayRefreshRate, std::optional<Fps> renderRate) = 0;
- // Increments janky frames, tracked globally. Because FrameTimeline is the infrastructure
- // responsible for computing jank in the system, this is expected to be called from
- // FrameTimeline, rather than directly from SurfaceFlinger or individual layers. If there are no
- // jank reasons, then total frames are incremented but jank is not, for accurate accounting of
- // janky frames.
- virtual void incrementJankyFrames(int32_t reasons) = 0;
- // Increments janky frames, blamed to the provided {uid, layerName} key, with JankMetadata as
- // supplementary reasons for the jank. Because FrameTimeline is the infrastructure responsible
- // for computing jank in the system, this is expected to be called from FrameTimeline, rather
- // than directly from SurfaceFlinger or individual layers.
- // If there are no jank reasons, then total frames are incremented but jank is not, for accurate
+ // Increments janky frames, blamed to the provided {refreshRate, renderRate, uid, layerName}
+ // key, with JankMetadata as supplementary reasons for the jank. Because FrameTimeline is the
+ // infrastructure responsible for computing jank in the system, this is expected to be called
+ // from FrameTimeline, rather than directly from SurfaceFlinger or individual layers. If there
+ // are no jank reasons, then total frames are incremented but jank is not, for accurate
// accounting of janky frames.
- virtual void incrementJankyFrames(uid_t uid, const std::string& layerName, int32_t reasons) = 0;
+ // displayDeadlineDelta, displayPresentJitter, and appDeadlineDelta are also provided in order
+ // to provide contextual information about a janky frame. These values may only be uploaded if
+ // there was an associated valid jank reason, and they must be positive. When these frame counts
+ // are incremented, these are also aggregated into a global reporting packet to help with data
+ // validation and assessing of overall device health.
+ struct JankyFramesInfo {
+ Fps refreshRate;
+ std::optional<Fps> renderRate;
+ uid_t uid = 0;
+ std::string layerName;
+ int32_t reasons = 0;
+ nsecs_t displayDeadlineDelta = 0;
+ nsecs_t displayPresentJitter = 0;
+ nsecs_t appDeadlineDelta = 0;
+
+ bool operator==(const JankyFramesInfo& o) const {
+ return Fps::EqualsInBuckets{}(refreshRate, o.refreshRate) &&
+ ((renderRate == std::nullopt && o.renderRate == std::nullopt) ||
+ (renderRate != std::nullopt && o.renderRate != std::nullopt &&
+ Fps::EqualsInBuckets{}(*renderRate, *o.renderRate))) &&
+ uid == o.uid && layerName == o.layerName && reasons == o.reasons &&
+ displayDeadlineDelta == o.displayDeadlineDelta &&
+ displayPresentJitter == o.displayPresentJitter &&
+ appDeadlineDelta == o.appDeadlineDelta;
+ }
+
+ friend std::ostream& operator<<(std::ostream& os, const JankyFramesInfo& info) {
+ os << "JankyFramesInfo {";
+ os << "\n .refreshRate = " << info.refreshRate;
+ os << "\n .renderRate = "
+ << (info.renderRate ? to_string(*info.renderRate) : "nullopt");
+ os << "\n .uid = " << info.uid;
+ os << "\n .layerName = " << info.layerName;
+ os << "\n .reasons = " << info.reasons;
+ os << "\n .displayDeadlineDelta = " << info.displayDeadlineDelta;
+ os << "\n .displayPresentJitter = " << info.displayPresentJitter;
+ os << "\n .appDeadlineDelta = " << info.appDeadlineDelta;
+ return os << "\n}";
+ }
+ };
+
+ virtual void incrementJankyFrames(const JankyFramesInfo& info) = 0;
// Clean up the layer record
virtual void onDestroy(int32_t layerId) = 0;
// If SF skips or rejects a buffer, remove the corresponding TimeRecord.
@@ -268,11 +306,13 @@
void setAcquireTime(int32_t layerId, uint64_t frameNumber, nsecs_t acquireTime) override;
void setAcquireFence(int32_t layerId, uint64_t frameNumber,
const std::shared_ptr<FenceTime>& acquireFence) override;
- void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime) override;
+ void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime,
+ Fps displayRefreshRate, std::optional<Fps> renderRate) override;
void setPresentFence(int32_t layerId, uint64_t frameNumber,
- const std::shared_ptr<FenceTime>& presentFence) override;
- void incrementJankyFrames(int32_t reasons) override;
- void incrementJankyFrames(uid_t uid, const std::string& layerName, int32_t reasons) override;
+ const std::shared_ptr<FenceTime>& presentFence, Fps displayRefreshRate,
+ std::optional<Fps> renderRate) override;
+
+ void incrementJankyFrames(const JankyFramesInfo& info) override;
// Clean up the layer record
void onDestroy(int32_t layerId) override;
// If SF skips or rejects a buffer, remove the corresponding TimeRecord.
@@ -293,7 +333,8 @@
AStatsManager_PullAtomCallbackReturn populateGlobalAtom(AStatsEventList* data);
AStatsManager_PullAtomCallbackReturn populateLayerAtom(AStatsEventList* data);
bool recordReadyLocked(int32_t layerId, TimeRecord* timeRecord);
- void flushAvailableRecordsToStatsLocked(int32_t layerId);
+ void flushAvailableRecordsToStatsLocked(int32_t layerId, Fps displayRefreshRate,
+ std::optional<Fps> renderRate);
void flushPowerTimeLocked();
void flushAvailableGlobalRecordsToStatsLocked();
bool canAddNewAggregatedStats(uid_t uid, const std::string& layerName);
@@ -314,6 +355,9 @@
GlobalRecord mGlobalRecord;
static const size_t MAX_NUM_LAYER_RECORDS = 200;
+
+ static const size_t REFRESH_RATE_BUCKET_WIDTH = 30;
+ static const size_t RENDER_RATE_BUCKET_WIDTH = REFRESH_RATE_BUCKET_WIDTH;
static const size_t MAX_NUM_LAYER_STATS = 200;
static const size_t MAX_NUM_PULLED_LAYERS = MAX_NUM_LAYER_STATS;
std::unique_ptr<StatsEventDelegate> mStatsDelegate = std::make_unique<StatsEventDelegate>();
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/Android.bp b/services/surfaceflinger/TimeStats/timestatsproto/Android.bp
index 9481cac..972edaa 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/Android.bp
+++ b/services/surfaceflinger/TimeStats/timestatsproto/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library {
name: "libtimestats_proto",
export_include_dirs: ["include"],
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
index 0fb748f..814f046 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
+++ b/services/surfaceflinger/TimeStats/timestatsproto/TimeStatsHelper.cpp
@@ -41,7 +41,7 @@
if (delta < 0) return;
// std::lower_bound won't work on out of range values
if (delta > histogramConfig[HISTOGRAM_SIZE - 1]) {
- hist[histogramConfig[HISTOGRAM_SIZE - 1]] += delta / histogramConfig[HISTOGRAM_SIZE - 1];
+ hist[histogramConfig[HISTOGRAM_SIZE - 1]]++;
return;
}
auto iter = std::lower_bound(histogramConfig.begin(), histogramConfig.end(), delta);
@@ -90,6 +90,8 @@
std::string TimeStatsHelper::TimeStatsLayer::toString() const {
std::string result = "\n";
+ StringAppendF(&result, "displayRefreshRate = %d fps\n", displayRefreshRateBucket);
+ StringAppendF(&result, "renderRate = %d fps\n", renderRateBucket);
StringAppendF(&result, "uid = %d\n", uid);
StringAppendF(&result, "layerName = %s\n", layerName.c_str());
StringAppendF(&result, "packageName = %s\n", packageName.c_str());
@@ -115,35 +117,49 @@
std::string TimeStatsHelper::TimeStatsGlobal::toString(std::optional<uint32_t> maxLayers) const {
std::string result = "SurfaceFlinger TimeStats:\n";
- StringAppendF(&result, "statsStart = %" PRId64 "\n", statsStart);
- StringAppendF(&result, "statsEnd = %" PRId64 "\n", statsEnd);
- StringAppendF(&result, "totalFrames = %d\n", totalFrames);
- StringAppendF(&result, "missedFrames = %d\n", missedFrames);
- StringAppendF(&result, "clientCompositionFrames = %d\n", clientCompositionFrames);
- StringAppendF(&result, "clientCompositionReusedFrames = %d\n", clientCompositionReusedFrames);
- StringAppendF(&result, "refreshRateSwitches = %d\n", refreshRateSwitches);
- StringAppendF(&result, "compositionStrategyChanges = %d\n", compositionStrategyChanges);
- StringAppendF(&result, "displayOnTime = %" PRId64 " ms\n", displayOnTime);
- result.append("Global aggregated jank payload:\n");
- result.append(jankPayload.toString());
+ result.append("Legacy stats are as follows:\n");
+ StringAppendF(&result, "statsStart = %" PRId64 "\n", statsStartLegacy);
+ StringAppendF(&result, "statsEnd = %" PRId64 "\n", statsEndLegacy);
+ StringAppendF(&result, "totalFrames = %d\n", totalFramesLegacy);
+ StringAppendF(&result, "missedFrames = %d\n", missedFramesLegacy);
+ StringAppendF(&result, "clientCompositionFrames = %d\n", clientCompositionFramesLegacy);
+ StringAppendF(&result, "clientCompositionReusedFrames = %d\n",
+ clientCompositionReusedFramesLegacy);
+ StringAppendF(&result, "refreshRateSwitches = %d\n", refreshRateSwitchesLegacy);
+ StringAppendF(&result, "compositionStrategyChanges = %d\n", compositionStrategyChangesLegacy);
+ StringAppendF(&result, "displayOnTime = %" PRId64 " ms\n", displayOnTimeLegacy);
StringAppendF(&result, "displayConfigStats is as below:\n");
- for (const auto& [fps, duration] : refreshRateStats) {
+ for (const auto& [fps, duration] : refreshRateStatsLegacy) {
StringAppendF(&result, "%dfps = %ldms\n", fps, ns2ms(duration));
}
result.back() = '\n';
- StringAppendF(&result, "totalP2PTime = %" PRId64 " ms\n", presentToPresent.totalTime());
+ StringAppendF(&result, "totalP2PTime = %" PRId64 " ms\n", presentToPresentLegacy.totalTime());
StringAppendF(&result, "presentToPresent histogram is as below:\n");
- result.append(presentToPresent.toString());
- const float averageFrameDuration = frameDuration.averageTime();
+ result.append(presentToPresentLegacy.toString());
+ const float averageFrameDuration = frameDurationLegacy.averageTime();
StringAppendF(&result, "averageFrameDuration = %.3f ms\n",
std::isnan(averageFrameDuration) ? 0.0f : averageFrameDuration);
StringAppendF(&result, "frameDuration histogram is as below:\n");
- result.append(frameDuration.toString());
- const float averageRenderEngineTiming = renderEngineTiming.averageTime();
+ result.append(frameDurationLegacy.toString());
+ const float averageRenderEngineTiming = renderEngineTimingLegacy.averageTime();
StringAppendF(&result, "averageRenderEngineTiming = %.3f ms\n",
std::isnan(averageRenderEngineTiming) ? 0.0f : averageRenderEngineTiming);
StringAppendF(&result, "renderEngineTiming histogram is as below:\n");
- result.append(renderEngineTiming.toString());
+ result.append(renderEngineTimingLegacy.toString());
+
+ result.append("\nGlobal aggregated jank payload (Timeline stats):");
+ for (const auto& ele : stats) {
+ result.append("\n");
+ StringAppendF(&result, "displayRefreshRate = %d fps\n",
+ ele.second.key.displayRefreshRateBucket);
+ StringAppendF(&result, "renderRate = %d fps\n", ele.second.key.renderRateBucket);
+ result.append(ele.second.jankPayload.toString());
+ StringAppendF(&result, "sfDeadlineMisses histogram is as below:\n");
+ result.append(ele.second.displayDeadlineDeltas.toString());
+ StringAppendF(&result, "sfPredictionErrors histogram is as below:\n");
+ result.append(ele.second.displayPresentDeltas.toString());
+ }
+
const auto dumpStats = generateDumpStats(maxLayers);
for (const auto& ele : dumpStats) {
result.append(ele->toString());
@@ -173,30 +189,30 @@
SFTimeStatsGlobalProto TimeStatsHelper::TimeStatsGlobal::toProto(
std::optional<uint32_t> maxLayers) const {
SFTimeStatsGlobalProto globalProto;
- globalProto.set_stats_start(statsStart);
- globalProto.set_stats_end(statsEnd);
- globalProto.set_total_frames(totalFrames);
- globalProto.set_missed_frames(missedFrames);
- globalProto.set_client_composition_frames(clientCompositionFrames);
- globalProto.set_display_on_time(displayOnTime);
- for (const auto& ele : refreshRateStats) {
+ globalProto.set_stats_start(statsStartLegacy);
+ globalProto.set_stats_end(statsEndLegacy);
+ globalProto.set_total_frames(totalFramesLegacy);
+ globalProto.set_missed_frames(missedFramesLegacy);
+ globalProto.set_client_composition_frames(clientCompositionFramesLegacy);
+ globalProto.set_display_on_time(displayOnTimeLegacy);
+ for (const auto& ele : refreshRateStatsLegacy) {
SFTimeStatsDisplayConfigBucketProto* configBucketProto =
globalProto.add_display_config_stats();
SFTimeStatsDisplayConfigProto* configProto = configBucketProto->mutable_config();
configProto->set_fps(ele.first);
configBucketProto->set_duration_millis(ns2ms(ele.second));
}
- for (const auto& histEle : presentToPresent.hist) {
+ for (const auto& histEle : presentToPresentLegacy.hist) {
SFTimeStatsHistogramBucketProto* histProto = globalProto.add_present_to_present();
histProto->set_time_millis(histEle.first);
histProto->set_frame_count(histEle.second);
}
- for (const auto& histEle : frameDuration.hist) {
+ for (const auto& histEle : frameDurationLegacy.hist) {
SFTimeStatsHistogramBucketProto* histProto = globalProto.add_frame_duration();
histProto->set_time_millis(histEle.first);
histProto->set_frame_count(histEle.second);
}
- for (const auto& histEle : renderEngineTiming.hist) {
+ for (const auto& histEle : renderEngineTimingLegacy.hist) {
SFTimeStatsHistogramBucketProto* histProto = globalProto.add_render_engine_timing();
histProto->set_time_millis(histEle.first);
histProto->set_frame_count(histEle.second);
@@ -212,8 +228,18 @@
std::vector<TimeStatsHelper::TimeStatsLayer const*>
TimeStatsHelper::TimeStatsGlobal::generateDumpStats(std::optional<uint32_t> maxLayers) const {
std::vector<TimeStatsLayer const*> dumpStats;
+
+ int numLayers = 0;
for (const auto& ele : stats) {
- dumpStats.push_back(&ele.second);
+ numLayers += ele.second.stats.size();
+ }
+
+ dumpStats.reserve(numLayers);
+
+ for (const auto& ele : stats) {
+ for (const auto& layerEle : ele.second.stats) {
+ dumpStats.push_back(&layerEle.second);
+ }
}
std::sort(dumpStats.begin(), dumpStats.end(),
diff --git a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h
index 033eb5d..38ee888 100644
--- a/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h
+++ b/services/surfaceflinger/TimeStats/timestatsproto/include/timestatsproto/TimeStatsHelper.h
@@ -57,6 +57,8 @@
uid_t uid;
std::string layerName;
std::string packageName;
+ int32_t displayRefreshRateBucket = 0;
+ int32_t renderRateBucket = 0;
int32_t totalFrames = 0;
int32_t droppedFrames = 0;
int32_t lateAcquireFrames = 0;
@@ -68,32 +70,84 @@
SFTimeStatsLayerProto toProto() const;
};
- class TimeStatsGlobal {
- public:
- int64_t statsStart = 0;
- int64_t statsEnd = 0;
- int32_t totalFrames = 0;
- int32_t missedFrames = 0;
- int32_t clientCompositionFrames = 0;
- int32_t clientCompositionReusedFrames = 0;
- int32_t refreshRateSwitches = 0;
- int32_t compositionStrategyChanges = 0;
- int32_t displayEventConnectionsCount = 0;
- int64_t displayOnTime = 0;
- Histogram presentToPresent;
- Histogram frameDuration;
- Histogram renderEngineTiming;
+ // Lifted from SkiaGLRenderEngine's LinearEffect class.
+ // Which in turn was inspired by art/runtime/class_linker.cc
+ // Also this is what boost:hash_combine does so this is a pretty good hash.
+ static size_t HashCombine(size_t seed, size_t val) {
+ return seed ^ (val + 0x9e3779b9 + (seed << 6) + (seed >> 2));
+ }
- struct StatsHasher {
- size_t operator()(const std::pair<uid_t, std::string>& p) const {
- // Normally this isn't a very good hash function due to symmetry reasons,
- // but these are distinct types so this should be good enough
- return std::hash<uid_t>{}(p.first) ^ std::hash<std::string>{}(p.second);
+ struct TimelineStatsKey {
+ int32_t displayRefreshRateBucket = 0;
+ int32_t renderRateBucket = 0;
+
+ struct Hasher {
+ size_t operator()(const TimelineStatsKey& key) const {
+ size_t result = std::hash<int32_t>{}(key.displayRefreshRateBucket);
+ return HashCombine(result, std::hash<int32_t>{}(key.renderRateBucket));
}
};
- std::unordered_map<std::pair<uid_t, std::string>, TimeStatsLayer, StatsHasher> stats;
- std::unordered_map<uint32_t, nsecs_t> refreshRateStats;
+
+ bool operator==(const TimelineStatsKey& o) const {
+ return displayRefreshRateBucket == o.displayRefreshRateBucket &&
+ renderRateBucket == o.renderRateBucket;
+ }
+ };
+
+ struct LayerStatsKey {
+ uid_t uid = 0;
+ std::string layerName;
+
+ struct Hasher {
+ size_t operator()(const LayerStatsKey& key) const {
+ size_t result = std::hash<uid_t>{}(key.uid);
+ return HashCombine(result, std::hash<std::string>{}(key.layerName));
+ }
+ };
+
+ bool operator==(const LayerStatsKey& o) const {
+ return uid == o.uid && layerName == o.layerName;
+ }
+ };
+
+ struct LayerStatsHasher {
+ size_t operator()(const std::pair<uid_t, std::string>& p) const {
+ // Normally this isn't a very good hash function due to symmetry reasons,
+ // but these are distinct types so this should be good enough
+ return std::hash<uid_t>{}(p.first) ^ std::hash<std::string>{}(p.second);
+ }
+ };
+
+ struct TimelineStats {
+ TimelineStatsKey key;
JankPayload jankPayload;
+ Histogram displayDeadlineDeltas;
+ Histogram displayPresentDeltas;
+ std::unordered_map<LayerStatsKey, TimeStatsLayer, LayerStatsKey::Hasher> stats;
+ };
+
+ class TimeStatsGlobal {
+ public:
+ // Note: these are all legacy statistics, we're keeping these around because a variety of
+ // systems and form-factors find these useful when comparing with older releases. However,
+ // the current recommendation is that the new timeline-based metrics are used, and the old
+ // ones are deprecated.
+ int64_t statsStartLegacy = 0;
+ int64_t statsEndLegacy = 0;
+ int32_t totalFramesLegacy = 0;
+ int32_t missedFramesLegacy = 0;
+ int32_t clientCompositionFramesLegacy = 0;
+ int32_t clientCompositionReusedFramesLegacy = 0;
+ int32_t refreshRateSwitchesLegacy = 0;
+ int32_t compositionStrategyChangesLegacy = 0;
+ int32_t displayEventConnectionsCountLegacy = 0;
+ int64_t displayOnTimeLegacy = 0;
+ Histogram presentToPresentLegacy;
+ Histogram frameDurationLegacy;
+ Histogram renderEngineTimingLegacy;
+ std::unordered_map<uint32_t, nsecs_t> refreshRateStatsLegacy;
+
+ std::unordered_map<TimelineStatsKey, TimelineStats, TimelineStatsKey::Hasher> stats;
std::string toString(std::optional<uint32_t> maxLayers) const;
SFTimeStatsGlobalProto toProto(std::optional<uint32_t> maxLayers) const;
diff --git a/services/surfaceflinger/layerproto/Android.bp b/services/surfaceflinger/layerproto/Android.bp
index e2a28a2..c8a2b5e 100644
--- a/services/surfaceflinger/layerproto/Android.bp
+++ b/services/surfaceflinger/layerproto/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library {
name: "liblayers_proto",
export_include_dirs: ["include"],
diff --git a/services/surfaceflinger/sysprop/Android.bp b/services/surfaceflinger/sysprop/Android.bp
index 7721d7d2..f579119 100644
--- a/services/surfaceflinger/sysprop/Android.bp
+++ b/services/surfaceflinger/sysprop/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
sysprop_library {
name: "SurfaceFlingerProperties",
srcs: ["*.sysprop"],
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index 8142aad..78187f7 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "SurfaceFlinger_test",
defaults: ["surfaceflinger_defaults"],
diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp
index 3535fbb..2551a19 100644
--- a/services/surfaceflinger/tests/fakehwc/Android.bp
+++ b/services/surfaceflinger/tests/fakehwc/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "sffakehwc_test",
defaults: ["surfaceflinger_defaults"],
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index e55821f..2ac6b09 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "libsurfaceflinger_unittest",
defaults: ["surfaceflinger_defaults"],
diff --git a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
index 6e9f09b..b3ab8f1 100644
--- a/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
+++ b/services/surfaceflinger/tests/unittests/FrameTimelineTest.cpp
@@ -27,6 +27,7 @@
#include <cinttypes>
using namespace std::chrono_literals;
+using testing::_;
using testing::AtLeast;
using testing::Contains;
using FrameTimelineEvent = perfetto::protos::FrameTimelineEvent;
@@ -40,10 +41,6 @@
using ProtoPresentType = perfetto::protos::FrameTimelineEvent_PresentType;
using ProtoJankType = perfetto::protos::FrameTimelineEvent_JankType;
-MATCHER_P(HasBit, bit, "") {
- return (arg & bit) != 0;
-}
-
namespace android::frametimeline {
class FrameTimelineTest : public testing::Test {
@@ -238,7 +235,6 @@
TEST_F(FrameTimelineTest, presentFenceSignaled_droppedFramesNotUpdated) {
// Global increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_));
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
@@ -249,14 +245,14 @@
sLayerNameOne, sLayerNameOne);
// Set up the display frame
- mFrameTimeline->setSfWakeUp(token1, 20, 11);
+ mFrameTimeline->setSfWakeUp(token1, 20, Fps::fromPeriodNsecs(11));
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Dropped);
mFrameTimeline->addSurfaceFrame(surfaceFrame1);
mFrameTimeline->setSfPresent(25, presentFence1);
presentFence1->signalForTest(30);
// Trigger a flush by calling setSfPresent for the next frame
- mFrameTimeline->setSfWakeUp(token2, 50, 11);
+ mFrameTimeline->setSfWakeUp(token2, 50, Fps::fromPeriodNsecs(11));
mFrameTimeline->setSfPresent(55, presentFence2);
auto& droppedSurfaceFrame = getSurfaceFrame(0, 0);
@@ -265,10 +261,8 @@
}
TEST_F(FrameTimelineTest, presentFenceSignaled_presentedFramesUpdated) {
- // Global increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_));
// Layer specific increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_, testing::_, testing::_)).Times(2);
+ EXPECT_CALL(*mTimeStats, incrementJankyFrames(_)).Times(2);
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
@@ -280,7 +274,7 @@
auto surfaceFrame2 =
mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
sUidOne, sLayerNameTwo, sLayerNameTwo);
- mFrameTimeline->setSfWakeUp(sfToken1, 22, 11);
+ mFrameTimeline->setSfWakeUp(sfToken1, 22, Fps::fromPeriodNsecs(11));
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame1);
surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented);
@@ -301,7 +295,7 @@
auto surfaceFrame3 =
mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
sUidOne, sLayerNameOne, sLayerNameOne);
- mFrameTimeline->setSfWakeUp(sfToken2, 52, 11);
+ mFrameTimeline->setSfWakeUp(sfToken2, 52, Fps::fromPeriodNsecs(11));
surfaceFrame3->setPresentState(SurfaceFrame::PresentState::Dropped);
mFrameTimeline->addSurfaceFrame(surfaceFrame3);
mFrameTimeline->setSfPresent(56, presentFence2);
@@ -318,11 +312,8 @@
TEST_F(FrameTimelineTest, displayFramesSlidingWindowMovesAfterLimit) {
// Insert kMaxDisplayFrames' count of DisplayFrames to fill the deque
int frameTimeFactor = 0;
- // Global increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_))
- .Times(static_cast<int32_t>(*maxDisplayFrames));
// Layer specific increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_, testing::_, testing::_))
+ EXPECT_CALL(*mTimeStats, incrementJankyFrames(_))
.Times(static_cast<int32_t>(*maxDisplayFrames));
for (size_t i = 0; i < *maxDisplayFrames; i++) {
auto presentFence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
@@ -334,7 +325,7 @@
mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId},
sPidOne, sUidOne, sLayerNameOne,
sLayerNameOne);
- mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor, 11);
+ mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor, Fps::fromPeriodNsecs(11));
surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame);
mFrameTimeline->setSfPresent(27 + frameTimeFactor, presentFence);
@@ -355,7 +346,7 @@
auto surfaceFrame =
mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne,
sUidOne, sLayerNameOne, sLayerNameOne);
- mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor, 11);
+ mFrameTimeline->setSfWakeUp(sfToken, 22 + frameTimeFactor, Fps::fromPeriodNsecs(11));
surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame);
mFrameTimeline->setSfPresent(27 + frameTimeFactor, presentFence);
@@ -386,9 +377,6 @@
}
TEST_F(FrameTimelineTest, setMaxDisplayFramesSetsSizeProperly) {
- // Global increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_))
- .Times(static_cast<int32_t>(*maxDisplayFrames + 10));
auto presentFence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
presentFence->signalForTest(2);
@@ -398,7 +386,7 @@
mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne,
sLayerNameOne);
int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30});
- mFrameTimeline->setSfWakeUp(sfToken, 22, 11);
+ mFrameTimeline->setSfWakeUp(sfToken, 22, Fps::fromPeriodNsecs(11));
surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame);
mFrameTimeline->setSfPresent(27, presentFence);
@@ -408,16 +396,13 @@
// Increase the size to 256
mFrameTimeline->setMaxDisplayFrames(256);
EXPECT_EQ(*maxDisplayFrames, 256u);
- // Global increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_))
- .Times(static_cast<int32_t>(*maxDisplayFrames + 10));
for (size_t i = 0; i < *maxDisplayFrames + 10; i++) {
auto surfaceFrame =
mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne,
sLayerNameOne);
int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30});
- mFrameTimeline->setSfWakeUp(sfToken, 22, 11);
+ mFrameTimeline->setSfWakeUp(sfToken, 22, Fps::fromPeriodNsecs(11));
surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame);
mFrameTimeline->setSfPresent(27, presentFence);
@@ -427,16 +412,13 @@
// Shrink the size to 128
mFrameTimeline->setMaxDisplayFrames(128);
EXPECT_EQ(*maxDisplayFrames, 128u);
- // Global increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_))
- .Times(static_cast<int32_t>(*maxDisplayFrames + 10));
for (size_t i = 0; i < *maxDisplayFrames + 10; i++) {
auto surfaceFrame =
mFrameTimeline->createSurfaceFrameForToken({}, sPidOne, sUidOne, sLayerNameOne,
sLayerNameOne);
int64_t sfToken = mTokenManager->generateTokenForPredictions({22, 26, 30});
- mFrameTimeline->setSfWakeUp(sfToken, 22, 11);
+ mFrameTimeline->setSfWakeUp(sfToken, 22, Fps::fromPeriodNsecs(11));
surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame);
mFrameTimeline->setSfPresent(27, presentFence);
@@ -446,11 +428,19 @@
// Tests related to TimeStats
TEST_F(FrameTimelineTest, presentFenceSignaled_reportsLongSfCpu) {
+ Fps refreshRate = Fps(11);
EXPECT_CALL(*mTimeStats,
- incrementJankyFrames(sUidOne, sLayerNameOne,
- HasBit(JankType::SurfaceFlingerCpuDeadlineMissed)));
- EXPECT_CALL(*mTimeStats,
- incrementJankyFrames(HasBit(JankType::SurfaceFlingerCpuDeadlineMissed)));
+ incrementJankyFrames(
+ TimeStats::JankyFramesInfo{refreshRate, std::nullopt, sUidOne,
+ sLayerNameOne,
+ JankType::SurfaceFlingerCpuDeadlineMissed,
+ std::chrono::duration_cast<
+ std::chrono::nanoseconds>(3ms)
+ .count(),
+ std::chrono::duration_cast<
+ std::chrono::nanoseconds>(10ms)
+ .count(),
+ 0}));
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions(
{std::chrono::duration_cast<std::chrono::nanoseconds>(10ms).count(),
@@ -465,7 +455,9 @@
sUidOne, sLayerNameOne, sLayerNameOne);
mFrameTimeline->setSfWakeUp(sfToken1,
std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
- 11);
+ refreshRate);
+ surfaceFrame1->setAcquireFenceTime(
+ std::chrono::duration_cast<std::chrono::nanoseconds>(20ms).count());
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame1);
presentFence1->signalForTest(
@@ -476,9 +468,11 @@
}
TEST_F(FrameTimelineTest, presentFenceSignaled_reportsDisplayMiss) {
+ Fps refreshRate = Fps::fromPeriodNsecs(30);
EXPECT_CALL(*mTimeStats,
- incrementJankyFrames(sUidOne, sLayerNameOne, HasBit(JankType::DisplayHAL)));
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(HasBit(JankType::DisplayHAL)));
+ incrementJankyFrames(TimeStats::JankyFramesInfo{refreshRate, std::nullopt, sUidOne,
+ sLayerNameOne, JankType::DisplayHAL,
+ 0, 0, 0}));
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions(
@@ -494,8 +488,10 @@
sUidOne, sLayerNameOne, sLayerNameOne);
mFrameTimeline->setSfWakeUp(sfToken1,
std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
- 30);
+ refreshRate);
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
+ surfaceFrame1->setAcquireFenceTime(
+ std::chrono::duration_cast<std::chrono::nanoseconds>(20ms).count());
mFrameTimeline->addSurfaceFrame(surfaceFrame1);
presentFence1->signalForTest(
std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count());
@@ -505,10 +501,14 @@
}
TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMiss) {
+ Fps refreshRate = Fps(11.0);
EXPECT_CALL(*mTimeStats,
- incrementJankyFrames(sUidOne, sLayerNameOne,
- HasBit(JankType::AppDeadlineMissed)));
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(HasBit(JankType::AppDeadlineMissed)));
+ incrementJankyFrames(
+ TimeStats::JankyFramesInfo{refreshRate, std::nullopt, sUidOne,
+ sLayerNameOne, JankType::AppDeadlineMissed, 0, 0,
+ std::chrono::duration_cast<
+ std::chrono::nanoseconds>(25ms)
+ .count()}));
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions(
{std::chrono::duration_cast<std::chrono::nanoseconds>(10ms).count(),
@@ -525,7 +525,7 @@
std::chrono::duration_cast<std::chrono::nanoseconds>(45ms).count());
mFrameTimeline->setSfWakeUp(sfToken1,
std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
- 11);
+ refreshRate);
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame1);
@@ -537,6 +537,45 @@
EXPECT_EQ(surfaceFrame1->getJankType(), JankType::AppDeadlineMissed);
}
+TEST_F(FrameTimelineTest, presentFenceSignaled_reportsAppMissWithRenderRate) {
+ Fps refreshRate = Fps(11.0);
+ Fps renderRate = Fps(30.0);
+ EXPECT_CALL(*mTimeStats,
+ incrementJankyFrames(
+ TimeStats::JankyFramesInfo{refreshRate, renderRate, sUidOne, sLayerNameOne,
+ JankType::AppDeadlineMissed, 0, 0,
+ std::chrono::duration_cast<
+ std::chrono::nanoseconds>(25ms)
+ .count()}));
+ auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
+ int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions(
+ {std::chrono::duration_cast<std::chrono::nanoseconds>(10ms).count(),
+ std::chrono::duration_cast<std::chrono::nanoseconds>(20ms).count(),
+ std::chrono::duration_cast<std::chrono::nanoseconds>(60ms).count()});
+ int64_t sfToken1 = mTokenManager->generateTokenForPredictions(
+ {std::chrono::duration_cast<std::chrono::nanoseconds>(82ms).count(),
+ std::chrono::duration_cast<std::chrono::nanoseconds>(86ms).count(),
+ std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count()});
+ auto surfaceFrame1 =
+ mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
+ sUidOne, sLayerNameOne, sLayerNameOne);
+ surfaceFrame1->setAcquireFenceTime(
+ std::chrono::duration_cast<std::chrono::nanoseconds>(45ms).count());
+ mFrameTimeline->setSfWakeUp(sfToken1,
+ std::chrono::duration_cast<std::chrono::nanoseconds>(52ms).count(),
+ refreshRate);
+
+ surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
+ surfaceFrame1->setRenderRate(renderRate);
+ mFrameTimeline->addSurfaceFrame(surfaceFrame1);
+ presentFence1->signalForTest(
+ std::chrono::duration_cast<std::chrono::nanoseconds>(90ms).count());
+ mFrameTimeline->setSfPresent(std::chrono::duration_cast<std::chrono::nanoseconds>(86ms).count(),
+ presentFence1);
+
+ EXPECT_EQ(surfaceFrame1->getJankType(), JankType::AppDeadlineMissed);
+}
+
/*
* Tracing Tests
*
@@ -547,8 +586,6 @@
*/
TEST_F(FrameTimelineTest, tracing_noPacketsSentWithoutTraceStart) {
auto tracingSession = getTracingSessionForTest();
- // Global increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_));
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
@@ -559,7 +596,7 @@
sLayerNameOne, sLayerNameOne);
// Set up the display frame
- mFrameTimeline->setSfWakeUp(token1, 20, 11);
+ mFrameTimeline->setSfWakeUp(token1, 20, Fps::fromPeriodNsecs(11));
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Dropped);
mFrameTimeline->addSurfaceFrame(surfaceFrame1);
mFrameTimeline->setSfPresent(25, presentFence1);
@@ -567,7 +604,7 @@
// Trigger a flushPresentFence (which will call trace function) by calling setSfPresent for the
// next frame
- mFrameTimeline->setSfWakeUp(token2, 50, 11);
+ mFrameTimeline->setSfWakeUp(token2, 50, Fps::fromPeriodNsecs(11));
mFrameTimeline->setSfPresent(55, presentFence2);
auto packets = readFrameTimelinePacketsBlocking(tracingSession.get());
@@ -576,10 +613,8 @@
TEST_F(FrameTimelineTest, tracing_sanityTest) {
auto tracingSession = getTracingSessionForTest();
- // Global increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_));
// Layer specific increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_, testing::_, testing::_));
+ EXPECT_CALL(*mTimeStats, incrementJankyFrames(_));
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
@@ -591,7 +626,7 @@
sLayerNameOne, sLayerNameOne);
// Set up the display frame
- mFrameTimeline->setSfWakeUp(token2, 20, 11);
+ mFrameTimeline->setSfWakeUp(token2, 20, Fps::fromPeriodNsecs(11));
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame1);
mFrameTimeline->setSfPresent(25, presentFence1);
@@ -599,7 +634,7 @@
// Trigger a flushPresentFence (which will call trace function) by calling setSfPresent for the
// next frame
- mFrameTimeline->setSfWakeUp(token2, 50, 11);
+ mFrameTimeline->setSfWakeUp(token2, 50, Fps::fromPeriodNsecs(11));
mFrameTimeline->setSfPresent(55, presentFence2);
presentFence2->signalForTest(55);
@@ -613,8 +648,6 @@
TEST_F(FrameTimelineTest, traceDisplayFrame_invalidTokenDoesNotEmitTracePacket) {
auto tracingSession = getTracingSessionForTest();
- // Global increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_));
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
@@ -622,13 +655,13 @@
int64_t token1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
// Set up the display frame
- mFrameTimeline->setSfWakeUp(-1, 20, 11);
+ mFrameTimeline->setSfWakeUp(-1, 20, Fps::fromPeriodNsecs(11));
mFrameTimeline->setSfPresent(25, presentFence1);
presentFence1->signalForTest(30);
// Trigger a flushPresentFence (which will call trace function) by calling setSfPresent for the
// next frame
- mFrameTimeline->setSfWakeUp(token1, 50, 11);
+ mFrameTimeline->setSfWakeUp(token1, 50, Fps::fromPeriodNsecs(11));
mFrameTimeline->setSfPresent(55, presentFence2);
presentFence2->signalForTest(60);
@@ -641,8 +674,6 @@
TEST_F(FrameTimelineTest, traceSurfaceFrame_invalidTokenDoesNotEmitTracePacket) {
auto tracingSession = getTracingSessionForTest();
- // Global increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_));
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
@@ -653,7 +684,7 @@
sLayerNameOne, sLayerNameOne);
// Set up the display frame
- mFrameTimeline->setSfWakeUp(token1, 20, 11);
+ mFrameTimeline->setSfWakeUp(token1, 20, Fps::fromPeriodNsecs(11));
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Dropped);
mFrameTimeline->addSurfaceFrame(surfaceFrame1);
mFrameTimeline->setSfPresent(25, presentFence1);
@@ -661,7 +692,7 @@
// Trigger a flushPresentFence (which will call trace function) by calling setSfPresent for the
// next frame
- mFrameTimeline->setSfWakeUp(token2, 50, 11);
+ mFrameTimeline->setSfWakeUp(token2, 50, Fps::fromPeriodNsecs(11));
mFrameTimeline->setSfPresent(55, presentFence2);
presentFence2->signalForTest(60);
@@ -759,8 +790,6 @@
TEST_F(FrameTimelineTest, traceDisplayFrame_emitsValidTracePacket) {
auto tracingSession = getTracingSessionForTest();
- // Global increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_));
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
@@ -769,7 +798,7 @@
int64_t displayFrameToken2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
// Set up the display frame
- mFrameTimeline->setSfWakeUp(displayFrameToken1, 20, 11);
+ mFrameTimeline->setSfWakeUp(displayFrameToken1, 20, Fps::fromPeriodNsecs(11));
mFrameTimeline->setSfPresent(26, presentFence1);
presentFence1->signalForTest(31);
@@ -797,7 +826,7 @@
// Trigger a flushPresentFence (which will call trace function) by calling setSfPresent for the
// next frame
- mFrameTimeline->setSfWakeUp(displayFrameToken2, 50, 11);
+ mFrameTimeline->setSfWakeUp(displayFrameToken2, 50, Fps::fromPeriodNsecs(11));
mFrameTimeline->setSfPresent(55, presentFence2);
presentFence2->signalForTest(55);
@@ -854,10 +883,8 @@
TEST_F(FrameTimelineTest, traceSurfaceFrame_emitsValidTracePacket) {
auto tracingSession = getTracingSessionForTest();
- // Global increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_));
// Layer specific increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_, testing::_, testing::_));
+ EXPECT_CALL(*mTimeStats, incrementJankyFrames(_));
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
@@ -902,7 +929,7 @@
protoActualSurfaceFrameEnd.set_cookie(traceCookie + 2);
// Set up the display frame
- mFrameTimeline->setSfWakeUp(displayFrameToken1, 20, 11);
+ mFrameTimeline->setSfWakeUp(displayFrameToken1, 20, Fps::fromPeriodNsecs(11));
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame1);
mFrameTimeline->setSfPresent(26, presentFence1);
@@ -910,7 +937,7 @@
// Trigger a flushPresentFence (which will call trace function) by calling setSfPresent for the
// next frame
- mFrameTimeline->setSfWakeUp(displayFrameToken2, 50, 11);
+ mFrameTimeline->setSfWakeUp(displayFrameToken2, 50, Fps::fromPeriodNsecs(11));
mFrameTimeline->setSfPresent(55, presentFence2);
presentFence2->signalForTest(55);
@@ -967,17 +994,15 @@
// Tests for Jank classification
TEST_F(FrameTimelineTest, jankClassification_presentOnTimeDoesNotClassify) {
- // Global increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_));
// Layer specific increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_, testing::_, testing::_));
+ EXPECT_CALL(*mTimeStats, incrementJankyFrames(_));
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t surfaceFrameToken = mTokenManager->generateTokenForPredictions({10, 20, 30});
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 30});
auto surfaceFrame =
mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken, sInputEventId}, sPidOne,
sUidOne, sLayerNameOne, sLayerNameOne);
- mFrameTimeline->setSfWakeUp(sfToken1, 22, 11);
+ mFrameTimeline->setSfWakeUp(sfToken1, 22, Fps::fromPeriodNsecs(11));
surfaceFrame->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame);
mFrameTimeline->setSfPresent(26, presentFence1);
@@ -1001,12 +1026,11 @@
}
TEST_F(FrameTimelineTest, jankClassification_displayFrameOnTimeFinishEarlyPresent) {
- // Global increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_)).Times(2);
+ Fps vsyncRate = Fps::fromPeriodNsecs(11);
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 40});
int64_t sfToken2 = mTokenManager->generateTokenForPredictions({52, 56, 70});
- mFrameTimeline->setSfWakeUp(sfToken1, 22, 11);
+ mFrameTimeline->setSfWakeUp(sfToken1, 22, vsyncRate);
mFrameTimeline->setSfPresent(26, presentFence1);
auto displayFrame = getDisplayFrame(0);
presentFence1->signalForTest(30);
@@ -1016,7 +1040,7 @@
// Trigger a flush by finalizing the next DisplayFrame
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
- mFrameTimeline->setSfWakeUp(sfToken2, 52, 11);
+ mFrameTimeline->setSfWakeUp(sfToken2, 52, vsyncRate);
mFrameTimeline->setSfPresent(56, presentFence2);
displayFrame = getDisplayFrame(0);
@@ -1030,7 +1054,6 @@
auto displayFrame2 = getDisplayFrame(1);
presentFence2->signalForTest(65);
EXPECT_EQ(displayFrame2->getActuals().presentTime, 0);
-
addEmptyDisplayFrame();
displayFrame2 = getDisplayFrame(1);
@@ -1042,12 +1065,11 @@
}
TEST_F(FrameTimelineTest, jankClassification_displayFrameOnTimeFinishLatePresent) {
- // Global increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_)).Times(2);
+ Fps vsyncRate = Fps::fromPeriodNsecs(11);
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 40});
int64_t sfToken2 = mTokenManager->generateTokenForPredictions({52, 56, 70});
- mFrameTimeline->setSfWakeUp(sfToken1, 22, 11);
+ mFrameTimeline->setSfWakeUp(sfToken1, 22, vsyncRate);
mFrameTimeline->setSfPresent(26, presentFence1);
auto displayFrame = getDisplayFrame(0);
presentFence1->signalForTest(50);
@@ -1057,7 +1079,7 @@
// Trigger a flush by finalizing the next DisplayFrame
auto presentFence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
- mFrameTimeline->setSfWakeUp(sfToken2, 52, 11);
+ mFrameTimeline->setSfWakeUp(sfToken2, 52, vsyncRate);
mFrameTimeline->setSfPresent(56, presentFence2);
displayFrame = getDisplayFrame(0);
@@ -1083,11 +1105,9 @@
}
TEST_F(FrameTimelineTest, jankClassification_displayFrameLateFinishEarlyPresent) {
- // Global increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_));
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({12, 18, 40});
- mFrameTimeline->setSfWakeUp(sfToken1, 12, 11);
+ mFrameTimeline->setSfWakeUp(sfToken1, 12, Fps::fromPeriodNsecs(11));
mFrameTimeline->setSfPresent(22, presentFence1);
auto displayFrame = getDisplayFrame(0);
@@ -1107,11 +1127,9 @@
}
TEST_F(FrameTimelineTest, jankClassification_displayFrameLateFinishLatePresent) {
- // Global increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_));
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 40});
- mFrameTimeline->setSfWakeUp(sfToken1, 12, 11);
+ mFrameTimeline->setSfWakeUp(sfToken1, 12, Fps::fromPeriodNsecs(11));
mFrameTimeline->setSfPresent(36, presentFence1);
auto displayFrame = getDisplayFrame(0);
presentFence1->signalForTest(52);
@@ -1130,10 +1148,7 @@
}
TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishEarlyPresent) {
- // Global increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_)).Times(2);
- // Layer specific increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_, testing::_, testing::_)).Times(2);
+ EXPECT_CALL(*mTimeStats, incrementJankyFrames(_));
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 40});
int64_t sfToken2 = mTokenManager->generateTokenForPredictions({52, 56, 70});
@@ -1143,7 +1158,7 @@
mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame1->setAcquireFenceTime(16);
- mFrameTimeline->setSfWakeUp(sfToken1, 22, 11);
+ mFrameTimeline->setSfWakeUp(sfToken1, 22, Fps::fromPeriodNsecs(11));
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame1);
mFrameTimeline->setSfPresent(26, presentFence1);
@@ -1162,7 +1177,7 @@
mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame2->setAcquireFenceTime(36);
- mFrameTimeline->setSfWakeUp(sfToken2, 52, 11);
+ mFrameTimeline->setSfWakeUp(sfToken2, 52, Fps::fromPeriodNsecs(11));
surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame2);
mFrameTimeline->setSfPresent(56, presentFence2);
@@ -1187,6 +1202,14 @@
auto actuals2 = presentedSurfaceFrame2.getActuals();
EXPECT_EQ(actuals2.presentTime, 0);
+ ::testing::Mock::VerifyAndClearExpectations(mTimeStats.get());
+
+ EXPECT_CALL(*mTimeStats,
+ incrementJankyFrames(
+ TimeStats::JankyFramesInfo{Fps::fromPeriodNsecs(11), std::nullopt, sUidOne,
+ sLayerNameOne, JankType::PredictionError, 0, 5,
+ 0}));
+
addEmptyDisplayFrame();
// Fences for the second frame have flushed, so the present timestamps should be updated
@@ -1203,10 +1226,7 @@
}
TEST_F(FrameTimelineTest, jankClassification_surfaceFrameOnTimeFinishLatePresent) {
- // Global increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_)).Times(2);
- // Layer specific increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_, testing::_, testing::_)).Times(2);
+ EXPECT_CALL(*mTimeStats, incrementJankyFrames(_));
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({22, 26, 40});
int64_t sfToken2 = mTokenManager->generateTokenForPredictions({52, 56, 70});
@@ -1216,7 +1236,7 @@
mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame1->setAcquireFenceTime(16);
- mFrameTimeline->setSfWakeUp(sfToken1, 22, 11);
+ mFrameTimeline->setSfWakeUp(sfToken1, 22, Fps::fromPeriodNsecs(11));
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame1);
mFrameTimeline->setSfPresent(26, presentFence1);
@@ -1235,7 +1255,7 @@
mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame2->setAcquireFenceTime(36);
- mFrameTimeline->setSfWakeUp(sfToken2, 52, 11);
+ mFrameTimeline->setSfWakeUp(sfToken2, 52, Fps::fromPeriodNsecs(11));
surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame2);
mFrameTimeline->setSfPresent(56, presentFence2);
@@ -1260,6 +1280,14 @@
auto actuals2 = presentedSurfaceFrame2.getActuals();
EXPECT_EQ(actuals2.presentTime, 0);
+ ::testing::Mock::VerifyAndClearExpectations(mTimeStats.get());
+
+ EXPECT_CALL(*mTimeStats,
+ incrementJankyFrames(
+ TimeStats::JankyFramesInfo{Fps::fromPeriodNsecs(11), std::nullopt, sUidOne,
+ sLayerNameOne, JankType::PredictionError, 0, 5,
+ 0}));
+
addEmptyDisplayFrame();
// Fences for the second frame have flushed, so the present timestamps should be updated
@@ -1276,10 +1304,8 @@
}
TEST_F(FrameTimelineTest, jankClassification_surfaceFrameLateFinishEarlyPresent) {
- // Global increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_));
- // Layer specific increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_, testing::_, testing::_));
+ EXPECT_CALL(*mTimeStats, incrementJankyFrames(_));
+
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({42, 46, 50});
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({5, 26, 60});
@@ -1287,7 +1313,7 @@
mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame1->setAcquireFenceTime(40);
- mFrameTimeline->setSfWakeUp(sfToken1, 42, 11);
+ mFrameTimeline->setSfWakeUp(sfToken1, 42, Fps::fromPeriodNsecs(11));
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame1);
mFrameTimeline->setSfPresent(46, presentFence1);
@@ -1320,10 +1346,7 @@
// AppDeadlineMissed. Second frame - DisplayFrame is janky. This should propagate DisplayFrame's
// jank to the SurfaceFrame.
- // Global increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_)).Times(2);
- // Layer specific increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_, testing::_, testing::_)).Times(2);
+ EXPECT_CALL(*mTimeStats, incrementJankyFrames(_)).Times(2);
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t sfToken1 = mTokenManager->generateTokenForPredictions({32, 36, 40});
int64_t sfToken2 = mTokenManager->generateTokenForPredictions({42, 46, 50});
@@ -1333,7 +1356,7 @@
mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame1->setAcquireFenceTime(26);
- mFrameTimeline->setSfWakeUp(sfToken1, 32, 11);
+ mFrameTimeline->setSfWakeUp(sfToken1, 32, Fps::fromPeriodNsecs(11));
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame1);
mFrameTimeline->setSfPresent(36, presentFence1);
@@ -1352,7 +1375,7 @@
mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame2->setAcquireFenceTime(40);
- mFrameTimeline->setSfWakeUp(sfToken2, 43, 11);
+ mFrameTimeline->setSfWakeUp(sfToken2, 43, Fps::fromPeriodNsecs(11));
surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame2);
mFrameTimeline->setSfPresent(56, presentFence2);
@@ -1393,10 +1416,8 @@
}
TEST_F(FrameTimelineTest, jankClassification_multiJankBufferStuffingAndAppDeadlineMissed) {
- // Global increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_)).Times(2);
// Layer specific increment
- EXPECT_CALL(*mTimeStats, incrementJankyFrames(testing::_, testing::_, testing::_)).Times(2);
+ EXPECT_CALL(*mTimeStats, incrementJankyFrames(_)).Times(2);
auto presentFence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE);
int64_t surfaceFrameToken1 = mTokenManager->generateTokenForPredictions({10, 20, 30});
int64_t surfaceFrameToken2 = mTokenManager->generateTokenForPredictions({40, 50, 60});
@@ -1407,7 +1428,7 @@
mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken1, sInputEventId}, sPidOne,
sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame1->setAcquireFenceTime(50);
- mFrameTimeline->setSfWakeUp(sfToken1, 52, 30);
+ mFrameTimeline->setSfWakeUp(sfToken1, 52, Fps::fromPeriodNsecs(30));
surfaceFrame1->setPresentState(SurfaceFrame::PresentState::Presented);
mFrameTimeline->addSurfaceFrame(surfaceFrame1);
mFrameTimeline->setSfPresent(56, presentFence1);
@@ -1426,7 +1447,7 @@
mFrameTimeline->createSurfaceFrameForToken({surfaceFrameToken2, sInputEventId}, sPidOne,
sUidOne, sLayerNameOne, sLayerNameOne);
surfaceFrame2->setAcquireFenceTime(84);
- mFrameTimeline->setSfWakeUp(sfToken2, 112, 30);
+ mFrameTimeline->setSfWakeUp(sfToken2, 112, Fps::fromPeriodNsecs(30));
surfaceFrame2->setPresentState(SurfaceFrame::PresentState::Presented, 54);
mFrameTimeline->addSurfaceFrame(surfaceFrame2);
mFrameTimeline->setSfPresent(116, presentFence2);
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index 376995f..06f2036 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -1792,6 +1792,26 @@
ASSERT_TRUE(frameRateOverrides.empty());
}
+TEST_F(RefreshRateConfigsTest, updateDisplayModes) {
+ auto refreshRateConfigs =
+ std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device,
+ /*currentConfigId=*/HWC_CONFIG_ID_30);
+ refreshRateConfigs->setDisplayManagerPolicy({DisplayModeId(HWC_CONFIG_ID_30),
+ /* allowGroupSwitching */ false,
+ /* range */ {Fps(30.0f), Fps(30.0f)}});
+
+ refreshRateConfigs->updateDisplayModes(m60_90Device, HWC_CONFIG_ID_60);
+
+ const auto currentRefreshRate = refreshRateConfigs->getCurrentRefreshRate();
+ EXPECT_TRUE(currentRefreshRate.getFps().equalsWithMargin(Fps(60.0)));
+ EXPECT_EQ(currentRefreshRate.getModeId(), HWC_CONFIG_ID_60);
+
+ EXPECT_TRUE(
+ getMaxSupportedRefreshRate(*refreshRateConfigs).getFps().equalsWithMargin(Fps(90.0)));
+ EXPECT_TRUE(
+ getMinSupportedRefreshRate(*refreshRateConfigs).getFps().equalsWithMargin(Fps(60.0)));
+}
+
} // namespace
} // namespace scheduler
} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
index df4464e..35c32ec 100644
--- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp
@@ -55,14 +55,21 @@
using PowerMode = hardware::graphics::composer::V2_4::IComposerClient::PowerMode;
// clang-format off
-#define FMT_PROTO true
-#define FMT_STRING false
-#define LAYER_ID_0 0
-#define LAYER_ID_1 1
-#define UID_0 123
-#define LAYER_ID_INVALID -1
-#define NUM_LAYERS 1
-#define NUM_LAYERS_INVALID "INVALID"
+#define FMT_PROTO true
+#define FMT_STRING false
+#define LAYER_ID_0 0
+#define LAYER_ID_1 1
+#define UID_0 123
+#define REFRESH_RATE_0 61
+#define RENDER_RATE_0 31
+#define REFRESH_RATE_BUCKET_0 60
+#define RENDER_RATE_BUCKET_0 30
+#define LAYER_ID_INVALID -1
+#define NUM_LAYERS 1
+#define NUM_LAYERS_INVALID "INVALID"
+
+const constexpr Fps kRefreshRate0 = Fps(static_cast<float>(REFRESH_RATE_0));
+const constexpr Fps kRenderRate0 = Fps(static_cast<float>(RENDER_RATE_0));
enum InputCommand : int32_t {
ENABLE = 0,
@@ -246,11 +253,13 @@
ASSERT_NO_FATAL_FAILURE(mTimeStats->setDesiredTime(id, frameNumber, ts));
break;
case TimeStamp::PRESENT:
- ASSERT_NO_FATAL_FAILURE(mTimeStats->setPresentTime(id, frameNumber, ts));
+ ASSERT_NO_FATAL_FAILURE(
+ mTimeStats->setPresentTime(id, frameNumber, ts, kRefreshRate0, kRenderRate0));
break;
case TimeStamp::PRESENT_FENCE:
- ASSERT_NO_FATAL_FAILURE(
- mTimeStats->setPresentFence(id, frameNumber, std::make_shared<FenceTime>(ts)));
+ ASSERT_NO_FATAL_FAILURE(mTimeStats->setPresentFence(id, frameNumber,
+ std::make_shared<FenceTime>(ts),
+ kRefreshRate0, kRenderRate0));
break;
default:
ALOGD("Invalid timestamp type");
@@ -352,48 +361,29 @@
EXPECT_THAT(result, HasSubstr(expectedResult));
}
-TEST_F(TimeStatsTest, canIncreaseJankyFrames) {
- // this stat is not in the proto so verify by checking the string dump
- EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
-
- insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
- mTimeStats->incrementJankyFrames(JankType::SurfaceFlingerCpuDeadlineMissed);
- mTimeStats->incrementJankyFrames(JankType::SurfaceFlingerGpuDeadlineMissed);
- mTimeStats->incrementJankyFrames(JankType::DisplayHAL);
- mTimeStats->incrementJankyFrames(JankType::AppDeadlineMissed);
- mTimeStats->incrementJankyFrames(JankType::None);
-
- const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
- std::string expectedResult = "totalTimelineFrames = " + std::to_string(5);
- EXPECT_THAT(result, HasSubstr(expectedResult));
- expectedResult = "jankyFrames = " + std::to_string(4);
- EXPECT_THAT(result, HasSubstr(expectedResult));
- expectedResult = "sfLongCpuJankyFrames = " + std::to_string(1);
- EXPECT_THAT(result, HasSubstr(expectedResult));
- expectedResult = "sfLongGpuJankyFrames = " + std::to_string(1);
- EXPECT_THAT(result, HasSubstr(expectedResult));
- expectedResult = "sfUnattributedJankyFrame = " + std::to_string(1);
- EXPECT_THAT(result, HasSubstr(expectedResult));
- expectedResult = "appUnattributedJankyFrame = " + std::to_string(1);
- EXPECT_THAT(result, HasSubstr(expectedResult));
-}
-
TEST_F(TimeStatsTest, canIncreaseJankyFramesForLayer) {
// this stat is not in the proto so verify by checking the string dump
EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty());
insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 1, 1000000);
- mTimeStats->incrementJankyFrames(UID_0, genLayerName(LAYER_ID_0),
- JankType::SurfaceFlingerCpuDeadlineMissed);
- mTimeStats->incrementJankyFrames(UID_0, genLayerName(LAYER_ID_0),
- JankType::SurfaceFlingerGpuDeadlineMissed);
- mTimeStats->incrementJankyFrames(UID_0, genLayerName(LAYER_ID_0), JankType::DisplayHAL);
- mTimeStats->incrementJankyFrames(UID_0, genLayerName(LAYER_ID_0),
- JankType::AppDeadlineMissed);
- mTimeStats->incrementJankyFrames(UID_0, genLayerName(LAYER_ID_0), JankType::None);
+ mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
+ JankType::SurfaceFlingerCpuDeadlineMissed, 1, 2, 3});
+ mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
+ JankType::SurfaceFlingerGpuDeadlineMissed, 1, 2, 3});
+ mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
+ JankType::DisplayHAL, 1, 2, 3});
+ mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
+ JankType::AppDeadlineMissed, 1, 2, 3});
+ mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
+ JankType::None, 1, 2, 3});
const std::string result(inputCommand(InputCommand::DUMP_ALL, FMT_STRING));
- std::string expectedResult = "totalTimelineFrames = " + std::to_string(5);
+ std::string expectedResult =
+ "displayRefreshRate = " + std::to_string(REFRESH_RATE_BUCKET_0) + " fps";
+ EXPECT_THAT(result, HasSubstr(expectedResult));
+ expectedResult = "renderRate = " + std::to_string(RENDER_RATE_BUCKET_0) + " fps";
+ EXPECT_THAT(result, HasSubstr(expectedResult));
+ expectedResult = "totalTimelineFrames = " + std::to_string(5);
EXPECT_THAT(result, HasSubstr(expectedResult));
expectedResult = "jankyFrames = " + std::to_string(4);
EXPECT_THAT(result, HasSubstr(expectedResult));
@@ -848,14 +838,16 @@
mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(
std::chrono::duration_cast<std::chrono::nanoseconds>(1ms).count()));
- mTimeStats->incrementJankyFrames(UID_0, genLayerName(LAYER_ID_0),
- JankType::SurfaceFlingerCpuDeadlineMissed);
- mTimeStats->incrementJankyFrames(UID_0, genLayerName(LAYER_ID_0),
- JankType::SurfaceFlingerGpuDeadlineMissed);
- mTimeStats->incrementJankyFrames(UID_0, genLayerName(LAYER_ID_0), JankType::DisplayHAL);
- mTimeStats->incrementJankyFrames(UID_0, genLayerName(LAYER_ID_0),
- JankType::AppDeadlineMissed);
- mTimeStats->incrementJankyFrames(UID_0, genLayerName(LAYER_ID_0), JankType::None);
+ mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
+ JankType::SurfaceFlingerCpuDeadlineMissed, 1, 2, 3});
+ mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
+ JankType::SurfaceFlingerGpuDeadlineMissed, 1, 2, 3});
+ mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
+ JankType::DisplayHAL, 1, 2, 3});
+ mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
+ JankType::AppDeadlineMissed, 1, 2, 3});
+ mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
+ JankType::None, 1, 2, 3});
EXPECT_TRUE(inputCommand(InputCommand::CLEAR, FMT_STRING).empty());
@@ -865,11 +857,6 @@
EXPECT_THAT(result, HasSubstr("compositionStrategyChanges = 0"));
EXPECT_THAT(result, HasSubstr("averageFrameDuration = 0.000 ms"));
EXPECT_THAT(result, HasSubstr("averageRenderEngineTiming = 0.000 ms"));
- EXPECT_THAT(result, HasSubstr("jankyFrames = 0"));
- EXPECT_THAT(result, HasSubstr("sfLongCpuJankyFrames = 0"));
- EXPECT_THAT(result, HasSubstr("sfLongGpuJankyFrames = 0"));
- EXPECT_THAT(result, HasSubstr("sfUnattributedJankyFrame = 0"));
- EXPECT_THAT(result, HasSubstr("appUnattributedJankyFrame = 0"));
}
TEST_F(TimeStatsTest, canDumpWithMaxLayers) {
@@ -1000,11 +987,16 @@
mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(3000000));
mTimeStats->setPresentFenceGlobal(std::make_shared<FenceTime>(5000000));
- mTimeStats->incrementJankyFrames(JankType::SurfaceFlingerCpuDeadlineMissed);
- mTimeStats->incrementJankyFrames(JankType::SurfaceFlingerGpuDeadlineMissed);
- mTimeStats->incrementJankyFrames(JankType::DisplayHAL);
- mTimeStats->incrementJankyFrames(JankType::AppDeadlineMissed);
- mTimeStats->incrementJankyFrames(JankType::None);
+ mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
+ JankType::SurfaceFlingerCpuDeadlineMissed, 1, 2, 3});
+ mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
+ JankType::SurfaceFlingerGpuDeadlineMissed, 1, 2, 3});
+ mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
+ JankType::DisplayHAL, 1, 2, 3});
+ mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
+ JankType::AppDeadlineMissed, 1, 2, 3});
+ mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
+ JankType::None, 1, 2, 3});
EXPECT_THAT(mDelegate->mAtomTags,
UnorderedElementsAre(android::util::SURFACEFLINGER_STATS_GLOBAL_INFO,
@@ -1015,6 +1007,8 @@
std::string expectedFrameDuration = buildExpectedHistogramBytestring({2}, {1});
std::string expectedRenderEngineTiming = buildExpectedHistogramBytestring({1, 2}, {1, 1});
std::string expectedEmptyHistogram = buildExpectedHistogramBytestring({}, {});
+ std::string expectedSfDeadlineMissed = buildExpectedHistogramBytestring({1}, {4});
+ std::string expectedSfPredictionErrors = buildExpectedHistogramBytestring({2}, {4});
{
InSequence seq;
@@ -1047,18 +1041,20 @@
EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 0));
EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 0));
EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 0));
- EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 0));
+ EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, REFRESH_RATE_BUCKET_0));
EXPECT_CALL(*mDelegate,
statsEventWriteByteArray(mDelegate->mEvent,
- BytesEq((const uint8_t*)expectedEmptyHistogram.c_str(),
- expectedEmptyHistogram.size()),
- expectedEmptyHistogram.size()));
+ BytesEq((const uint8_t*)
+ expectedSfDeadlineMissed.c_str(),
+ expectedSfDeadlineMissed.size()),
+ expectedSfDeadlineMissed.size()));
EXPECT_CALL(*mDelegate,
statsEventWriteByteArray(mDelegate->mEvent,
- BytesEq((const uint8_t*)expectedEmptyHistogram.c_str(),
- expectedEmptyHistogram.size()),
- expectedEmptyHistogram.size()));
- EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 0));
+ BytesEq((const uint8_t*)
+ expectedSfPredictionErrors.c_str(),
+ expectedSfPredictionErrors.size()),
+ expectedSfPredictionErrors.size()));
+ EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, RENDER_RATE_BUCKET_0));
EXPECT_CALL(*mDelegate, statsEventBuild(mDelegate->mEvent));
}
@@ -1091,14 +1087,16 @@
}
insertTimeRecord(NORMAL_SEQUENCE, LAYER_ID_0, 2, 2000000);
- mTimeStats->incrementJankyFrames(UID_0, genLayerName(LAYER_ID_0),
- JankType::SurfaceFlingerCpuDeadlineMissed);
- mTimeStats->incrementJankyFrames(UID_0, genLayerName(LAYER_ID_0),
- JankType::SurfaceFlingerGpuDeadlineMissed);
- mTimeStats->incrementJankyFrames(UID_0, genLayerName(LAYER_ID_0), JankType::DisplayHAL);
- mTimeStats->incrementJankyFrames(UID_0, genLayerName(LAYER_ID_0),
- JankType::AppDeadlineMissed);
- mTimeStats->incrementJankyFrames(UID_0, genLayerName(LAYER_ID_0), JankType::None);
+ mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
+ JankType::SurfaceFlingerCpuDeadlineMissed, 1, 2, 3});
+ mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
+ JankType::SurfaceFlingerGpuDeadlineMissed, 1, 2, 3});
+ mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
+ JankType::DisplayHAL, 1, 2, 3});
+ mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
+ JankType::AppDeadlineMissed, 1, 2, 3});
+ mTimeStats->incrementJankyFrames({kRefreshRate0, kRenderRate0, UID_0, genLayerName(LAYER_ID_0),
+ JankType::None, 1, 2, 3});
EXPECT_THAT(mDelegate->mAtomTags,
UnorderedElementsAre(android::util::SURFACEFLINGER_STATS_GLOBAL_INFO,
@@ -1113,7 +1111,7 @@
std::string expectedDesiredToPresent = buildExpectedHistogramBytestring({1}, {1});
std::string expectedPostToAcquire = buildExpectedHistogramBytestring({1}, {1});
std::string expectedFrameRateOverride = frameRateVoteToProtoByteString(0.0, 0, 0);
- std::string expectedEmptyHistogram = buildExpectedHistogramBytestring({}, {});
+ std::string expectedAppDeadlineMissed = buildExpectedHistogramBytestring({3}, {4});
{
InSequence seq;
EXPECT_CALL(*mDelegate,
@@ -1170,8 +1168,8 @@
EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 0));
EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 0));
EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 0));
- EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 0));
- EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, 0));
+ EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, REFRESH_RATE_BUCKET_0));
+ EXPECT_CALL(*mDelegate, statsEventWriteInt32(mDelegate->mEvent, RENDER_RATE_BUCKET_0));
EXPECT_CALL(*mDelegate,
statsEventWriteByteArray(mDelegate->mEvent,
BytesEq((const uint8_t*)
@@ -1180,9 +1178,10 @@
expectedFrameRateOverride.size()));
EXPECT_CALL(*mDelegate,
statsEventWriteByteArray(mDelegate->mEvent,
- BytesEq((const uint8_t*)expectedEmptyHistogram.c_str(),
- expectedEmptyHistogram.size()),
- expectedEmptyHistogram.size()));
+ BytesEq((const uint8_t*)
+ expectedAppDeadlineMissed.c_str(),
+ expectedAppDeadlineMissed.size()),
+ expectedAppDeadlineMissed.size()));
EXPECT_CALL(*mDelegate, statsEventBuild(mDelegate->mEvent));
}
diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
index aa6798d..a6a465e 100644
--- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
@@ -328,6 +328,41 @@
EXPECT_EQ(PresentState::Presented, bufferlessSurfaceFrame2->getPresentState());
EXPECT_EQ(12, bufferlessSurfaceFrame2->getActuals().endTime);
}
+
+ void PendingSurfaceFramesRemovedAfterClassification() {
+ sp<BufferStateLayer> layer = createBufferStateLayer();
+
+ sp<Fence> fence1(new Fence());
+ auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1);
+ sp<GraphicBuffer> buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
+ layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt,
+ {/*vsyncId*/ 1, /*inputEventId*/ 0});
+ ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
+ const auto droppedSurfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX;
+
+ sp<Fence> fence2(new Fence());
+ auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2);
+ sp<GraphicBuffer> buffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
+ layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt,
+ {/*vsyncId*/ 1, /*inputEventId*/ 0});
+ acquireFence2->signalForTest(12);
+
+ ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
+ auto& presentedSurfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX;
+
+ commitTransaction(layer.get());
+ bool computeVisisbleRegions;
+ layer->updateTexImage(computeVisisbleRegions, 15, 0);
+
+ // Both the droppedSurfaceFrame and presentedSurfaceFrame should be in
+ // pendingJankClassifications.
+ EXPECT_EQ(2u, layer->mPendingJankClassifications.size());
+ presentedSurfaceFrame->onPresent(20, JankType::None, Fps::fromPeriodNsecs(11),
+ /*displayDeadlineDelta*/ 0, /*displayPresentDelta*/ 0);
+ layer->releasePendingBuffer(25);
+
+ EXPECT_EQ(0u, layer->mPendingJankClassifications.size());
+ }
};
TEST_F(TransactionSurfaceFrameTest, PresentedBufferlessSurfaceFrame) {
@@ -364,4 +399,7 @@
MergePendingStates_BufferlessSurfaceFramesWithOverlappingToken();
}
+TEST_F(TransactionSurfaceFrameTest, PendingSurfaceFramesRemovedAfterClassification) {
+ PendingSurfaceFramesRemovedAfterClassification();
+}
} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h b/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h
index 0a6a9f4..44b9b73 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockFrameTimeline.h
@@ -31,7 +31,7 @@
MOCK_METHOD0(onBootFinished, void());
MOCK_METHOD1(addSurfaceFrame, void(std::shared_ptr<frametimeline::SurfaceFrame>));
- MOCK_METHOD3(setSfWakeUp, void(int64_t, nsecs_t, nsecs_t));
+ MOCK_METHOD3(setSfWakeUp, void(int64_t, nsecs_t, Fps));
MOCK_METHOD2(setSfPresent, void(nsecs_t, const std::shared_ptr<FenceTime>&));
};
diff --git a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
index 99ec353..3e4a0b8 100644
--- a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
+++ b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h
@@ -48,10 +48,11 @@
MOCK_METHOD3(setDesiredTime, void(int32_t, uint64_t, nsecs_t));
MOCK_METHOD3(setAcquireTime, void(int32_t, uint64_t, nsecs_t));
MOCK_METHOD3(setAcquireFence, void(int32_t, uint64_t, const std::shared_ptr<FenceTime>&));
- MOCK_METHOD3(setPresentTime, void(int32_t, uint64_t, nsecs_t));
- MOCK_METHOD3(setPresentFence, void(int32_t, uint64_t, const std::shared_ptr<FenceTime>&));
- MOCK_METHOD1(incrementJankyFrames, void(int32_t));
- MOCK_METHOD3(incrementJankyFrames, void(uid_t, const std::string&, int32_t));
+ MOCK_METHOD5(setPresentTime, void(int32_t, uint64_t, nsecs_t, Fps, std::optional<Fps>));
+ MOCK_METHOD5(setPresentFence,
+ void(int32_t, uint64_t, const std::shared_ptr<FenceTime>&, Fps,
+ std::optional<Fps>));
+ MOCK_METHOD1(incrementJankyFrames, void(const JankyFramesInfo&));
MOCK_METHOD1(onDestroy, void(int32_t));
MOCK_METHOD2(removeTimeRecord, void(int32_t, uint64_t));
MOCK_METHOD1(setPowerMode,
diff --git a/services/surfaceflinger/tests/vsync/Android.bp b/services/surfaceflinger/tests/vsync/Android.bp
index 6a89945..bae9796 100644
--- a/services/surfaceflinger/tests/vsync/Android.bp
+++ b/services/surfaceflinger/tests/vsync/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_binary {
name: "test-vsync-events",
defaults: ["surfaceflinger_defaults"],
diff --git a/services/surfaceflinger/tests/waitforvsync/Android.bp b/services/surfaceflinger/tests/waitforvsync/Android.bp
index cb6d0fd..ffed4d7 100644
--- a/services/surfaceflinger/tests/waitforvsync/Android.bp
+++ b/services/surfaceflinger/tests/waitforvsync/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_binary {
name: "test-waitforvsync",
cflags: [
diff --git a/services/utils/Android.bp b/services/utils/Android.bp
index f3d2bc9..81e1232 100644
--- a/services/utils/Android.bp
+++ b/services/utils/Android.bp
@@ -15,6 +15,15 @@
//
// Static library used in testing and executables
//
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_static {
name: "libserviceutils",
diff --git a/services/utils/tests/Android.bp b/services/utils/tests/Android.bp
index f21254c..54cf5b7 100644
--- a/services/utils/tests/Android.bp
+++ b/services/utils/tests/Android.bp
@@ -14,6 +14,15 @@
// Build unit tests.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_test {
name: "prioritydumper_test",
test_suites: ["device-tests"],
diff --git a/services/vr/Android.bp b/services/vr/Android.bp
index 80df479..980dcf4 100644
--- a/services/vr/Android.bp
+++ b/services/vr/Android.bp
@@ -1,3 +1,13 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
subdirs = [
"*",
]
diff --git a/services/vr/bufferhubd/Android.bp b/services/vr/bufferhubd/Android.bp
index 7097e7a..8523bb2 100644
--- a/services/vr/bufferhubd/Android.bp
+++ b/services/vr/bufferhubd/Android.bp
@@ -12,6 +12,17 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
sharedLibraries = [
"libbase",
"libcutils",
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index 3728731..866007e 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libvr_hwc-hal",
diff --git a/services/vr/hardware_composer/aidl/Android.bp b/services/vr/hardware_composer/aidl/Android.bp
index a1d5392..98afdec 100644
--- a/services/vr/hardware_composer/aidl/Android.bp
+++ b/services/vr/hardware_composer/aidl/Android.bp
@@ -1,3 +1,14 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ // SPDX-license-identifier-Unicode-DFS
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_static {
name: "libvr_hwc-binder",
srcs: [
diff --git a/services/vr/performanced/Android.bp b/services/vr/performanced/Android.bp
index 0ef8cc4..5eca88b 100644
--- a/services/vr/performanced/Android.bp
+++ b/services/vr/performanced/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-MIT
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_defaults {
name: "performanced_defaults",
static_libs: [
diff --git a/services/vr/virtual_touchpad/Android.bp b/services/vr/virtual_touchpad/Android.bp
index 9cf4905..f2ec5a4 100644
--- a/services/vr/virtual_touchpad/Android.bp
+++ b/services/vr/virtual_touchpad/Android.bp
@@ -2,6 +2,15 @@
// Touchpad implementation.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
src = [
"EvdevInjector.cpp",
"VirtualTouchpadEvdev.cpp",
diff --git a/vulkan/Android.bp b/vulkan/Android.bp
index 4934970..33599ea 100644
--- a/vulkan/Android.bp
+++ b/vulkan/Android.bp
@@ -14,6 +14,16 @@
// This module makes the Vulkan libhardware HAL headers available, for
// the loader and for HAL/driver implementations.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ // SPDX-license-identifier-MIT
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_headers {
name: "hwvulkan_headers",
vendor_available: true,
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index 1d29bab..67cd875 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -13,6 +13,15 @@
// limitations under the License.
// Headers module is in external/vulkan-headers/Android.bp.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
ndk_library {
name: "libvulkan",
symbol_file: "libvulkan.map.txt",
diff --git a/vulkan/nulldrv/Android.bp b/vulkan/nulldrv/Android.bp
index ba02504..0daad9c 100644
--- a/vulkan/nulldrv/Android.bp
+++ b/vulkan/nulldrv/Android.bp
@@ -12,6 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
// Real drivers would set this to vulkan.$(TARGET_BOARD_PLATFORM)
name: "vulkan.default",
diff --git a/vulkan/vkjson/Android.bp b/vulkan/vkjson/Android.bp
index 8528898..fa0258b 100644
--- a/vulkan/vkjson/Android.bp
+++ b/vulkan/vkjson/Android.bp
@@ -1,3 +1,12 @@
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_native_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_native_license"],
+}
+
cc_library_shared {
name: "libvkjson",
srcs: [