summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/dumpstate/Android.bp5
-rw-r--r--include/android/choreographer.h89
-rw-r--r--include/android/looper.h47
-rw-r--r--include/android/sensor.h5
-rw-r--r--include/android/surface_control.h216
-rw-r--r--include/input/BlockingQueue.h (renamed from services/inputflinger/BlockingQueue.h)0
-rw-r--r--libs/binder/Android.bp10
-rw-r--r--libs/binder/liblog_stub/include/log/log.h20
-rw-r--r--libs/binder/ndk/include_ndk/android/binder_ibinder.h10
-rw-r--r--libs/binder/ndk/include_platform/android/binder_manager.h5
-rw-r--r--libs/binder/rust/binder_tokio/lib.rs27
-rw-r--r--libs/binder/rust/src/lib.rs6
-rw-r--r--libs/binder/rust/src/service.rs17
-rw-r--r--libs/binder/rust/tests/integration.rs60
-rw-r--r--libs/binder/tests/Android.bp4
-rw-r--r--libs/binder/tests/binderThroughputTest.cpp43
-rw-r--r--libs/binder/trusty/ndk/include/android/llndk-versioning.h18
-rw-r--r--libs/binder/trusty/ndk/include/sys/cdefs.h1
-rw-r--r--libs/binder/trusty/rust/binder_rpc_test/binder_rpc_test_session/lib.rs174
-rw-r--r--libs/binder/trusty/rust/binder_rpc_test/binder_rpc_test_session/rules.mk32
-rw-r--r--libs/binder/trusty/rust/binder_rpc_test/main.rs194
-rw-r--r--libs/binder/trusty/rust/binder_rpc_test/manifest.json2
-rw-r--r--libs/binder/trusty/rust/binder_rpc_test/rules.mk2
-rw-r--r--libs/binder/trusty/rust/binder_rpc_test/service/main.rs131
-rw-r--r--libs/binder/trusty/rust/binder_rpc_test/service/rules.mk3
-rw-r--r--libs/binder/trusty/rust/rules.mk1
-rw-r--r--libs/bufferstreams/Android.bp1
-rw-r--r--libs/bufferstreams/aconfig/bufferstreams_flags.aconfig1
-rw-r--r--libs/bufferstreams/rust/src/publishers/buffer_pool_publisher.rs2
-rw-r--r--libs/cputimeinstate/testtimeinstate.cpp5
-rw-r--r--libs/gui/Android.bp1
-rw-r--r--libs/gui/libgui_flags.aconfig1
-rw-r--r--libs/input/Android.bp1
-rw-r--r--libs/input/input_flags.aconfig1
-rw-r--r--libs/input/tests/Android.bp1
-rw-r--r--libs/input/tests/BlockingQueue_test.cpp (renamed from services/inputflinger/tests/BlockingQueue_test.cpp)7
-rw-r--r--services/gpuservice/GpuService.cpp3
-rw-r--r--services/gpuservice/gpumem/GpuMem.cpp1
-rw-r--r--services/gpuservice/gpumem/include/gpumem/GpuMem.h5
-rw-r--r--services/gpuservice/gpuwork/GpuWork.cpp1
-rw-r--r--services/gpuservice/gpuwork/include/gpuwork/GpuWork.h6
-rw-r--r--services/inputflinger/InputProcessor.h2
-rw-r--r--services/inputflinger/tests/Android.bp1
-rw-r--r--services/inputflinger/tests/InputDispatcher_test.cpp2
-rw-r--r--services/inputflinger/tests/fuzzers/BlockingQueueFuzzer.cpp2
-rw-r--r--services/surfaceflinger/Android.bp1
-rw-r--r--services/surfaceflinger/CompositionEngine/Android.bp1
-rw-r--r--services/surfaceflinger/surfaceflinger_flags.aconfig1
-rw-r--r--services/vibratorservice/VibratorCallbackScheduler.cpp8
-rw-r--r--services/vibratorservice/test/VibratorCallbackSchedulerTest.cpp69
-rw-r--r--services/vibratorservice/test/test_utils.h28
51 files changed, 1000 insertions, 274 deletions
diff --git a/cmds/dumpstate/Android.bp b/cmds/dumpstate/Android.bp
index 23f33d85a2..4a77967bb2 100644
--- a/cmds/dumpstate/Android.bp
+++ b/cmds/dumpstate/Android.bp
@@ -79,7 +79,10 @@ filegroup {
cc_defaults {
name: "dumpstate_defaults",
- defaults: ["dumpstate_cflag_defaults"],
+ defaults: [
+ "aconfig_lib_cc_static_link.defaults",
+ "dumpstate_cflag_defaults",
+ ],
shared_libs: [
"android.hardware.dumpstate@1.0",
"android.hardware.dumpstate@1.1",
diff --git a/include/android/choreographer.h b/include/android/choreographer.h
index f999708f04..6a91d9836e 100644
--- a/include/android/choreographer.h
+++ b/include/android/choreographer.h
@@ -17,8 +17,20 @@
/**
* @addtogroup Choreographer
*
- * Choreographer coordinates the timing of frame rendering. This is the C version of the
- * android.view.Choreographer object in Java.
+ * Choreographer coordinates the timing of frame rendering. This is the C
+ * version of the android.view.Choreographer object in Java. If you do not use
+ * Choreographer to pace your render loop, you may render too quickly for the
+ * display, increasing latency between frame submission and presentation.
+ *
+ * Input events are guaranteed to be processed before the frame callback is
+ * called, and will not be run concurrently. Input and sensor events should not
+ * be handled in the Choregrapher callback.
+ *
+ * The frame callback is also the appropriate place to run any per-frame state
+ * update logic. For example, in a game, the frame callback should be
+ * responsible for updating things like physics, AI, game state, and rendering
+ * the frame. Input and sensors should be handled separately via callbacks
+ * registered with AInputQueue and ASensorManager.
*
* As of API level 33, apps can follow proper frame pacing and even choose a future frame to render.
* The API is used as follows:
@@ -38,6 +50,11 @@
* 4. SurfaceFlinger attempts to follow the chosen frame timeline, by not applying transactions or
* latching buffers before the desired presentation time.
*
+ * On older devices, AChoreographer_postFrameCallback64 or
+ * AChoreographer_postFrameCallback can be used to lesser effect. They cannot be
+ * used to precisely plan your render timeline, but will rate limit to avoid
+ * overloading the display pipeline and increasing frame latency.
+ *
* @{
*/
@@ -119,23 +136,60 @@ typedef void (*AChoreographer_refreshRateCallback)(int64_t vsyncPeriodNanos, voi
AChoreographer* AChoreographer_getInstance() __INTRODUCED_IN(24);
/**
- * Deprecated: Use AChoreographer_postFrameCallback64 instead.
+ * Post a callback to be run when the application should begin rendering the
+ * next frame. The data pointer provided will be passed to the callback function
+ * when it's called.
+ *
+ * The callback will only be run for the next frame, not all subsequent frames,
+ * so to render continuously the callback should itself call
+ * AChoreographer_postFrameCallback.
+ *
+ * \bug The callback receives the frame time in nanoseconds as a long. On 32-bit
+ * systems, long is 32-bit, so the frame time will roll over roughly every two
+ * seconds. If your minSdkVersion is 29 or higher, switch to
+ * AChoreographer_postFrameCallback64, which uses a 64-bit frame time for all
+ * platforms. For older OS versions, you must combine the argument with the
+ * upper bits of clock_gettime(CLOCK_MONOTONIC, ...) on 32-bit systems.
+ *
+ * \deprecated Use AChoreographer_postFrameCallback64, which does not have the
+ * bug described above.
*/
void AChoreographer_postFrameCallback(AChoreographer* choreographer,
AChoreographer_frameCallback callback, void* data)
- __INTRODUCED_IN(24) __DEPRECATED_IN(29);
+ __INTRODUCED_IN(24) __DEPRECATED_IN(29, "Use AChoreographer_postFrameCallback64 instead");
/**
- * Deprecated: Use AChoreographer_postFrameCallbackDelayed64 instead.
+ * Post a callback to be run when the application should begin rendering the
+ * next frame following the specified delay. The data pointer provided will be
+ * passed to the callback function when it's called.
+ *
+ * The callback will only be run for the next frame after the delay, not all
+ * subsequent frames, so to render continuously the callback should itself call
+ * AChoreographer_postFrameCallbackDelayed.
+ *
+ * \bug The callback receives the frame time in nanoseconds as a long. On 32-bit
+ * systems, long is 32-bit, so the frame time will roll over roughly every two
+ * seconds. If your minSdkVersion is 29 or higher, switch to
+ * AChoreographer_postFrameCallbackDelayed64, which uses a 64-bit frame time for
+ * all platforms. For older OS versions, you must combine the argument with the
+ * upper bits of clock_gettime(CLOCK_MONOTONIC, ...) on 32-bit systems.
+ *
+ * \deprecated Use AChoreographer_postFrameCallbackDelayed64, which does not
+ * have the bug described above.
*/
void AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer,
AChoreographer_frameCallback callback, void* data,
long delayMillis) __INTRODUCED_IN(24)
- __DEPRECATED_IN(29);
+ __DEPRECATED_IN(29, "Use AChoreographer_postFrameCallbackDelayed64 instead");
/**
- * Post a callback to be run on the next frame. The data pointer provided will
- * be passed to the callback function when it's called.
+ * Post a callback to be run when the application should begin rendering the
+ * next frame. The data pointer provided will be passed to the callback function
+ * when it's called.
+ *
+ * The callback will only be run on the next frame, not all subsequent frames,
+ * so to render continuously the callback should itself call
+ * AChoreographer_postFrameCallback64.
*
* Available since API level 29.
*/
@@ -144,9 +198,13 @@ void AChoreographer_postFrameCallback64(AChoreographer* choreographer,
__INTRODUCED_IN(29);
/**
- * Post a callback to be run on the frame following the specified delay. The
- * data pointer provided will be passed to the callback function when it's
- * called.
+ * Post a callback to be run when the application should begin rendering the
+ * next frame following the specified delay. The data pointer provided will be
+ * passed to the callback function when it's called.
+ *
+ * The callback will only be run for the next frame after the delay, not all
+ * subsequent frames, so to render continuously the callback should itself call
+ * AChoreographer_postFrameCallbackDelayed64.
*
* Available since API level 29.
*/
@@ -155,8 +213,13 @@ void AChoreographer_postFrameCallbackDelayed64(AChoreographer* choreographer,
uint32_t delayMillis) __INTRODUCED_IN(29);
/**
- * Posts a callback to be run on the next frame. The data pointer provided will
- * be passed to the callback function when it's called.
+ * Posts a callback to be run when the application should begin rendering the
+ * next frame. The data pointer provided will be passed to the callback function
+ * when it's called.
+ *
+ * The callback will only be run for the next frame, not all subsequent frames,
+ * so to render continuously the callback should itself call
+ * AChoreographer_postVsyncCallback.
*
* Available since API level 33.
*/
diff --git a/include/android/looper.h b/include/android/looper.h
index e50730d5c1..d80a3660a6 100644
--- a/include/android/looper.h
+++ b/include/android/looper.h
@@ -35,7 +35,7 @@ extern "C" {
// This file may also be built on glibc or on Windows/MacOS libc's, so
// deprecated definitions are provided.
#if !defined(__REMOVED_IN)
-#define __REMOVED_IN(__api_level) __attribute__((__deprecated__))
+#define __REMOVED_IN(__api_level, msg) __attribute__((__deprecated__(msg)))
#endif
struct ALooper;
@@ -182,23 +182,27 @@ typedef int (*ALooper_callbackFunc)(int fd, int events, void* data);
* If the timeout is zero, returns immediately without blocking.
* If the timeout is negative, waits indefinitely until an event appears.
*
- * Returns ALOOPER_POLL_WAKE if the poll was awoken using wake() before
+ * Returns ALOOPER_POLL_WAKE if the poll was awoken using ALooper_wake() before
* the timeout expired and no callbacks were invoked and no other file
- * descriptors were ready.
+ * descriptors were ready. **All return values may also imply
+ * ALOOPER_POLL_WAKE.**
*
- * Returns ALOOPER_POLL_CALLBACK if one or more callbacks were invoked.
+ * Returns ALOOPER_POLL_CALLBACK if one or more callbacks were invoked. The poll
+ * may also have been explicitly woken by ALooper_wake.
*
- * Returns ALOOPER_POLL_TIMEOUT if there was no data before the given
- * timeout expired.
+ * Returns ALOOPER_POLL_TIMEOUT if there was no data before the given timeout
+ * expired. The poll may also have been explicitly woken by ALooper_wake.
*
- * Returns ALOOPER_POLL_ERROR if an error occurred.
+ * Returns ALOOPER_POLL_ERROR if the calling thread has no associated Looper or
+ * for unrecoverable internal errors. The poll may also have been explicitly
+ * woken by ALooper_wake.
*
- * Returns a value >= 0 containing an identifier (the same identifier
- * `ident` passed to ALooper_addFd()) if its file descriptor has data
- * and it has no callback function (requiring the caller here to
- * handle it). In this (and only this) case outFd, outEvents and
- * outData will contain the poll events and data associated with the
- * fd, otherwise they will be set to NULL.
+ * Returns a value >= 0 containing an identifier (the same identifier `ident`
+ * passed to ALooper_addFd()) if its file descriptor has data and it has no
+ * callback function (requiring the caller here to handle it). In this (and
+ * only this) case outFd, outEvents and outData will contain the poll events and
+ * data associated with the fd, otherwise they will be set to NULL. The poll may
+ * also have been explicitly woken by ALooper_wake.
*
* This method does not return until it has finished invoking the appropriate callbacks
* for all file descriptors that were signalled.
@@ -210,10 +214,21 @@ int ALooper_pollOnce(int timeoutMillis, int* outFd, int* outEvents, void** outDa
* data has been consumed or a file descriptor is available with no callback.
* This function will never return ALOOPER_POLL_CALLBACK.
*
- * Removed in API 34 as ALooper_pollAll can swallow ALooper_wake calls.
- * Use ALooper_pollOnce instead.
+ * This API cannot be used safely, but a safe alternative exists (see below). As
+ * such, new builds will not be able to call this API and must migrate to the
+ * safe API. Binary compatibility is preserved to support already-compiled apps.
+ *
+ * \bug ALooper_pollAll will not wake in response to ALooper_wake calls if it
+ * also handles another event at the same time.
+ *
+ * \deprecated Calls to ALooper_pollAll should be replaced with
+ * ALooper_pollOnce. If you call ALooper_pollOnce in a loop, you *must* treat
+ * all return values as if they also indicate ALOOPER_POLL_WAKE.
*/
-int ALooper_pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData) __REMOVED_IN(1);
+int ALooper_pollAll(int timeoutMillis, int* outFd, int* outEvents, void** outData)
+ __REMOVED_IN(1,
+ "ALooper_pollAll may ignore wakes. Use ALooper_pollOnce instead. See "
+ "The API documentation for more information");
/**
* Wakes the poll asynchronously.
diff --git a/include/android/sensor.h b/include/android/sensor.h
index a618393e66..e3c1ccfc6c 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -60,7 +60,7 @@
#define __INTRODUCED_IN(__api_level) /* nothing */
#endif
#if !defined(__DEPRECATED_IN)
-#define __DEPRECATED_IN(__api_level) __attribute__((__deprecated__))
+#define __DEPRECATED_IN(__api_level, msg) __attribute__((__deprecated__(msg)))
#endif
#ifdef __cplusplus
@@ -748,7 +748,8 @@ typedef ASensorRef const* ASensorList;
* ASensorManager* sensorManager = ASensorManager_getInstance();
*
*/
-ASensorManager* ASensorManager_getInstance() __DEPRECATED_IN(26);
+ASensorManager* ASensorManager_getInstance()
+ __DEPRECATED_IN(26, "Use ASensorManager_getInstanceForPackage instead");
/**
* Get a reference to the sensor manager. ASensorManager is a singleton
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index 443cb7e51f..14167e6467 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -62,16 +62,18 @@ typedef struct ASurfaceControl ASurfaceControl;
*
* Available since API level 29.
*/
-ASurfaceControl* ASurfaceControl_createFromWindow(ANativeWindow* parent, const char* debug_name)
- __INTRODUCED_IN(29);
+ASurfaceControl* _Nullable ASurfaceControl_createFromWindow(ANativeWindow* _Nonnull parent,
+ const char* _Nonnull debug_name)
+ __INTRODUCED_IN(29);
/**
* See ASurfaceControl_createFromWindow.
*
* Available since API level 29.
*/
-ASurfaceControl* ASurfaceControl_create(ASurfaceControl* parent, const char* debug_name)
- __INTRODUCED_IN(29);
+ASurfaceControl* _Nullable ASurfaceControl_create(ASurfaceControl* _Nonnull parent,
+ const char* _Nonnull debug_name)
+ __INTRODUCED_IN(29);
/**
* Acquires a reference on the given ASurfaceControl object. This prevents the object
@@ -81,7 +83,7 @@ ASurfaceControl* ASurfaceControl_create(ASurfaceControl* parent, const char* deb
*
* Available since API level 31.
*/
-void ASurfaceControl_acquire(ASurfaceControl* surface_control) __INTRODUCED_IN(31);
+void ASurfaceControl_acquire(ASurfaceControl* _Nonnull surface_control) __INTRODUCED_IN(31);
/**
* Removes a reference that was previously acquired with one of the following functions:
@@ -92,7 +94,7 @@ void ASurfaceControl_acquire(ASurfaceControl* surface_control) __INTRODUCED_IN(3
*
* Available since API level 29.
*/
-void ASurfaceControl_release(ASurfaceControl* surface_control) __INTRODUCED_IN(29);
+void ASurfaceControl_release(ASurfaceControl* _Nonnull surface_control) __INTRODUCED_IN(29);
struct ASurfaceTransaction;
@@ -108,14 +110,14 @@ typedef struct ASurfaceTransaction ASurfaceTransaction;
*
* Available since API level 29.
*/
-ASurfaceTransaction* ASurfaceTransaction_create() __INTRODUCED_IN(29);
+ASurfaceTransaction* _Nonnull ASurfaceTransaction_create() __INTRODUCED_IN(29);
/**
* Destroys the \a transaction object.
*
* Available since API level 29.
*/
-void ASurfaceTransaction_delete(ASurfaceTransaction* transaction) __INTRODUCED_IN(29);
+void ASurfaceTransaction_delete(ASurfaceTransaction* _Nullable transaction) __INTRODUCED_IN(29);
/**
* Applies the updates accumulated in \a transaction.
@@ -126,7 +128,7 @@ void ASurfaceTransaction_delete(ASurfaceTransaction* transaction) __INTRODUCED_I
*
* Available since API level 29.
*/
-void ASurfaceTransaction_apply(ASurfaceTransaction* transaction) __INTRODUCED_IN(29);
+void ASurfaceTransaction_apply(ASurfaceTransaction* _Nonnull transaction) __INTRODUCED_IN(29);
/**
* An opaque handle returned during a callback that can be used to query general stats and stats for
@@ -154,9 +156,9 @@ typedef struct ASurfaceTransactionStats ASurfaceTransactionStats;
*
* Available since API level 29.
*/
-typedef void (*ASurfaceTransaction_OnComplete)(void* context, ASurfaceTransactionStats* stats)
- __INTRODUCED_IN(29);
-
+typedef void (*ASurfaceTransaction_OnComplete)(void* _Null_unspecified context,
+ ASurfaceTransactionStats* _Nonnull stats)
+ __INTRODUCED_IN(29);
/**
* The ASurfaceTransaction_OnCommit callback is invoked when transaction is applied and the updates
@@ -183,8 +185,9 @@ typedef void (*ASurfaceTransaction_OnComplete)(void* context, ASurfaceTransactio
*
* Available since API level 31.
*/
-typedef void (*ASurfaceTransaction_OnCommit)(void* context, ASurfaceTransactionStats* stats)
- __INTRODUCED_IN(31);
+typedef void (*ASurfaceTransaction_OnCommit)(void* _Null_unspecified context,
+ ASurfaceTransactionStats* _Nonnull stats)
+ __INTRODUCED_IN(31);
/**
* Returns the timestamp of when the frame was latched by the framework. Once a frame is
@@ -192,8 +195,8 @@ typedef void (*ASurfaceTransaction_OnCommit)(void* context, ASurfaceTransactionS
*
* Available since API level 29.
*/
-int64_t ASurfaceTransactionStats_getLatchTime(ASurfaceTransactionStats* surface_transaction_stats)
- __INTRODUCED_IN(29);
+int64_t ASurfaceTransactionStats_getLatchTime(
+ ASurfaceTransactionStats* _Nonnull surface_transaction_stats) __INTRODUCED_IN(29);
/**
* Returns a sync fence that signals when the transaction has been presented.
@@ -204,8 +207,8 @@ int64_t ASurfaceTransactionStats_getLatchTime(ASurfaceTransactionStats* surface_
*
* Available since API level 29.
*/
-int ASurfaceTransactionStats_getPresentFenceFd(ASurfaceTransactionStats* surface_transaction_stats)
- __INTRODUCED_IN(29);
+int ASurfaceTransactionStats_getPresentFenceFd(
+ ASurfaceTransactionStats* _Nonnull surface_transaction_stats) __INTRODUCED_IN(29);
/**
* \a outASurfaceControls returns an array of ASurfaceControl pointers that were updated during the
@@ -217,18 +220,18 @@ int ASurfaceTransactionStats_getPresentFenceFd(ASurfaceTransactionStats* surface
*
* \a outASurfaceControlsSize returns the size of the ASurfaceControls array.
*/
-void ASurfaceTransactionStats_getASurfaceControls(ASurfaceTransactionStats* surface_transaction_stats,
- ASurfaceControl*** outASurfaceControls,
- size_t* outASurfaceControlsSize)
- __INTRODUCED_IN(29);
+void ASurfaceTransactionStats_getASurfaceControls(
+ ASurfaceTransactionStats* _Nonnull surface_transaction_stats,
+ ASurfaceControl* _Nullable* _Nullable* _Nonnull outASurfaceControls,
+ size_t* _Nonnull outASurfaceControlsSize) __INTRODUCED_IN(29);
/**
* Releases the array of ASurfaceControls that were returned by
* ASurfaceTransactionStats_getASurfaceControls().
*
* Available since API level 29.
*/
-void ASurfaceTransactionStats_releaseASurfaceControls(ASurfaceControl** surface_controls)
- __INTRODUCED_IN(29);
+void ASurfaceTransactionStats_releaseASurfaceControls(
+ ASurfaceControl* _Nonnull* _Nonnull surface_controls) __INTRODUCED_IN(29);
/**
* Returns the timestamp of when the CURRENT buffer was acquired. A buffer is considered
@@ -237,9 +240,9 @@ void ASurfaceTransactionStats_releaseASurfaceControls(ASurfaceControl** surface_
*
* Available since API level 29.
*/
-int64_t ASurfaceTransactionStats_getAcquireTime(ASurfaceTransactionStats* surface_transaction_stats,
- ASurfaceControl* surface_control)
- __INTRODUCED_IN(29);
+int64_t ASurfaceTransactionStats_getAcquireTime(
+ ASurfaceTransactionStats* _Nonnull surface_transaction_stats,
+ ASurfaceControl* _Nonnull surface_control) __INTRODUCED_IN(29);
/**
* The returns the fence used to signal the release of the PREVIOUS buffer set on
@@ -264,9 +267,8 @@ int64_t ASurfaceTransactionStats_getAcquireTime(ASurfaceTransactionStats* surfac
* Available since API level 29.
*/
int ASurfaceTransactionStats_getPreviousReleaseFenceFd(
- ASurfaceTransactionStats* surface_transaction_stats,
- ASurfaceControl* surface_control)
- __INTRODUCED_IN(29);
+ ASurfaceTransactionStats* _Nonnull surface_transaction_stats,
+ ASurfaceControl* _Nonnull surface_control) __INTRODUCED_IN(29);
/**
* Sets the callback that will be invoked when the updates from this transaction
@@ -275,8 +277,10 @@ int ASurfaceTransactionStats_getPreviousReleaseFenceFd(
*
* Available since API level 29.
*/
-void ASurfaceTransaction_setOnComplete(ASurfaceTransaction* transaction, void* context,
- ASurfaceTransaction_OnComplete func) __INTRODUCED_IN(29);
+void ASurfaceTransaction_setOnComplete(ASurfaceTransaction* _Nonnull transaction,
+ void* _Null_unspecified context,
+ ASurfaceTransaction_OnComplete _Nonnull func)
+ __INTRODUCED_IN(29);
/**
* Sets the callback that will be invoked when the updates from this transaction are applied and are
@@ -285,8 +289,10 @@ void ASurfaceTransaction_setOnComplete(ASurfaceTransaction* transaction, void* c
*
* Available since API level 31.
*/
-void ASurfaceTransaction_setOnCommit(ASurfaceTransaction* transaction, void* context,
- ASurfaceTransaction_OnCommit func) __INTRODUCED_IN(31);
+void ASurfaceTransaction_setOnCommit(ASurfaceTransaction* _Nonnull transaction,
+ void* _Null_unspecified context,
+ ASurfaceTransaction_OnCommit _Nonnull func)
+ __INTRODUCED_IN(31);
/**
* Reparents the \a surface_control from its old parent to the \a new_parent surface control.
@@ -296,9 +302,9 @@ void ASurfaceTransaction_setOnCommit(ASurfaceTransaction* transaction, void* con
*
* Available since API level 29.
*/
-void ASurfaceTransaction_reparent(ASurfaceTransaction* transaction,
- ASurfaceControl* surface_control, ASurfaceControl* new_parent)
- __INTRODUCED_IN(29);
+void ASurfaceTransaction_reparent(ASurfaceTransaction* _Nonnull transaction,
+ ASurfaceControl* _Nonnull surface_control,
+ ASurfaceControl* _Nullable new_parent) __INTRODUCED_IN(29);
/**
* Parameter for ASurfaceTransaction_setVisibility().
@@ -314,10 +320,10 @@ enum ASurfaceTransactionVisibility : int8_t {
*
* Available since API level 29.
*/
-void ASurfaceTransaction_setVisibility(ASurfaceTransaction* transaction,
- ASurfaceControl* surface_control,
+void ASurfaceTransaction_setVisibility(ASurfaceTransaction* _Nonnull transaction,
+ ASurfaceControl* _Nonnull surface_control,
enum ASurfaceTransactionVisibility visibility)
- __INTRODUCED_IN(29);
+ __INTRODUCED_IN(29);
/**
* Updates the z order index for \a surface_control. Note that the z order for a surface
@@ -328,9 +334,9 @@ void ASurfaceTransaction_setVisibility(ASurfaceTransaction* transaction,
*
* Available since API level 29.
*/
-void ASurfaceTransaction_setZOrder(ASurfaceTransaction* transaction,
- ASurfaceControl* surface_control, int32_t z_order)
- __INTRODUCED_IN(29);
+void ASurfaceTransaction_setZOrder(ASurfaceTransaction* _Nonnull transaction,
+ ASurfaceControl* _Nonnull surface_control, int32_t z_order)
+ __INTRODUCED_IN(29);
/**
* Updates the AHardwareBuffer displayed for \a surface_control. If not -1, the
@@ -345,9 +351,10 @@ void ASurfaceTransaction_setZOrder(ASurfaceTransaction* transaction,
*
* Available since API level 29.
*/
-void ASurfaceTransaction_setBuffer(ASurfaceTransaction* transaction,
- ASurfaceControl* surface_control, AHardwareBuffer* buffer,
- int acquire_fence_fd) __INTRODUCED_IN(29);
+void ASurfaceTransaction_setBuffer(ASurfaceTransaction* _Nonnull transaction,
+ ASurfaceControl* _Nonnull surface_control,
+ AHardwareBuffer* _Nonnull buffer, int acquire_fence_fd)
+ __INTRODUCED_IN(29);
/**
* Updates the color for \a surface_control. This will make the background color for the
@@ -357,23 +364,23 @@ void ASurfaceTransaction_setBuffer(ASurfaceTransaction* transaction,
*
* Available since API level 29.
*/
-void ASurfaceTransaction_setColor(ASurfaceTransaction* transaction,
- ASurfaceControl* surface_control, float r, float g, float b,
- float alpha, enum ADataSpace dataspace)
- __INTRODUCED_IN(29);
+void ASurfaceTransaction_setColor(ASurfaceTransaction* _Nonnull transaction,
+ ASurfaceControl* _Nonnull surface_control, float r, float g,
+ float b, float alpha, enum ADataSpace dataspace)
+ __INTRODUCED_IN(29);
/**
* \param source The sub-rect within the buffer's content to be rendered inside the surface's area
* The surface's source rect is clipped by the bounds of its current buffer. The source rect's width
* and height must be > 0.
*
- * \param destination Specifies the rect in the parent's space where this surface will be drawn. The post
- * source rect bounds are scaled to fit the destination rect. The surface's destination rect is
+ * \param destination Specifies the rect in the parent's space where this surface will be drawn. The
+ * post source rect bounds are scaled to fit the destination rect. The surface's destination rect is
* clipped by the bounds of its parent. The destination rect's width and height must be > 0.
*
- * \param transform The transform applied after the source rect is applied to the buffer. This parameter
- * should be set to 0 for no transform. To specify a transfrom use the NATIVE_WINDOW_TRANSFORM_*
- * enum.
+ * \param transform The transform applied after the source rect is applied to the buffer. This
+ * parameter should be set to 0 for no transform. To specify a transfrom use the
+ * NATIVE_WINDOW_TRANSFORM_* enum.
*
* Available since API level 29.
*
@@ -382,10 +389,10 @@ void ASurfaceTransaction_setColor(ASurfaceTransaction* transaction,
* to set different properties at different times, instead of having to specify all the desired
* properties at once.
*/
-void ASurfaceTransaction_setGeometry(ASurfaceTransaction* transaction,
- ASurfaceControl* surface_control, const ARect& source,
+void ASurfaceTransaction_setGeometry(ASurfaceTransaction* _Nonnull transaction,
+ ASurfaceControl* _Nonnull surface_control, const ARect& source,
const ARect& destination, int32_t transform)
- __INTRODUCED_IN(29);
+ __INTRODUCED_IN(29);
/**
* Bounds the surface and its children to the bounds specified. The crop and buffer size will be
@@ -396,9 +403,9 @@ void ASurfaceTransaction_setGeometry(ASurfaceTransaction* transaction,
*
* Available since API level 31.
*/
-void ASurfaceTransaction_setCrop(ASurfaceTransaction* transaction,
- ASurfaceControl* surface_control, const ARect& crop)
- __INTRODUCED_IN(31);
+void ASurfaceTransaction_setCrop(ASurfaceTransaction* _Nonnull transaction,
+ ASurfaceControl* _Nonnull surface_control, const ARect& crop)
+ __INTRODUCED_IN(31);
/**
* Specifies the position in the parent's space where the surface will be drawn.
@@ -408,9 +415,9 @@ void ASurfaceTransaction_setCrop(ASurfaceTransaction* transaction,
*
* Available since API level 31.
*/
-void ASurfaceTransaction_setPosition(ASurfaceTransaction* transaction,
- ASurfaceControl* surface_control, int32_t x, int32_t y)
- __INTRODUCED_IN(31);
+void ASurfaceTransaction_setPosition(ASurfaceTransaction* _Nonnull transaction,
+ ASurfaceControl* _Nonnull surface_control, int32_t x,
+ int32_t y) __INTRODUCED_IN(31);
/**
* \param transform The transform applied after the source rect is applied to the buffer. This
@@ -419,9 +426,9 @@ void ASurfaceTransaction_setPosition(ASurfaceTransaction* transaction,
*
* Available since API level 31.
*/
-void ASurfaceTransaction_setBufferTransform(ASurfaceTransaction* transaction,
- ASurfaceControl* surface_control, int32_t transform)
- __INTRODUCED_IN(31);
+void ASurfaceTransaction_setBufferTransform(ASurfaceTransaction* _Nonnull transaction,
+ ASurfaceControl* _Nonnull surface_control,
+ int32_t transform) __INTRODUCED_IN(31);
/**
* Sets an x and y scale of a surface with (0, 0) as the centerpoint of the scale.
@@ -431,9 +438,9 @@ void ASurfaceTransaction_setBufferTransform(ASurfaceTransaction* transaction,
*
* Available since API level 31.
*/
-void ASurfaceTransaction_setScale(ASurfaceTransaction* transaction,
- ASurfaceControl* surface_control, float xScale, float yScale)
- __INTRODUCED_IN(31);
+void ASurfaceTransaction_setScale(ASurfaceTransaction* _Nonnull transaction,
+ ASurfaceControl* _Nonnull surface_control, float xScale,
+ float yScale) __INTRODUCED_IN(31);
/**
* Parameter for ASurfaceTransaction_setBufferTransparency().
*/
@@ -449,8 +456,8 @@ enum ASurfaceTransactionTransparency : int8_t {
*
* Available since API level 29.
*/
-void ASurfaceTransaction_setBufferTransparency(ASurfaceTransaction* transaction,
- ASurfaceControl* surface_control,
+void ASurfaceTransaction_setBufferTransparency(ASurfaceTransaction* _Nonnull transaction,
+ ASurfaceControl* _Nonnull surface_control,
enum ASurfaceTransactionTransparency transparency)
__INTRODUCED_IN(29);
@@ -460,9 +467,10 @@ void ASurfaceTransaction_setBufferTransparency(ASurfaceTransaction* transaction,
*
* Available since API level 29.
*/
-void ASurfaceTransaction_setDamageRegion(ASurfaceTransaction* transaction,
- ASurfaceControl* surface_control, const ARect rects[],
- uint32_t count) __INTRODUCED_IN(29);
+void ASurfaceTransaction_setDamageRegion(ASurfaceTransaction* _Nonnull transaction,
+ ASurfaceControl* _Nonnull surface_control,
+ const ARect* _Nullable rects, uint32_t count)
+ __INTRODUCED_IN(29);
/**
* Specifies a desiredPresentTime for the transaction. The framework will try to present
@@ -476,7 +484,7 @@ void ASurfaceTransaction_setDamageRegion(ASurfaceTransaction* transaction,
*
* Available since API level 29.
*/
-void ASurfaceTransaction_setDesiredPresentTime(ASurfaceTransaction* transaction,
+void ASurfaceTransaction_setDesiredPresentTime(ASurfaceTransaction* _Nonnull transaction,
int64_t desiredPresentTime) __INTRODUCED_IN(29);
/**
@@ -486,8 +494,8 @@ void ASurfaceTransaction_setDesiredPresentTime(ASurfaceTransaction* transaction,
*
* Available since API level 29.
*/
-void ASurfaceTransaction_setBufferAlpha(ASurfaceTransaction* transaction,
- ASurfaceControl* surface_control, float alpha)
+void ASurfaceTransaction_setBufferAlpha(ASurfaceTransaction* _Nonnull transaction,
+ ASurfaceControl* _Nonnull surface_control, float alpha)
__INTRODUCED_IN(29);
/**
@@ -497,9 +505,9 @@ void ASurfaceTransaction_setBufferAlpha(ASurfaceTransaction* transaction,
*
* Available since API level 29.
*/
-void ASurfaceTransaction_setBufferDataSpace(ASurfaceTransaction* transaction,
- ASurfaceControl* surface_control, enum ADataSpace data_space)
- __INTRODUCED_IN(29);
+void ASurfaceTransaction_setBufferDataSpace(ASurfaceTransaction* _Nonnull transaction,
+ ASurfaceControl* _Nonnull surface_control,
+ enum ADataSpace data_space) __INTRODUCED_IN(29);
/**
* SMPTE ST 2086 "Mastering Display Color Volume" static metadata
@@ -509,9 +517,9 @@ void ASurfaceTransaction_setBufferDataSpace(ASurfaceTransaction* transaction,
*
* Available since API level 29.
*/
-void ASurfaceTransaction_setHdrMetadata_smpte2086(ASurfaceTransaction* transaction,
- ASurfaceControl* surface_control,
- struct AHdrMetadata_smpte2086* metadata)
+void ASurfaceTransaction_setHdrMetadata_smpte2086(ASurfaceTransaction* _Nonnull transaction,
+ ASurfaceControl* _Nonnull surface_control,
+ struct AHdrMetadata_smpte2086* _Nullable metadata)
__INTRODUCED_IN(29);
/**
@@ -522,9 +530,9 @@ void ASurfaceTransaction_setHdrMetadata_smpte2086(ASurfaceTransaction* transacti
*
* Available since API level 29.
*/
-void ASurfaceTransaction_setHdrMetadata_cta861_3(ASurfaceTransaction* transaction,
- ASurfaceControl* surface_control,
- struct AHdrMetadata_cta861_3* metadata)
+void ASurfaceTransaction_setHdrMetadata_cta861_3(ASurfaceTransaction* _Nonnull transaction,
+ ASurfaceControl* _Nonnull surface_control,
+ struct AHdrMetadata_cta861_3* _Nullable metadata)
__INTRODUCED_IN(29);
/**
@@ -569,10 +577,10 @@ void ASurfaceTransaction_setHdrMetadata_cta861_3(ASurfaceTransaction* transactio
*
* Available since API level 34.
*/
-void ASurfaceTransaction_setExtendedRangeBrightness(ASurfaceTransaction* transaction,
- ASurfaceControl* surface_control,
- float currentBufferRatio,
- float desiredRatio) __INTRODUCED_IN(__ANDROID_API_U__);
+void ASurfaceTransaction_setExtendedRangeBrightness(ASurfaceTransaction* _Nonnull transaction,
+ ASurfaceControl* _Nonnull surface_control,
+ float currentBufferRatio, float desiredRatio)
+ __INTRODUCED_IN(__ANDROID_API_U__);
/**
* Same as ASurfaceTransaction_setFrameRateWithChangeStrategy(transaction, surface_control,
@@ -582,8 +590,8 @@ void ASurfaceTransaction_setExtendedRangeBrightness(ASurfaceTransaction* transac
*
* Available since API level 30.
*/
-void ASurfaceTransaction_setFrameRate(ASurfaceTransaction* transaction,
- ASurfaceControl* surface_control, float frameRate,
+void ASurfaceTransaction_setFrameRate(ASurfaceTransaction* _Nonnull transaction,
+ ASurfaceControl* _Nonnull surface_control, float frameRate,
int8_t compatibility) __INTRODUCED_IN(30);
/**
@@ -618,10 +626,11 @@ void ASurfaceTransaction_setFrameRate(ASurfaceTransaction* transaction,
*
* Available since API level 31.
*/
-void ASurfaceTransaction_setFrameRateWithChangeStrategy(ASurfaceTransaction* transaction,
- ASurfaceControl* surface_control, float frameRate,
- int8_t compatibility, int8_t changeFrameRateStrategy)
- __INTRODUCED_IN(31);
+void ASurfaceTransaction_setFrameRateWithChangeStrategy(ASurfaceTransaction* _Nonnull transaction,
+ ASurfaceControl* _Nonnull surface_control,
+ float frameRate, int8_t compatibility,
+ int8_t changeFrameRateStrategy)
+ __INTRODUCED_IN(31);
/**
* Clears the frame rate which is set for \a surface_control.
@@ -644,8 +653,8 @@ void ASurfaceTransaction_setFrameRateWithChangeStrategy(ASurfaceTransaction* tra
*
* Available since API level 34.
*/
-void ASurfaceTransaction_clearFrameRate(ASurfaceTransaction* transaction,
- ASurfaceControl* surface_control)
+void ASurfaceTransaction_clearFrameRate(ASurfaceTransaction* _Nonnull transaction,
+ ASurfaceControl* _Nonnull surface_control)
__INTRODUCED_IN(__ANDROID_API_U__);
/**
@@ -674,10 +683,9 @@ void ASurfaceTransaction_clearFrameRate(ASurfaceTransaction* transaction,
* \param surface_control The ASurfaceControl on which to control buffer backpressure behavior.
* \param enableBackPressure Whether to enable back pressure.
*/
-void ASurfaceTransaction_setEnableBackPressure(ASurfaceTransaction* transaction,
- ASurfaceControl* surface_control,
- bool enableBackPressure)
- __INTRODUCED_IN(31);
+void ASurfaceTransaction_setEnableBackPressure(ASurfaceTransaction* _Nonnull transaction,
+ ASurfaceControl* _Nonnull surface_control,
+ bool enableBackPressure) __INTRODUCED_IN(31);
/**
* Sets the frame timeline to use in SurfaceFlinger.
@@ -697,7 +705,7 @@ void ASurfaceTransaction_setEnableBackPressure(ASurfaceTransaction* transaction,
* to the corresponding expected presentation time and deadline from the frame to be rendered. A
* stale or invalid value will be ignored.
*/
-void ASurfaceTransaction_setFrameTimeline(ASurfaceTransaction* transaction,
+void ASurfaceTransaction_setFrameTimeline(ASurfaceTransaction* _Nonnull transaction,
AVsyncId vsyncId) __INTRODUCED_IN(33);
__END_DECLS
diff --git a/services/inputflinger/BlockingQueue.h b/include/input/BlockingQueue.h
index f848c82c42..f848c82c42 100644
--- a/services/inputflinger/BlockingQueue.h
+++ b/include/input/BlockingQueue.h
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 57a48d7e92..090e35bc37 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -446,7 +446,7 @@ cc_library_host_shared {
},
}
-cc_library_static {
+cc_library {
name: "libbinder_rpc_no_kernel",
vendor_available: true,
defaults: [
@@ -458,7 +458,7 @@ cc_library_static {
],
}
-cc_library_static {
+cc_library {
name: "libbinder_rpc_no_blob",
vendor_available: true,
defaults: [
@@ -474,7 +474,7 @@ cc_library_static {
],
}
-cc_library_static {
+cc_library {
name: "libbinder_rpc_no_native_handle",
vendor_available: true,
defaults: [
@@ -490,7 +490,7 @@ cc_library_static {
],
}
-cc_library_static {
+cc_library {
name: "libbinder_rpc_single_threaded",
defaults: [
"libbinder_common_defaults",
@@ -505,7 +505,7 @@ cc_library_static {
],
}
-cc_library_static {
+cc_library {
name: "libbinder_rpc_single_threaded_no_kernel",
defaults: [
"libbinder_common_defaults",
diff --git a/libs/binder/liblog_stub/include/log/log.h b/libs/binder/liblog_stub/include/log/log.h
index 91c9632c1b..dad0020ace 100644
--- a/libs/binder/liblog_stub/include/log/log.h
+++ b/libs/binder/liblog_stub/include/log/log.h
@@ -54,16 +54,16 @@ int __android_log_print(int prio, const char* tag, const char* fmt, ...)
#define IF_ALOGW() IF_ALOG(LOG_WARN, LOG_TAG)
#define IF_ALOGE() IF_ALOG(LOG_ERROR, LOG_TAG)
-#define ALOG(priority, tag, fmt, ...) \
- do { \
- if (false)[[/*VERY*/ unlikely]] { /* ignore unused __VA_ARGS__ */ \
- std::fprintf(stderr, fmt __VA_OPT__(, ) __VA_ARGS__); \
- } \
- IF_ALOG(priority, tag) { \
- __android_log_print(ANDROID_##priority, tag, \
- tag ": " fmt "\n" __VA_OPT__(, ) __VA_ARGS__); \
- } \
- if constexpr (ANDROID_##priority == ANDROID_LOG_FATAL) std::abort(); \
+#define ALOG(priority, tag, fmt, ...) \
+ do { \
+ if (false)[[/*VERY*/ unlikely]] { /* ignore unused __VA_ARGS__ */ \
+ std::fprintf(stderr, fmt __VA_OPT__(, ) __VA_ARGS__); \
+ } \
+ IF_ALOG(priority, tag) { \
+ __android_log_print(ANDROID_##priority, tag, "%s: " fmt "\n", \
+ (tag)__VA_OPT__(, ) __VA_ARGS__); \
+ } \
+ if constexpr (ANDROID_##priority == ANDROID_LOG_FATAL) std::abort(); \
} while (false)
#define ALOGV(...) ALOG(LOG_VERBOSE, LOG_TAG, __VA_ARGS__)
#define ALOGD(...) ALOG(LOG_DEBUG, LOG_TAG, __VA_ARGS__)
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index b1ab7b0f9a..2929bce897 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -718,9 +718,17 @@ binder_status_t AIBinder_getExtension(AIBinder* binder, AIBinder** outExt) __INT
* When registering the interface, add:
* std::shared_ptr<MyFoo> foo = new MyFoo; // class in AOSP codebase
* std::shared_ptr<MyBar> bar = new MyBar; // custom extension class
- * ... = AIBinder_setExtension(foo->asBinder().get(), bar->asBinder().get());
+ * SpAIBinder binder = foo->asBinder(); // target binder to extend
+ * ... = AIBinder_setExtension(binder.get(), bar->asBinder().get());
+ * ... = AServiceManager_addService(binder.get(), instanceName);
* // handle error
*
+ * Do not use foo->asBinder().get() as the target binder argument to
+ * AIBinder_setExtensions because asBinder it creates a new binder
+ * object that will be destroyed after the function is called. The same
+ * binder object must be used for AIBinder_setExtension and
+ * AServiceManager_addService to register the service with an extension.
+ *
* Then, clients of IFoo can get this extension:
* SpAIBinder binder = ...;
* std::shared_ptr<IFoo> foo = IFoo::fromBinder(binder); // handle if null
diff --git a/libs/binder/ndk/include_platform/android/binder_manager.h b/libs/binder/ndk/include_platform/android/binder_manager.h
index c665ad82ad..52edae4a38 100644
--- a/libs/binder/ndk/include_platform/android/binder_manager.h
+++ b/libs/binder/ndk/include_platform/android/binder_manager.h
@@ -18,11 +18,8 @@
#include <android/binder_ibinder.h>
#include <android/binder_status.h>
-#include <sys/cdefs.h>
-
-#ifndef __TRUSTY__
#include <android/llndk-versioning.h>
-#endif
+#include <sys/cdefs.h>
__BEGIN_DECLS
diff --git a/libs/binder/rust/binder_tokio/lib.rs b/libs/binder/rust/binder_tokio/lib.rs
index 1dc0b2471d..71bb95bc0e 100644
--- a/libs/binder/rust/binder_tokio/lib.rs
+++ b/libs/binder/rust/binder_tokio/lib.rs
@@ -34,6 +34,7 @@ use std::future::Future;
/// Retrieve an existing service for a particular interface, sleeping for a few
/// seconds if it doesn't yet exist.
+#[deprecated = "this polls 5s, use wait_for_interface or check_interface"]
pub async fn get_interface<T: FromIBinder + ?Sized + 'static>(
name: &str,
) -> Result<Strong<T>, StatusCode> {
@@ -56,6 +57,32 @@ pub async fn get_interface<T: FromIBinder + ?Sized + 'static>(
}
}
+/// Retrieve an existing service for a particular interface. Returns
+/// `Err(StatusCode::NAME_NOT_FOUND)` immediately if the service is not available.
+///
+/// NOTE: "immediately" above does not mean the future will complete the first time it is polled.
+pub async fn check_interface<T: FromIBinder + ?Sized + 'static>(
+ name: &str,
+) -> Result<Strong<T>, StatusCode> {
+ if binder::is_handling_transaction() {
+ // See comment in the BinderAsyncPool impl.
+ return binder::check_interface::<T>(name);
+ }
+
+ let name = name.to_string();
+ let res = tokio::task::spawn_blocking(move || binder::check_interface::<T>(&name)).await;
+
+ // The `is_panic` branch is not actually reachable in Android as we compile
+ // with `panic = abort`.
+ match res {
+ Ok(Ok(service)) => Ok(service),
+ Ok(Err(err)) => Err(err),
+ Err(e) if e.is_panic() => std::panic::resume_unwind(e.into_panic()),
+ Err(e) if e.is_cancelled() => Err(StatusCode::FAILED_TRANSACTION),
+ Err(_) => Err(StatusCode::UNKNOWN_ERROR),
+ }
+}
+
/// Retrieve an existing service for a particular interface, or start it if it
/// is configured as a dynamic service and isn't yet started.
pub async fn wait_for_interface<T: FromIBinder + ?Sized + 'static>(
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs
index 0f9c58c0a2..e70f4f0232 100644
--- a/libs/binder/rust/src/lib.rs
+++ b/libs/binder/rust/src/lib.rs
@@ -114,9 +114,9 @@ pub use parcel::{ParcelFileDescriptor, Parcelable, ParcelableHolder};
pub use proxy::{DeathRecipient, SpIBinder, WpIBinder};
#[cfg(not(trusty))]
pub use service::{
- add_service, force_lazy_services_persist, get_declared_instances, get_interface, get_service,
- is_declared, is_handling_transaction, register_lazy_service, wait_for_interface,
- wait_for_service, LazyServiceGuard,
+ add_service, check_interface, check_service, force_lazy_services_persist,
+ get_declared_instances, get_interface, get_service, is_declared, is_handling_transaction,
+ register_lazy_service, wait_for_interface, wait_for_service, LazyServiceGuard,
};
#[cfg(not(trusty))]
pub use state::{ProcessState, ThreadState};
diff --git a/libs/binder/rust/src/service.rs b/libs/binder/rust/src/service.rs
index 3ca3b540c4..29dd8e1f58 100644
--- a/libs/binder/rust/src/service.rs
+++ b/libs/binder/rust/src/service.rs
@@ -144,6 +144,7 @@ fn interface_cast<T: FromIBinder + ?Sized>(service: Option<SpIBinder>) -> Result
/// Retrieve an existing service, blocking for a few seconds if it doesn't yet
/// exist.
+#[deprecated = "this polls 5s, use wait_for_service or check_service"]
pub fn get_service(name: &str) -> Option<SpIBinder> {
let name = CString::new(name).ok()?;
// Safety: `AServiceManager_getService` returns either a null pointer or a
@@ -152,6 +153,15 @@ pub fn get_service(name: &str) -> Option<SpIBinder> {
unsafe { SpIBinder::from_raw(sys::AServiceManager_getService(name.as_ptr())) }
}
+/// Retrieve an existing service. Returns `None` immediately if the service is not available.
+pub fn check_service(name: &str) -> Option<SpIBinder> {
+ let name = CString::new(name).ok()?;
+ // Safety: `AServiceManager_checkService` returns either a null pointer or
+ // a valid pointer to an owned `AIBinder`. Either of these values is safe to
+ // pass to `SpIBinder::from_raw`.
+ unsafe { SpIBinder::from_raw(sys::AServiceManager_checkService(name.as_ptr())) }
+}
+
/// Retrieve an existing service, or start it if it is configured as a dynamic
/// service and isn't yet started.
pub fn wait_for_service(name: &str) -> Option<SpIBinder> {
@@ -164,10 +174,17 @@ pub fn wait_for_service(name: &str) -> Option<SpIBinder> {
/// Retrieve an existing service for a particular interface, blocking for a few
/// seconds if it doesn't yet exist.
+#[deprecated = "this polls 5s, use wait_for_interface or check_interface"]
pub fn get_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> {
interface_cast(get_service(name))
}
+/// Retrieve an existing service for a particular interface. Returns
+/// `Err(StatusCode::NAME_NOT_FOUND)` immediately if the service is not available.
+pub fn check_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> {
+ interface_cast(check_service(name))
+}
+
/// Retrieve an existing service for a particular interface, or start it if it
/// is configured as a dynamic service and isn't yet started.
pub fn wait_for_interface<T: FromIBinder + ?Sized>(name: &str) -> Result<Strong<T>> {
diff --git a/libs/binder/rust/tests/integration.rs b/libs/binder/rust/tests/integration.rs
index c87fa89756..15ae56fdd7 100644
--- a/libs/binder/rust/tests/integration.rs
+++ b/libs/binder/rust/tests/integration.rs
@@ -421,7 +421,7 @@ mod tests {
}
#[test]
- fn check_services() {
+ fn check_get_service() {
let mut sm = binder::get_service("manager").expect("Did not get manager binder service");
assert!(sm.is_binder_alive());
assert!(sm.ping_binder().is_ok());
@@ -445,7 +445,7 @@ mod tests {
}
#[tokio::test]
- async fn check_services_async() {
+ async fn check_get_service_async() {
let mut sm = binder::get_service("manager").expect("Did not get manager binder service");
assert!(sm.is_binder_alive());
assert!(sm.ping_binder().is_ok());
@@ -474,6 +474,62 @@ mod tests {
}
#[test]
+ fn check_check_service() {
+ let mut sm = binder::check_service("manager").expect("Did not find manager binder service");
+ assert!(sm.is_binder_alive());
+ assert!(sm.ping_binder().is_ok());
+
+ assert!(binder::check_service("this_service_does_not_exist").is_none());
+ assert_eq!(
+ binder::check_interface::<dyn ITest>("this_service_does_not_exist").err(),
+ Some(StatusCode::NAME_NOT_FOUND)
+ );
+ assert_eq!(
+ binder::check_interface::<dyn IATest<Tokio>>("this_service_does_not_exist").err(),
+ Some(StatusCode::NAME_NOT_FOUND)
+ );
+
+ // The service manager service isn't an ITest, so this must fail.
+ assert_eq!(
+ binder::check_interface::<dyn ITest>("manager").err(),
+ Some(StatusCode::BAD_TYPE)
+ );
+ assert_eq!(
+ binder::check_interface::<dyn IATest<Tokio>>("manager").err(),
+ Some(StatusCode::BAD_TYPE)
+ );
+ }
+
+ #[tokio::test]
+ async fn check_check_service_async() {
+ let mut sm = binder::check_service("manager").expect("Did not find manager binder service");
+ assert!(sm.is_binder_alive());
+ assert!(sm.ping_binder().is_ok());
+
+ assert!(binder::check_service("this_service_does_not_exist").is_none());
+ assert_eq!(
+ binder_tokio::check_interface::<dyn ITest>("this_service_does_not_exist").await.err(),
+ Some(StatusCode::NAME_NOT_FOUND)
+ );
+ assert_eq!(
+ binder_tokio::check_interface::<dyn IATest<Tokio>>("this_service_does_not_exist")
+ .await
+ .err(),
+ Some(StatusCode::NAME_NOT_FOUND)
+ );
+
+ // The service manager service isn't an ITest, so this must fail.
+ assert_eq!(
+ binder_tokio::check_interface::<dyn ITest>("manager").await.err(),
+ Some(StatusCode::BAD_TYPE)
+ );
+ assert_eq!(
+ binder_tokio::check_interface::<dyn IATest<Tokio>>("manager").await.err(),
+ Some(StatusCode::BAD_TYPE)
+ );
+ }
+
+ #[test]
fn check_wait_for_service() {
let mut sm =
binder::wait_for_service("manager").expect("Did not get manager binder service");
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 35002eb3c5..6800a8d36c 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -200,9 +200,11 @@ cc_library_static {
defaults: [
"binder_test_defaults",
],
+ header_libs: [
+ "libbinder_headers_base",
+ ],
shared_libs: [
"libbase",
- "liblog",
],
srcs: [
"FileUtils.cpp",
diff --git a/libs/binder/tests/binderThroughputTest.cpp b/libs/binder/tests/binderThroughputTest.cpp
index 10912c7363..f912348689 100644
--- a/libs/binder/tests/binderThroughputTest.cpp
+++ b/libs/binder/tests/binderThroughputTest.cpp
@@ -7,9 +7,10 @@
#include <cstdlib>
#include <cstdio>
+#include <fstream>
#include <iostream>
-#include <vector>
#include <tuple>
+#include <vector>
#include <unistd.h>
#include <sys/wait.h>
@@ -63,6 +64,18 @@ struct ProcResults {
uint64_t worst() {
return *max_element(data.begin(), data.end());
}
+ void dump_to_file(string filename) {
+ ofstream output;
+ output.open(filename);
+ if (!output.is_open()) {
+ cerr << "Failed to open '" << filename << "'." << endl;
+ exit(EXIT_FAILURE);
+ }
+ for (uint64_t value : data) {
+ output << value << "\n";
+ }
+ output.close();
+ }
void dump() {
if (data.size() == 0) {
// This avoids index-out-of-bounds below.
@@ -293,12 +306,8 @@ void signal_all(vector<Pipe>& v)
}
}
-void run_main(int iterations,
- int workers,
- int payload_size,
- int cs_pair,
- bool training_round=false)
-{
+void run_main(int iterations, int workers, int payload_size, int cs_pair,
+ bool training_round = false, bool dump_to_file = false, string dump_filename = "") {
vector<Pipe> pipes;
// Create all the workers and wait for them to spawn.
for (int i = 0; i < workers; i++) {
@@ -349,6 +358,9 @@ void run_main(int iterations,
warn_latency = 2 * tot_results.worst();
cout << "Max latency during training: " << tot_results.worst() / 1.0E6 << "ms" << endl;
} else {
+ if (dump_to_file) {
+ tot_results.dump_to_file(dump_filename);
+ }
tot_results.dump();
}
}
@@ -361,6 +373,8 @@ int main(int argc, char *argv[])
bool cs_pair = false;
bool training_round = false;
int max_time_us;
+ bool dump_to_file = false;
+ string dump_filename;
// Parse arguments.
for (int i = 1; i < argc; i++) {
@@ -372,6 +386,7 @@ int main(int argc, char *argv[])
cout << "\t-s N : Specify payload size." << endl;
cout << "\t-t : Run training round." << endl;
cout << "\t-w N : Specify total number of workers." << endl;
+ cout << "\t-d FILE : Dump raw data to file." << endl;
return 0;
}
if (string(argv[i]) == "-w") {
@@ -430,14 +445,24 @@ int main(int argc, char *argv[])
i++;
continue;
}
+ if (string(argv[i]) == "-d") {
+ if (i + 1 == argc) {
+ cout << "-d requires an argument\n" << endl;
+ exit(EXIT_FAILURE);
+ }
+ dump_to_file = true;
+ dump_filename = argv[i + 1];
+ i++;
+ continue;
+ }
}
if (training_round) {
cout << "Start training round" << endl;
- run_main(iterations, workers, payload_size, cs_pair, training_round=true);
+ run_main(iterations, workers, payload_size, cs_pair, true);
cout << "Completed training round" << endl << endl;
}
- run_main(iterations, workers, payload_size, cs_pair);
+ run_main(iterations, workers, payload_size, cs_pair, false, dump_to_file, dump_filename);
return 0;
}
diff --git a/libs/binder/trusty/ndk/include/android/llndk-versioning.h b/libs/binder/trusty/ndk/include/android/llndk-versioning.h
new file mode 100644
index 0000000000..3ae3d8f577
--- /dev/null
+++ b/libs/binder/trusty/ndk/include/android/llndk-versioning.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#define __INTRODUCED_IN_LLNDK(x) /* nothing on Trusty */
diff --git a/libs/binder/trusty/ndk/include/sys/cdefs.h b/libs/binder/trusty/ndk/include/sys/cdefs.h
index 7528f2bb45..4e9b0e83c6 100644
--- a/libs/binder/trusty/ndk/include/sys/cdefs.h
+++ b/libs/binder/trusty/ndk/include/sys/cdefs.h
@@ -27,4 +27,3 @@
#endif
#define __INTRODUCED_IN(x) /* nothing on Trusty */
-#define __INTRODUCED_IN_LLNDK(x) /* nothing on Trusty */
diff --git a/libs/binder/trusty/rust/binder_rpc_test/binder_rpc_test_session/lib.rs b/libs/binder/trusty/rust/binder_rpc_test/binder_rpc_test_session/lib.rs
new file mode 100644
index 0000000000..22cba44975
--- /dev/null
+++ b/libs/binder/trusty/rust/binder_rpc_test/binder_rpc_test_session/lib.rs
@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2023 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.
+ */
+
+use binder::{Interface, ParcelFileDescriptor, SpIBinder, Status, StatusCode, Strong};
+use binder_rpc_test_aidl::aidl::IBinderRpcCallback::IBinderRpcCallback;
+use binder_rpc_test_aidl::aidl::IBinderRpcSession::IBinderRpcSession;
+use binder_rpc_test_aidl::aidl::IBinderRpcTest::IBinderRpcTest;
+use std::sync::Mutex;
+
+static G_NUM: Mutex<i32> = Mutex::new(0);
+
+#[derive(Debug, Default)]
+pub struct MyBinderRpcSession {
+ name: String,
+}
+
+impl MyBinderRpcSession {
+ pub fn new(name: &str) -> Self {
+ Self::increment_instance_count();
+ Self { name: name.to_string() }
+ }
+
+ pub fn get_instance_count() -> i32 {
+ *G_NUM.lock().unwrap()
+ }
+
+ fn increment_instance_count() {
+ *G_NUM.lock().unwrap() += 1;
+ }
+
+ fn decrement_instance_count() {
+ *G_NUM.lock().unwrap() -= 1;
+ }
+}
+
+impl Drop for MyBinderRpcSession {
+ fn drop(&mut self) {
+ MyBinderRpcSession::decrement_instance_count();
+ }
+}
+
+impl Interface for MyBinderRpcSession {}
+
+impl IBinderRpcSession for MyBinderRpcSession {
+ fn getName(&self) -> Result<String, Status> {
+ Ok(self.name.clone())
+ }
+}
+
+impl IBinderRpcTest for MyBinderRpcSession {
+ fn sendString(&self, _: &str) -> Result<(), Status> {
+ todo!()
+ }
+ fn doubleString(&self, _s: &str) -> Result<String, Status> {
+ todo!()
+ }
+ fn getClientPort(&self) -> Result<i32, Status> {
+ todo!()
+ }
+ fn countBinders(&self) -> Result<Vec<i32>, Status> {
+ todo!()
+ }
+ fn getNullBinder(&self) -> Result<SpIBinder, Status> {
+ todo!()
+ }
+ fn pingMe(&self, _binder: &SpIBinder) -> Result<i32, Status> {
+ todo!()
+ }
+ fn repeatBinder(&self, _binder: Option<&SpIBinder>) -> Result<Option<SpIBinder>, Status> {
+ todo!()
+ }
+ fn holdBinder(&self, _binder: Option<&SpIBinder>) -> Result<(), Status> {
+ todo!()
+ }
+ fn getHeldBinder(&self) -> Result<Option<SpIBinder>, Status> {
+ todo!()
+ }
+ fn nestMe(
+ &self,
+ binder: &Strong<(dyn IBinderRpcTest + 'static)>,
+ count: i32,
+ ) -> Result<(), Status> {
+ if count < 0 {
+ Ok(())
+ } else {
+ binder.nestMe(binder, count - 1)
+ }
+ }
+ fn alwaysGiveMeTheSameBinder(&self) -> Result<SpIBinder, Status> {
+ todo!()
+ }
+ fn openSession(
+ &self,
+ _name: &str,
+ ) -> Result<Strong<(dyn IBinderRpcSession + 'static)>, Status> {
+ todo!()
+ }
+ fn getNumOpenSessions(&self) -> Result<i32, Status> {
+ todo!()
+ }
+ fn lock(&self) -> Result<(), Status> {
+ todo!()
+ }
+ fn unlockInMsAsync(&self, _: i32) -> Result<(), Status> {
+ todo!()
+ }
+ fn lockUnlock(&self) -> Result<(), Status> {
+ todo!()
+ }
+ fn sleepMs(&self, _: i32) -> Result<(), Status> {
+ todo!()
+ }
+ fn sleepMsAsync(&self, _: i32) -> Result<(), Status> {
+ todo!()
+ }
+ fn doCallback(
+ &self,
+ _: &Strong<(dyn IBinderRpcCallback + 'static)>,
+ _: bool,
+ _: bool,
+ _: &str,
+ ) -> Result<(), Status> {
+ todo!()
+ }
+ fn doCallbackAsync(
+ &self,
+ _: &Strong<(dyn IBinderRpcCallback + 'static)>,
+ _: bool,
+ _: bool,
+ _: &str,
+ ) -> Result<(), Status> {
+ todo!()
+ }
+ fn die(&self, _: bool) -> Result<(), Status> {
+ Err(Status::from(StatusCode::UNKNOWN_TRANSACTION))
+ }
+ fn scheduleShutdown(&self) -> Result<(), Status> {
+ todo!()
+ }
+ fn useKernelBinderCallingId(&self) -> Result<(), Status> {
+ todo!()
+ }
+ fn echoAsFile(&self, _: &str) -> Result<ParcelFileDescriptor, Status> {
+ todo!()
+ }
+ fn concatFiles(&self, _: &[ParcelFileDescriptor]) -> Result<ParcelFileDescriptor, Status> {
+ todo!()
+ }
+ fn blockingSendFdOneway(&self, _: &ParcelFileDescriptor) -> Result<(), Status> {
+ todo!()
+ }
+ fn blockingRecvFd(&self) -> Result<ParcelFileDescriptor, Status> {
+ todo!()
+ }
+ fn blockingSendIntOneway(&self, _: i32) -> Result<(), Status> {
+ todo!()
+ }
+ fn blockingRecvInt(&self) -> Result<i32, Status> {
+ todo!()
+ }
+}
diff --git a/libs/binder/trusty/rust/binder_rpc_test/binder_rpc_test_session/rules.mk b/libs/binder/trusty/rust/binder_rpc_test/binder_rpc_test_session/rules.mk
new file mode 100644
index 0000000000..ae26355521
--- /dev/null
+++ b/libs/binder/trusty/rust/binder_rpc_test/binder_rpc_test_session/rules.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2023 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.
+#
+
+LOCAL_DIR := $(GET_LOCAL_DIR)
+LIBBINDER_DIR := $(LOCAL_DIR)/../../../..
+
+MODULE := $(LOCAL_DIR)
+
+MODULE_SRCS := $(LOCAL_DIR)/lib.rs
+
+MODULE_CRATE_NAME := binder_rpc_test_session
+
+MODULE_LIBRARY_DEPS += \
+ $(LIBBINDER_DIR)/trusty/rust \
+ $(LIBBINDER_DIR)/trusty/rust/rpcbinder \
+ $(LOCAL_DIR)/../aidl \
+ $(call FIND_CRATE,log) \
+ trusty/user/base/lib/trusty-std \
+
+include make/library.mk
diff --git a/libs/binder/trusty/rust/binder_rpc_test/main.rs b/libs/binder/trusty/rust/binder_rpc_test/main.rs
index 3c1e784418..baea5a827b 100644
--- a/libs/binder/trusty/rust/binder_rpc_test/main.rs
+++ b/libs/binder/trusty/rust/binder_rpc_test/main.rs
@@ -15,8 +15,11 @@
*/
#![cfg(test)]
-use binder::{IBinder, Strong};
-use binder_rpc_test_aidl::aidl::IBinderRpcTest::IBinderRpcTest;
+use binder::{BinderFeatures, IBinder, Status, StatusCode, Strong};
+use binder_rpc_test_aidl::aidl::IBinderRpcSession::{BnBinderRpcSession, IBinderRpcSession};
+use binder_rpc_test_aidl::aidl::IBinderRpcTest::{BnBinderRpcTest, IBinderRpcTest};
+use binder_rpc_test_session::MyBinderRpcSession;
+use libc::{clock_gettime, CLOCK_REALTIME};
use rpcbinder::RpcSession;
use trusty_std::ffi::{CString, FallibleCString};
@@ -25,19 +28,190 @@ test::init!();
const SERVICE_PORT: &str = "com.android.trusty.binderRpcTestService.V1";
const RUST_SERVICE_PORT: &str = "com.android.trusty.rust.binderRpcTestService.V1";
+macro_rules! service_test {
+ ($c_name:ident, $rust_name:ident, $body:expr) => {
+ #[test]
+ fn $c_name() {
+ $body(get_service(SERVICE_PORT))
+ }
+ #[test]
+ fn $rust_name() {
+ $body(get_service(RUST_SERVICE_PORT))
+ }
+ };
+}
+
fn get_service(port: &str) -> Strong<dyn IBinderRpcTest> {
let port = CString::try_new(port).expect("Failed to allocate port name");
RpcSession::new().setup_trusty_client(port.as_c_str()).expect("Failed to create session")
}
-#[test]
-fn ping() {
- let srv = get_service(SERVICE_PORT);
- assert_eq!(srv.as_binder().ping_binder(), Ok(()));
+fn expect_sessions(expected: i32, srv: &Strong<dyn IBinderRpcTest>) {
+ let count = srv.getNumOpenSessions();
+ assert!(count.is_ok());
+ assert_eq!(expected, count.unwrap());
}
-#[test]
-fn ping_rust() {
- let srv = get_service(RUST_SERVICE_PORT);
- assert_eq!(srv.as_binder().ping_binder(), Ok(()));
+fn get_time_ns() -> u64 {
+ let mut ts = libc::timespec { tv_sec: 0, tv_nsec: 0 };
+
+ // Safety: Passing valid pointer to variable ts which lives past end of call
+ assert_eq!(unsafe { clock_gettime(CLOCK_REALTIME, &mut ts) }, 0);
+
+ ts.tv_sec as u64 * 1_000_000_000u64 + ts.tv_nsec as u64
}
+
+fn get_time_ms() -> u64 {
+ get_time_ns() / 1_000_000u64
+}
+
+// ----------
+
+service_test! {ping, ping_rust, |srv: Strong<dyn IBinderRpcTest>| {
+ assert_eq!(srv.as_binder().ping_binder(), Ok(()));
+}}
+
+service_test! {send_something_oneway, send_something_oneway_rust, |srv: Strong<dyn IBinderRpcTest>| {
+ assert_eq!(srv.sendString("Foo"), Ok(()));
+}}
+
+service_test! {send_and_get_result_back, send_and_get_result_back_rust, |srv: Strong<dyn IBinderRpcTest>| {
+ assert_eq!(srv.doubleString("Foo"), Ok(String::from("FooFoo")));
+}}
+
+service_test! {send_and_get_result_back_big, send_and_get_result_back_big_rust, |srv: Strong<dyn IBinderRpcTest>| {
+ let single_len = 512;
+ let single = "a".repeat(single_len);
+ assert_eq!(srv.doubleString(&single), Ok(String::from(single.clone() + &single)));
+}}
+
+service_test! {invalid_null_binder_return, invalid_null_binder_return_rust, |srv: Strong<dyn IBinderRpcTest>| {
+ let binder = srv.getNullBinder();
+ assert!(binder == Err(Status::from(StatusCode::UNEXPECTED_NULL)) || binder == Err(Status::from(StatusCode::UNKNOWN_TRANSACTION)));
+}}
+
+service_test! {call_me_back, call_me_back_rust, |srv: Strong<dyn IBinderRpcTest>| {
+ let binder =
+ BnBinderRpcSession::new_binder(MyBinderRpcSession::new("Foo"), BinderFeatures::default())
+ .as_binder();
+ let result = srv.pingMe(&binder);
+ assert_eq!(result, Ok(0));
+}}
+
+service_test! {repeat_binder, repeat_binder_rust, |srv: Strong<dyn IBinderRpcTest>| {
+ let in_binder =
+ BnBinderRpcSession::new_binder(MyBinderRpcSession::new("Foo"), BinderFeatures::default())
+ .as_binder();
+ let result = srv.repeatBinder(Some(&in_binder));
+ assert_eq!(result.unwrap().unwrap(), in_binder);
+}}
+
+service_test! {repeat_their_binder, repeat_their_binder_rust, |srv: Strong<dyn IBinderRpcTest>| {
+ let session = srv.openSession("Test");
+ assert!(session.is_ok());
+
+ let in_binder = session.unwrap().as_binder();
+ let out_binder = srv.repeatBinder(Some(&in_binder));
+ assert_eq!(out_binder.unwrap().unwrap(), in_binder);
+}}
+
+service_test! {hold_binder, hold_binder_rust, |srv: Strong<dyn IBinderRpcTest>| {
+ let name = "Foo";
+
+ let binder =
+ BnBinderRpcSession::new_binder(MyBinderRpcSession::new(name), BinderFeatures::default())
+ .as_binder();
+ assert!(srv.holdBinder(Some(&binder)).is_ok());
+
+ let held = srv.getHeldBinder();
+ assert!(held.is_ok());
+ let held = held.unwrap();
+ assert!(held.is_some());
+ let held = held.unwrap();
+ assert_eq!(binder, held);
+
+ let session = held.into_interface::<dyn IBinderRpcSession>();
+ assert!(session.is_ok());
+
+ let session_name = session.unwrap().getName();
+ assert!(session_name.is_ok());
+ let session_name = session_name.unwrap();
+ assert_eq!(session_name, name);
+
+ assert!(srv.holdBinder(None).is_ok());
+}}
+
+service_test! {nested_transactions, nested_transactions_rust, |srv: Strong<dyn IBinderRpcTest>| {
+ let binder =
+ BnBinderRpcTest::new_binder(MyBinderRpcSession::new("Nest"), BinderFeatures::default());
+ assert!(srv.nestMe(&binder, 10).is_ok());
+}}
+
+service_test! {same_binder_equality, same_binder_equality_rust, |srv: Strong<dyn IBinderRpcTest>| {
+ let a = srv.alwaysGiveMeTheSameBinder();
+ assert!(a.is_ok());
+
+ let b = srv.alwaysGiveMeTheSameBinder();
+ assert!(b.is_ok());
+
+ assert_eq!(a.unwrap(), b.unwrap());
+}}
+
+service_test! {single_session, single_session_rust, |srv: Strong<dyn IBinderRpcTest>| {
+ let session = srv.openSession("aoeu");
+ assert!(session.is_ok());
+ let session = session.unwrap();
+ let name = session.getName();
+ assert!(name.is_ok());
+ assert_eq!(name.unwrap(), "aoeu");
+
+ let count = srv.getNumOpenSessions();
+ assert!(count.is_ok());
+ assert_eq!(count.unwrap(), 1);
+
+ drop(session);
+ let count = srv.getNumOpenSessions();
+ assert!(count.is_ok());
+ assert_eq!(count.unwrap(), 0);
+}}
+
+service_test! {many_session, many_session_rust, |srv: Strong<dyn IBinderRpcTest>| {
+ let mut sessions = Vec::new();
+
+ for i in 0..15 {
+ expect_sessions(i, &srv);
+
+ let session = srv.openSession(&(i.to_string()));
+ assert!(session.is_ok());
+ sessions.push(session.unwrap());
+ }
+
+ expect_sessions(sessions.len() as i32, &srv);
+
+ for i in 0..sessions.len() {
+ let name = sessions[i].getName();
+ assert!(name.is_ok());
+ assert_eq!(name.unwrap(), i.to_string());
+ }
+
+ expect_sessions(sessions.len() as i32, &srv);
+
+ while !sessions.is_empty() {
+ sessions.pop();
+
+ expect_sessions(sessions.len() as i32, &srv);
+ }
+
+ expect_sessions(0, &srv);
+}}
+
+service_test! {one_way_call_does_not_wait, one_way_call_does_not_wait_rust, |srv: Strong<dyn IBinderRpcTest>| {
+ let really_long_time_ms = 100;
+ let sleep_ms = really_long_time_ms * 5;
+
+ let before = get_time_ms();
+ let _ = srv.sleepMsAsync(sleep_ms);
+ let after = get_time_ms();
+
+ assert!(after < before + really_long_time_ms as u64);
+}}
diff --git a/libs/binder/trusty/rust/binder_rpc_test/manifest.json b/libs/binder/trusty/rust/binder_rpc_test/manifest.json
index c2ecaa4fe3..384ed441c6 100644
--- a/libs/binder/trusty/rust/binder_rpc_test/manifest.json
+++ b/libs/binder/trusty/rust/binder_rpc_test/manifest.json
@@ -1,7 +1,7 @@
{
"uuid": "91eed949-8a9e-4569-9c83-5935fb624025",
"app_name": "rust_binder_rpc_test",
- "min_heap": 16384,
+ "min_heap": 32768,
"min_stack": 16384,
"mgmt_flags": {
"non_critical_app": true
diff --git a/libs/binder/trusty/rust/binder_rpc_test/rules.mk b/libs/binder/trusty/rust/binder_rpc_test/rules.mk
index 192a1591ae..8347a359db 100644
--- a/libs/binder/trusty/rust/binder_rpc_test/rules.mk
+++ b/libs/binder/trusty/rust/binder_rpc_test/rules.mk
@@ -26,6 +26,8 @@ MODULE_LIBRARY_DEPS += \
$(LIBBINDER_DIR)/trusty/rust \
$(LIBBINDER_DIR)/trusty/rust/rpcbinder \
$(LOCAL_DIR)/aidl \
+ $(LOCAL_DIR)/binder_rpc_test_session \
+ $(call FIND_CRATE,log) \
trusty/user/base/lib/trusty-std \
MODULE_RUST_TESTS := true
diff --git a/libs/binder/trusty/rust/binder_rpc_test/service/main.rs b/libs/binder/trusty/rust/binder_rpc_test/service/main.rs
index b9a86bf240..c4a758a214 100644
--- a/libs/binder/trusty/rust/binder_rpc_test/service/main.rs
+++ b/libs/binder/trusty/rust/binder_rpc_test/service/main.rs
@@ -13,61 +13,126 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-use binder::{BinderFeatures, Interface, ParcelFileDescriptor, SpIBinder, Status, Strong};
+use binder::{
+ BinderFeatures, IBinder, Interface, ParcelFileDescriptor, SpIBinder, Status, StatusCode, Strong,
+};
use binder_rpc_test_aidl::aidl::IBinderRpcCallback::IBinderRpcCallback;
-use binder_rpc_test_aidl::aidl::IBinderRpcSession::IBinderRpcSession;
+use binder_rpc_test_aidl::aidl::IBinderRpcSession::{BnBinderRpcSession, IBinderRpcSession};
use binder_rpc_test_aidl::aidl::IBinderRpcTest::{BnBinderRpcTest, IBinderRpcTest};
+use binder_rpc_test_session::MyBinderRpcSession;
+use libc::{c_long, nanosleep, timespec};
use rpcbinder::RpcServer;
use std::rc::Rc;
+use std::sync::Mutex;
use tipc::{service_dispatcher, wrap_service, Manager, PortCfg};
const RUST_SERVICE_PORT: &str = "com.android.trusty.rust.binderRpcTestService.V1";
+// -----------------------------------------------------------------------------
+
+static SESSION_COUNT: Mutex<i32> = Mutex::new(0);
+static HOLD_BINDER: Mutex<Option<SpIBinder>> = Mutex::new(None);
+static SAME_BINDER: Mutex<Option<SpIBinder>> = Mutex::new(None);
+
#[derive(Debug, Default)]
-struct TestService;
+struct TestService {
+ port: i32,
+ name: String,
+}
+
+#[allow(dead_code)]
+impl TestService {
+ fn new(name: &str) -> Self {
+ *SESSION_COUNT.lock().unwrap() += 1;
+ Self { name: name.to_string(), ..Default::default() }
+ }
+
+ fn get_instance_count() -> i32 {
+ *SESSION_COUNT.lock().unwrap()
+ }
+}
+
+impl Drop for TestService {
+ fn drop(&mut self) {
+ *SESSION_COUNT.lock().unwrap() -= 1;
+ }
+}
impl Interface for TestService {}
+impl IBinderRpcSession for TestService {
+ fn getName(&self) -> Result<String, Status> {
+ Ok(self.name.clone())
+ }
+}
+
impl IBinderRpcTest for TestService {
fn sendString(&self, _: &str) -> Result<(), Status> {
- todo!()
+ // This is a oneway function, so caller returned immediately and gives back an Ok(()) regardless of what this returns
+ Ok(())
}
- fn doubleString(&self, _: &str) -> Result<String, Status> {
- todo!()
+ fn doubleString(&self, s: &str) -> Result<String, Status> {
+ let ss = [s, s].concat();
+ Ok(ss)
}
fn getClientPort(&self) -> Result<i32, Status> {
- todo!()
+ Ok(self.port)
}
fn countBinders(&self) -> Result<Vec<i32>, Status> {
todo!()
}
fn getNullBinder(&self) -> Result<SpIBinder, Status> {
- todo!()
+ Err(Status::from(StatusCode::UNKNOWN_TRANSACTION))
}
- fn pingMe(&self, _: &SpIBinder) -> Result<i32, Status> {
- todo!()
+ fn pingMe(&self, binder: &SpIBinder) -> Result<i32, Status> {
+ match binder.clone().ping_binder() {
+ Ok(()) => Ok(StatusCode::OK as i32),
+ Err(e) => Err(Status::from(e)),
+ }
}
- fn repeatBinder(&self, _: Option<&SpIBinder>) -> Result<Option<SpIBinder>, Status> {
- todo!()
+ fn repeatBinder(&self, binder: Option<&SpIBinder>) -> Result<Option<SpIBinder>, Status> {
+ match binder {
+ Some(x) => Ok(Some(x.clone())),
+ None => Err(Status::from(StatusCode::BAD_VALUE)),
+ }
}
- fn holdBinder(&self, _: Option<&SpIBinder>) -> Result<(), Status> {
- todo!()
+ fn holdBinder(&self, binder: Option<&SpIBinder>) -> Result<(), Status> {
+ *HOLD_BINDER.lock().unwrap() = binder.cloned();
+ Ok(())
}
fn getHeldBinder(&self) -> Result<Option<SpIBinder>, Status> {
- todo!()
+ Ok((*HOLD_BINDER.lock().unwrap()).clone())
}
- fn nestMe(&self, _: &Strong<(dyn IBinderRpcTest + 'static)>, _: i32) -> Result<(), Status> {
- todo!()
+ fn nestMe(
+ &self,
+ binder: &Strong<(dyn IBinderRpcTest + 'static)>,
+ count: i32,
+ ) -> Result<(), Status> {
+ if count < 0 {
+ Ok(())
+ } else {
+ binder.nestMe(binder, count - 1)
+ }
}
fn alwaysGiveMeTheSameBinder(&self) -> Result<SpIBinder, Status> {
- todo!()
- }
- fn openSession(&self, _: &str) -> Result<Strong<(dyn IBinderRpcSession + 'static)>, Status> {
- todo!()
+ let mut locked = SAME_BINDER.lock().unwrap();
+ Ok((*locked)
+ .get_or_insert_with(|| {
+ BnBinderRpcTest::new_binder(TestService::default(), BinderFeatures::default())
+ .as_binder()
+ })
+ .clone())
+ }
+ fn openSession(&self, name: &str) -> Result<Strong<(dyn IBinderRpcSession + 'static)>, Status> {
+ let s = BnBinderRpcSession::new_binder(
+ MyBinderRpcSession::new(name),
+ BinderFeatures::default(),
+ );
+ Ok(s)
}
fn getNumOpenSessions(&self) -> Result<i32, Status> {
- todo!()
+ let count = MyBinderRpcSession::get_instance_count();
+ Ok(count)
}
fn lock(&self) -> Result<(), Status> {
todo!()
@@ -78,11 +143,21 @@ impl IBinderRpcTest for TestService {
fn lockUnlock(&self) -> Result<(), Status> {
todo!()
}
- fn sleepMs(&self, _: i32) -> Result<(), Status> {
- todo!()
+ fn sleepMs(&self, ms: i32) -> Result<(), Status> {
+ let ts = timespec {
+ tv_sec: (ms / 1000) as c_long,
+ tv_nsec: (ms % 1000) as c_long * 1_000_000 as c_long,
+ };
+
+ let mut rem = timespec { tv_sec: 0, tv_nsec: 0 };
+
+ // Safety: Passing valid pointers to variables ts & rem which live past end of call
+ assert_eq!(unsafe { nanosleep(&ts, &mut rem) }, 0);
+
+ Ok(())
}
- fn sleepMsAsync(&self, _: i32) -> Result<(), Status> {
- todo!()
+ fn sleepMsAsync(&self, ms: i32) -> Result<(), Status> {
+ self.sleepMs(ms)
}
fn doCallback(
&self,
@@ -103,7 +178,7 @@ impl IBinderRpcTest for TestService {
todo!()
}
fn die(&self, _: bool) -> Result<(), Status> {
- todo!()
+ Err(Status::from(StatusCode::UNKNOWN_TRANSACTION))
}
fn scheduleShutdown(&self) -> Result<(), Status> {
todo!()
diff --git a/libs/binder/trusty/rust/binder_rpc_test/service/rules.mk b/libs/binder/trusty/rust/binder_rpc_test/service/rules.mk
index 1ddc382197..f71ee9bcbd 100644
--- a/libs/binder/trusty/rust/binder_rpc_test/service/rules.mk
+++ b/libs/binder/trusty/rust/binder_rpc_test/service/rules.mk
@@ -25,7 +25,10 @@ MODULE_CRATE_NAME := binder_rpc_test_service
MODULE_LIBRARY_DEPS += \
$(LIBBINDER_DIR)/trusty/rust \
$(LIBBINDER_DIR)/trusty/rust/rpcbinder \
+ $(LIBBINDER_DIR)/trusty/rust/binder_rpc_server \
$(LOCAL_DIR)/../aidl \
+ $(LOCAL_DIR)/../binder_rpc_test_session \
+ $(LOCAL_DIR)/.. \
trusty/user/base/lib/tipc/rust \
MANIFEST := $(LOCAL_DIR)/manifest.json
diff --git a/libs/binder/trusty/rust/rules.mk b/libs/binder/trusty/rust/rules.mk
index c5e671a4f5..36bd3a2e75 100644
--- a/libs/binder/trusty/rust/rules.mk
+++ b/libs/binder/trusty/rust/rules.mk
@@ -28,6 +28,7 @@ MODULE_LIBRARY_DEPS += \
$(LIBBINDER_DIR)/trusty/rust/binder_ndk_sys \
$(LIBBINDER_DIR)/trusty/rust/binder_rpc_unstable_bindgen \
external/rust/crates/downcast-rs \
+ external/rust/crates/libc \
trusty/user/base/lib/trusty-sys \
MODULE_RUSTFLAGS += \
diff --git a/libs/bufferstreams/Android.bp b/libs/bufferstreams/Android.bp
index 365fc457d1..6c2a980f71 100644
--- a/libs/bufferstreams/Android.bp
+++ b/libs/bufferstreams/Android.bp
@@ -19,6 +19,7 @@ package {
aconfig_declarations {
name: "bufferstreams_flags",
package: "com.android.graphics.bufferstreams.flags",
+ container: "system",
srcs: [
"aconfig/bufferstreams_flags.aconfig",
],
diff --git a/libs/bufferstreams/aconfig/bufferstreams_flags.aconfig b/libs/bufferstreams/aconfig/bufferstreams_flags.aconfig
index e258725e3d..d0f7812d21 100644
--- a/libs/bufferstreams/aconfig/bufferstreams_flags.aconfig
+++ b/libs/bufferstreams/aconfig/bufferstreams_flags.aconfig
@@ -1,4 +1,5 @@
package: "com.android.graphics.bufferstreams.flags"
+container: "system"
flag {
name: "bufferstreams_steel_thread"
diff --git a/libs/bufferstreams/rust/src/publishers/buffer_pool_publisher.rs b/libs/bufferstreams/rust/src/publishers/buffer_pool_publisher.rs
index 846105dacd..c5c1fd37c1 100644
--- a/libs/bufferstreams/rust/src/publishers/buffer_pool_publisher.rs
+++ b/libs/bufferstreams/rust/src/publishers/buffer_pool_publisher.rs
@@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-//!
-
use std::time::Instant;
use crate::{
diff --git a/libs/cputimeinstate/testtimeinstate.cpp b/libs/cputimeinstate/testtimeinstate.cpp
index 6ccc6cafb6..81f6a585ab 100644
--- a/libs/cputimeinstate/testtimeinstate.cpp
+++ b/libs/cputimeinstate/testtimeinstate.cpp
@@ -40,6 +40,9 @@ namespace bpf {
static constexpr uint64_t NSEC_PER_SEC = 1000000000;
static constexpr uint64_t NSEC_PER_YEAR = NSEC_PER_SEC * 60 * 60 * 24 * 365;
+// Declare busy loop variable globally to prevent removal during optimization
+static long sum __attribute__((used)) = 0;
+
using std::vector;
class TimeInStateTest : public testing::Test {
@@ -576,7 +579,7 @@ uint64_t timeNanos() {
// Keeps CPU busy with some number crunching
void useCpu() {
- long sum = 0;
+ sum = 0;
for (int i = 0; i < 100000; i++) {
sum *= i;
}
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 86431484d6..059e19ebb8 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -23,6 +23,7 @@ package {
aconfig_declarations {
name: "libgui_flags",
package: "com.android.graphics.libgui.flags",
+ container: "system",
srcs: ["libgui_flags.aconfig"],
}
diff --git a/libs/gui/libgui_flags.aconfig b/libs/gui/libgui_flags.aconfig
index b081030c9f..38646992da 100644
--- a/libs/gui/libgui_flags.aconfig
+++ b/libs/gui/libgui_flags.aconfig
@@ -1,4 +1,5 @@
package: "com.android.graphics.libgui.flags"
+container: "system"
flag {
name: "bq_setframerate"
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 252040d1b0..20b35383bc 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -39,6 +39,7 @@ filegroup {
aconfig_declarations {
name: "com.android.input.flags-aconfig",
package: "com.android.input.flags",
+ container: "system",
srcs: ["input_flags.aconfig"],
}
diff --git a/libs/input/input_flags.aconfig b/libs/input/input_flags.aconfig
index 54eeb39935..dbc002ccb3 100644
--- a/libs/input/input_flags.aconfig
+++ b/libs/input/input_flags.aconfig
@@ -1,4 +1,5 @@
package: "com.android.input.flags"
+container: "system"
flag {
name: "enable_outbound_event_verification"
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index 13cfb491b5..9137a3468f 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -13,6 +13,7 @@ cc_test {
cpp_std: "c++20",
host_supported: true,
srcs: [
+ "BlockingQueue_test.cpp",
"IdGenerator_test.cpp",
"InputChannel_test.cpp",
"InputDevice_test.cpp",
diff --git a/services/inputflinger/tests/BlockingQueue_test.cpp b/libs/input/tests/BlockingQueue_test.cpp
index 754a5c451e..924b937080 100644
--- a/services/inputflinger/tests/BlockingQueue_test.cpp
+++ b/libs/input/tests/BlockingQueue_test.cpp
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#include "../BlockingQueue.h"
-
+#include <input/BlockingQueue.h>
#include <gtest/gtest.h>
#include <thread>
@@ -109,7 +108,7 @@ TEST(BlockingQueueTest, Queue_AllowsMultipleThreads) {
BlockingQueue<int> queue(capacity);
// Fill queue from a different thread
- std::thread fillQueue([&queue](){
+ std::thread fillQueue([&queue]() {
for (size_t i = 0; i < capacity; i++) {
ASSERT_TRUE(queue.push(static_cast<int>(i)));
}
@@ -136,7 +135,7 @@ TEST(BlockingQueueTest, Queue_BlocksWhileWaitingForElements) {
std::atomic_bool hasReceivedElement = false;
// fill queue from a different thread
- std::thread waitUntilHasElements([&queue, &hasReceivedElement](){
+ std::thread waitUntilHasElements([&queue, &hasReceivedElement]() {
queue.pop(); // This should block until an element has been added
hasReceivedElement = true;
});
diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp
index 48d793a4d4..080e62b164 100644
--- a/services/gpuservice/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -70,6 +70,9 @@ GpuService::GpuService()
};
GpuService::~GpuService() {
+ mGpuMem->stop();
+ mGpuWork->stop();
+
mGpuWorkAsyncInitThread->join();
mGpuMemAsyncInitThread->join();
}
diff --git a/services/gpuservice/gpumem/GpuMem.cpp b/services/gpuservice/gpumem/GpuMem.cpp
index 141fe021ee..d0783df109 100644
--- a/services/gpuservice/gpumem/GpuMem.cpp
+++ b/services/gpuservice/gpumem/GpuMem.cpp
@@ -61,6 +61,7 @@ void GpuMem::initialize() {
return;
}
// Retry until GPU driver loaded or timeout.
+ if (mStop.load()) return;
sleep(1);
}
diff --git a/services/gpuservice/gpumem/include/gpumem/GpuMem.h b/services/gpuservice/gpumem/include/gpumem/GpuMem.h
index 9aa74d6863..16b201f516 100644
--- a/services/gpuservice/gpumem/include/gpumem/GpuMem.h
+++ b/services/gpuservice/gpumem/include/gpumem/GpuMem.h
@@ -34,6 +34,7 @@ public:
// dumpsys interface
void dump(const Vector<String16>& args, std::string* result);
bool isInitialized() { return mInitialized.load(); }
+ void stop() { mStop.store(true); }
// Traverse the gpu memory total map to feed the callback function.
void traverseGpuMemTotals(const std::function<void(int64_t ts, uint32_t gpuId, uint32_t pid,
@@ -48,6 +49,10 @@ private:
// indicate whether ebpf has been initialized
std::atomic<bool> mInitialized = false;
+
+ // whether initialization should be stopped
+ std::atomic<bool> mStop = false;
+
// bpf map for GPU memory total data
android::bpf::BpfMapRO<uint64_t, uint64_t> mGpuMemTotalMap;
diff --git a/services/gpuservice/gpuwork/GpuWork.cpp b/services/gpuservice/gpuwork/GpuWork.cpp
index fd703239e9..1a744abc6d 100644
--- a/services/gpuservice/gpuwork/GpuWork.cpp
+++ b/services/gpuservice/gpuwork/GpuWork.cpp
@@ -243,6 +243,7 @@ bool GpuWork::attachTracepoint(const char* programPath, const char* tracepointGr
return false;
}
// Retry until GPU driver loaded or timeout.
+ if (mStop.load()) return false;
sleep(1);
errno = 0;
}
diff --git a/services/gpuservice/gpuwork/include/gpuwork/GpuWork.h b/services/gpuservice/gpuwork/include/gpuwork/GpuWork.h
index cece9999c6..e70da540b9 100644
--- a/services/gpuservice/gpuwork/include/gpuwork/GpuWork.h
+++ b/services/gpuservice/gpuwork/include/gpuwork/GpuWork.h
@@ -40,6 +40,7 @@ public:
~GpuWork();
void initialize();
+ void stop() { mStop.store(true); }
// Dumps the GPU work information.
void dump(const Vector<String16>& args, std::string* result);
@@ -47,7 +48,7 @@ public:
private:
// Attaches tracepoint |tracepoint_group|/|tracepoint_name| to BPF program at path
// |program_path|. The tracepoint is also enabled.
- static bool attachTracepoint(const char* program_path, const char* tracepoint_group,
+ bool attachTracepoint(const char* program_path, const char* tracepoint_group,
const char* tracepoint_name);
// Native atom puller callback registered in statsd.
@@ -80,6 +81,9 @@ private:
// Indicates whether our eBPF components have been initialized.
std::atomic<bool> mInitialized = false;
+ // Indicates whether eBPF initialization should be stopped.
+ std::atomic<bool> mStop = false;
+
// A thread that periodically checks whether |mGpuWorkMap| is nearly full
// and, if so, clears it.
std::thread mMapClearerThread;
diff --git a/services/inputflinger/InputProcessor.h b/services/inputflinger/InputProcessor.h
index dcbfebc62f..7a00a2dae8 100644
--- a/services/inputflinger/InputProcessor.h
+++ b/services/inputflinger/InputProcessor.h
@@ -22,7 +22,7 @@
#include <unordered_map>
#include <aidl/android/hardware/input/processor/IInputProcessor.h>
-#include "BlockingQueue.h"
+#include <input/BlockingQueue.h>
#include "InputListener.h"
namespace android {
diff --git a/services/inputflinger/tests/Android.bp b/services/inputflinger/tests/Android.bp
index 2a03ecc62b..9c9f643656 100644
--- a/services/inputflinger/tests/Android.bp
+++ b/services/inputflinger/tests/Android.bp
@@ -39,7 +39,6 @@ cc_test {
],
srcs: [
"AnrTracker_test.cpp",
- "BlockingQueue_test.cpp",
"CapturedTouchpadEventConverter_test.cpp",
"CursorInputMapper_test.cpp",
"EventHub_test.cpp",
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 5002391f61..c2e67fa788 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -15,7 +15,6 @@
*/
#include "../dispatcher/InputDispatcher.h"
-#include "../BlockingQueue.h"
#include "FakeApplicationHandle.h"
#include "TestEventMatchers.h"
@@ -31,6 +30,7 @@
#include <flag_macros.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
+#include <input/BlockingQueue.h>
#include <input/Input.h>
#include <input/PrintTools.h>
#include <linux/input.h>
diff --git a/services/inputflinger/tests/fuzzers/BlockingQueueFuzzer.cpp b/services/inputflinger/tests/fuzzers/BlockingQueueFuzzer.cpp
index 219b662ffb..863d0a165e 100644
--- a/services/inputflinger/tests/fuzzers/BlockingQueueFuzzer.cpp
+++ b/services/inputflinger/tests/fuzzers/BlockingQueueFuzzer.cpp
@@ -15,8 +15,8 @@
*/
#include <fuzzer/FuzzedDataProvider.h>
+#include <input/BlockingQueue.h>
#include <thread>
-#include "BlockingQueue.h"
// Chosen to be a number large enough for variation in fuzzer runs, but not consume too much memory.
static constexpr size_t MAX_CAPACITY = 1024;
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 0989863b7d..dcef9a3775 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -10,6 +10,7 @@ package {
aconfig_declarations {
name: "surfaceflinger_flags",
package: "com.android.graphics.surfaceflinger.flags",
+ container: "system",
srcs: ["surfaceflinger_flags.aconfig"],
}
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index ae2f2dbbf5..0a70d4299d 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -10,6 +10,7 @@ package {
cc_defaults {
name: "libcompositionengine_defaults",
defaults: [
+ "aconfig_lib_cc_static_link.defaults",
"android.hardware.graphics.composer3-ndk_shared",
"android.hardware.power-ndk_shared",
"librenderengine_deps",
diff --git a/services/surfaceflinger/surfaceflinger_flags.aconfig b/services/surfaceflinger/surfaceflinger_flags.aconfig
index 1a28b81483..abe7ec708f 100644
--- a/services/surfaceflinger/surfaceflinger_flags.aconfig
+++ b/services/surfaceflinger/surfaceflinger_flags.aconfig
@@ -1,4 +1,5 @@
package: "com.android.graphics.surfaceflinger.flags"
+container: "system"
flag {
name: "misc1"
diff --git a/services/vibratorservice/VibratorCallbackScheduler.cpp b/services/vibratorservice/VibratorCallbackScheduler.cpp
index 7eda9ef0c7..b2b1988d97 100644
--- a/services/vibratorservice/VibratorCallbackScheduler.cpp
+++ b/services/vibratorservice/VibratorCallbackScheduler.cpp
@@ -87,13 +87,13 @@ void CallbackScheduler::loop() {
lock.lock();
}
if (mQueue.empty()) {
- // Wait until a new callback is scheduled.
- mCondition.wait(mMutex);
+ // Wait until a new callback is scheduled or destructor was called.
+ mCondition.wait(lock, [this] { return mFinished || !mQueue.empty(); });
} else {
- // Wait until next callback expires, or a new one is scheduled.
+ // Wait until next callback expires or a new one is scheduled.
// Use the monotonic steady clock to wait for the measured delay interval via wait_for
// instead of using a wall clock via wait_until.
- mCondition.wait_for(mMutex, mQueue.top().getWaitForExpirationDuration());
+ mCondition.wait_for(lock, mQueue.top().getWaitForExpirationDuration());
}
}
}
diff --git a/services/vibratorservice/test/VibratorCallbackSchedulerTest.cpp b/services/vibratorservice/test/VibratorCallbackSchedulerTest.cpp
index 426cd426f7..881e32152c 100644
--- a/services/vibratorservice/test/VibratorCallbackSchedulerTest.cpp
+++ b/services/vibratorservice/test/VibratorCallbackSchedulerTest.cpp
@@ -14,20 +14,13 @@
* limitations under the License.
*/
-#define LOG_TAG "VibratorHalWrapperAidlTest"
-
-#include <android-base/thread_annotations.h>
-#include <android/hardware/vibrator/IVibrator.h>
-#include <condition_variable>
-
#include <gmock/gmock.h>
#include <gtest/gtest.h>
-#include <utils/Log.h>
-#include <thread>
-
#include <vibratorservice/VibratorCallbackScheduler.h>
+#include "test_utils.h"
+
using std::chrono::milliseconds;
using std::chrono::steady_clock;
using std::chrono::time_point;
@@ -39,29 +32,25 @@ using namespace testing;
// -------------------------------------------------------------------------------------------------
// Delay allowed for the scheduler to process callbacks during this test.
-static const auto TEST_TIMEOUT = 50ms;
+static const auto TEST_TIMEOUT = 100ms;
class VibratorCallbackSchedulerTest : public Test {
public:
- void SetUp() override {
- mScheduler = std::make_unique<vibrator::CallbackScheduler>();
- std::lock_guard<std::mutex> lock(mMutex);
- mExpiredCallbacks.clear();
- }
+ void SetUp() override { mScheduler = std::make_unique<vibrator::CallbackScheduler>(); }
protected:
std::mutex mMutex;
- std::condition_variable_any mCondition;
std::unique_ptr<vibrator::CallbackScheduler> mScheduler = nullptr;
+ vibrator::TestCounter mCallbackCounter;
std::vector<int32_t> mExpiredCallbacks GUARDED_BY(mMutex);
std::function<void()> createCallback(int32_t id) {
- return [=]() {
+ return [this, id]() {
{
std::lock_guard<std::mutex> lock(mMutex);
mExpiredCallbacks.push_back(id);
}
- mCondition.notify_all();
+ mCallbackCounter.increment();
};
}
@@ -71,56 +60,42 @@ protected:
}
int32_t waitForCallbacks(int32_t callbackCount, milliseconds timeout) {
- time_point<steady_clock> expirationTime = steady_clock::now() + timeout + TEST_TIMEOUT;
- int32_t expiredCallbackCount = 0;
- while (steady_clock::now() < expirationTime) {
- std::lock_guard<std::mutex> lock(mMutex);
- expiredCallbackCount = mExpiredCallbacks.size();
- if (callbackCount <= expiredCallbackCount) {
- return expiredCallbackCount;
- }
- auto currentTimeout = std::chrono::duration_cast<std::chrono::milliseconds>(
- expirationTime - steady_clock::now());
- if (currentTimeout > currentTimeout.zero()) {
- // Use the monotonic steady clock to wait for the requested timeout via wait_for
- // instead of using a wall clock via wait_until.
- mCondition.wait_for(mMutex, currentTimeout);
- }
- }
- return expiredCallbackCount;
+ mCallbackCounter.tryWaitUntilCountIsAtLeast(callbackCount, timeout);
+ return mCallbackCounter.get();
}
};
// -------------------------------------------------------------------------------------------------
TEST_F(VibratorCallbackSchedulerTest, TestScheduleRunsOnlyAfterDelay) {
+ auto callbackDuration = 50ms;
time_point<steady_clock> startTime = steady_clock::now();
- mScheduler->schedule(createCallback(1), 50ms);
+ mScheduler->schedule(createCallback(1), callbackDuration);
- ASSERT_EQ(1, waitForCallbacks(1, 50ms));
+ ASSERT_THAT(waitForCallbacks(1, callbackDuration + TEST_TIMEOUT), Eq(1));
time_point<steady_clock> callbackTime = steady_clock::now();
- // Callback happened at least 50ms after the beginning of the test.
- ASSERT_TRUE(startTime + 50ms <= callbackTime);
- ASSERT_THAT(getExpiredCallbacks(), ElementsAre(1));
+ // Callback took at least the required duration to trigger.
+ ASSERT_THAT(callbackTime, Ge(startTime + callbackDuration));
}
TEST_F(VibratorCallbackSchedulerTest, TestScheduleMultipleCallbacksRunsInDelayOrder) {
// Schedule first callbacks long enough that all 3 will be scheduled together and run in order.
- mScheduler->schedule(createCallback(1), 50ms);
- mScheduler->schedule(createCallback(2), 40ms);
- mScheduler->schedule(createCallback(3), 10ms);
+ mScheduler->schedule(createCallback(1), 50ms + 2 * TEST_TIMEOUT);
+ mScheduler->schedule(createCallback(2), 50ms + TEST_TIMEOUT);
+ mScheduler->schedule(createCallback(3), 50ms);
- ASSERT_EQ(3, waitForCallbacks(3, 50ms));
+ // Callbacks triggered in the expected order based on the requested durations.
+ ASSERT_THAT(waitForCallbacks(3, 50ms + 3 * TEST_TIMEOUT), Eq(3));
ASSERT_THAT(getExpiredCallbacks(), ElementsAre(3, 2, 1));
}
TEST_F(VibratorCallbackSchedulerTest, TestDestructorDropsPendingCallbacksAndKillsThread) {
// Schedule callback long enough that scheduler will be destroyed while it's still scheduled.
- mScheduler->schedule(createCallback(1), 50ms);
+ mScheduler->schedule(createCallback(1), 100ms);
mScheduler.reset(nullptr);
// Should timeout waiting for callback to run.
- ASSERT_EQ(0, waitForCallbacks(1, 50ms));
- ASSERT_TRUE(getExpiredCallbacks().empty());
+ ASSERT_THAT(waitForCallbacks(1, 100ms + TEST_TIMEOUT), Eq(0));
+ ASSERT_THAT(getExpiredCallbacks(), IsEmpty());
}
diff --git a/services/vibratorservice/test/test_utils.h b/services/vibratorservice/test/test_utils.h
index 1933a118ef..c08cfc6bfa 100644
--- a/services/vibratorservice/test/test_utils.h
+++ b/services/vibratorservice/test/test_utils.h
@@ -85,6 +85,34 @@ private:
~TestFactory() = delete;
};
+class TestCounter {
+public:
+ TestCounter(int32_t init = 0) : mMutex(), mCondVar(), mCount(init) {}
+
+ int32_t get() {
+ std::lock_guard<std::mutex> lock(mMutex);
+ return mCount;
+ }
+
+ void increment() {
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mCount += 1;
+ }
+ mCondVar.notify_all();
+ }
+
+ void tryWaitUntilCountIsAtLeast(int32_t count, std::chrono::milliseconds timeout) {
+ std::unique_lock<std::mutex> lock(mMutex);
+ mCondVar.wait_for(lock, timeout, [&] { return mCount >= count; });
+ }
+
+private:
+ std::mutex mMutex;
+ std::condition_variable mCondVar;
+ int32_t mCount GUARDED_BY(mMutex);
+};
+
// -------------------------------------------------------------------------------------------------
} // namespace vibrator