Merge "Add feature definition for devices that support IMS single registration" into sc-dev
diff --git a/cmds/installd/dexopt.cpp b/cmds/installd/dexopt.cpp
index 65fc46e..4dfd1d0 100644
--- a/cmds/installd/dexopt.cpp
+++ b/cmds/installd/dexopt.cpp
@@ -1130,23 +1130,6 @@
return true;
}
-// Updates the access times of out_oat_path based on those from apk_path.
-void update_out_oat_access_times(const char* apk_path, const char* out_oat_path) {
- struct stat input_stat;
- memset(&input_stat, 0, sizeof(input_stat));
- if (stat(apk_path, &input_stat) != 0) {
- PLOG(ERROR) << "Could not stat " << apk_path << " during dexopt";
- return;
- }
-
- struct utimbuf ut;
- ut.actime = input_stat.st_atime;
- ut.modtime = input_stat.st_mtime;
- if (utime(out_oat_path, &ut) != 0) {
- PLOG(WARNING) << "Could not update access times for " << apk_path << " during dexopt";
- }
-}
-
// Runs (execv) dexoptanalyzer on the given arguments.
// The analyzer will check if the dex_file needs to be (re)compiled to match the compiler_filter.
// If this is for a profile guided compilation, profile_was_updated will tell whether or not
@@ -1843,8 +1826,6 @@
}
}
- update_out_oat_access_times(dex_path, out_oat.path().c_str());
-
// We've been successful, don't delete output.
out_oat.DisableCleanup();
out_vdex.DisableCleanup();
diff --git a/cmds/surfacereplayer/proto/src/trace.proto b/cmds/surfacereplayer/proto/src/trace.proto
index c6f656b..79aab82 100644
--- a/cmds/surfacereplayer/proto/src/trace.proto
+++ b/cmds/surfacereplayer/proto/src/trace.proto
@@ -50,11 +50,10 @@
CornerRadiusChange corner_radius = 16;
ReparentChange reparent = 17;
RelativeParentChange relative_parent = 18;
- DetachChildrenChange detach_children = 19;
- ReparentChildrenChange reparent_children = 20;
- BackgroundBlurRadiusChange background_blur_radius = 21;
- ShadowRadiusChange shadow_radius = 22;
- BlurRegionsChange blur_regions = 23;
+ ReparentChildrenChange reparent_children = 19;
+ BackgroundBlurRadiusChange background_blur_radius = 20;
+ ShadowRadiusChange shadow_radius = 21;
+ BlurRegionsChange blur_regions = 22;
}
}
@@ -200,10 +199,6 @@
required int32 z = 2;
}
-message DetachChildrenChange {
- required bool detach_children = 1;
-}
-
message ShadowRadiusChange {
required float radius = 1;
}
diff --git a/cmds/surfacereplayer/replayer/Replayer.cpp b/cmds/surfacereplayer/replayer/Replayer.cpp
index 5849212..58d6582 100644
--- a/cmds/surfacereplayer/replayer/Replayer.cpp
+++ b/cmds/surfacereplayer/replayer/Replayer.cpp
@@ -417,9 +417,6 @@
case SurfaceChange::SurfaceChangeCase::kRelativeParent:
setRelativeParentChange(transaction, change.id(), change.relative_parent());
break;
- case SurfaceChange::SurfaceChangeCase::kDetachChildren:
- setDetachChildrenChange(transaction, change.id(), change.detach_children());
- break;
case SurfaceChange::SurfaceChangeCase::kShadowRadius:
setShadowRadiusChange(transaction, change.id(), change.shadow_radius());
break;
@@ -713,11 +710,6 @@
t.setRelativeLayer(mLayers[id], mLayers[c.relative_parent_id()], c.z());
}
-void Replayer::setDetachChildrenChange(SurfaceComposerClient::Transaction& t,
- layer_id id, const DetachChildrenChange& c) {
- t.detachChildren(mLayers[id]);
-}
-
void Replayer::setReparentChildrenChange(SurfaceComposerClient::Transaction& t,
layer_id id, const ReparentChildrenChange& c) {
if (mLayers.count(c.parent_id()) == 0 || mLayers[c.parent_id()] == nullptr) {
diff --git a/cmds/surfacereplayer/replayer/Replayer.h b/cmds/surfacereplayer/replayer/Replayer.h
index a22262a..324d591 100644
--- a/cmds/surfacereplayer/replayer/Replayer.h
+++ b/cmds/surfacereplayer/replayer/Replayer.h
@@ -116,8 +116,6 @@
layer_id id, const ReparentChange& c);
void setRelativeParentChange(SurfaceComposerClient::Transaction& t,
layer_id id, const RelativeParentChange& c);
- void setDetachChildrenChange(SurfaceComposerClient::Transaction& t,
- layer_id id, const DetachChildrenChange& c);
void setReparentChildrenChange(SurfaceComposerClient::Transaction& t,
layer_id id, const ReparentChildrenChange& c);
void setShadowRadiusChange(SurfaceComposerClient::Transaction& t,
diff --git a/data/etc/android.hardware.keystore.limited_use_key.xml b/data/etc/android.hardware.keystore.limited_use_key.xml
new file mode 100644
index 0000000..5217086
--- /dev/null
+++ b/data/etc/android.hardware.keystore.limited_use_key.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Feature for devices with KeyMint that can enforce limited use key
+ in hardware with any max usage count (including count equals to 1). -->
+<permissions>
+ <feature name="android.hardware.keystore.limited_use_key" />
+</permissions>
\ No newline at end of file
diff --git a/data/etc/android.hardware.keystore.single_use_key.xml b/data/etc/android.hardware.keystore.single_use_key.xml
new file mode 100644
index 0000000..40e80aa
--- /dev/null
+++ b/data/etc/android.hardware.keystore.single_use_key.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- Feature for devices with KeyMint that only can enforce limited use key
+ in hardware with max usage count equals to 1. -->
+<permissions>
+ <feature name="android.hardware.keystore.single_use_key" />
+</permissions>
\ No newline at end of file
diff --git a/data/etc/car_core_hardware.xml b/data/etc/car_core_hardware.xml
index cc0ee82..adfd6e2 100644
--- a/data/etc/car_core_hardware.xml
+++ b/data/etc/car_core_hardware.xml
@@ -47,6 +47,12 @@
<feature name="android.software.secure_lock_screen" />
<feature name="android.software.input_methods" />
+
+ <!-- Feature to support device admins -->
+ <!-- TODO(b/178412797): not fully supported yet, CTS tests are still
+ failing. -->
+ <feature name="android.software.device_admin" />
+
<!-- devices with GPS must include android.hardware.location.gps.xml -->
<!-- devices with an autofocus camera and/or flash must include either
android.hardware.camera.autofocus.xml or
diff --git a/include/android/bitmap.h b/include/android/bitmap.h
index d7f25e1..2362c9e 100644
--- a/include/android/bitmap.h
+++ b/include/android/bitmap.h
@@ -132,8 +132,6 @@
int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,
AndroidBitmapInfo* info);
-#if __ANDROID_API__ >= 30
-
/**
* Given a java bitmap object, return its {@link ADataSpace}.
*
@@ -145,8 +143,6 @@
*/
int32_t AndroidBitmap_getDataSpace(JNIEnv* env, jobject jbitmap) __INTRODUCED_IN(30);
-#endif // __ANDROID_API__ >= 30
-
/**
* Given a java bitmap object, attempt to lock the pixel address.
* Locking will ensure that the memory for the pixels will not move
@@ -216,8 +212,6 @@
const void* data,
size_t size) __INTRODUCED_IN(30);
-#if __ANDROID_API__ >= 30
-
/**
* Compress |pixels| as described by |info|.
*
@@ -269,8 +263,6 @@
int AndroidBitmap_getHardwareBuffer(JNIEnv* env, jobject bitmap,
AHardwareBuffer** outBuffer) __INTRODUCED_IN(30);
-#endif // __ANDROID_API__ >= 30
-
#ifdef __cplusplus
}
#endif
diff --git a/include/android/choreographer.h b/include/android/choreographer.h
index e9f559c..8039bb0 100644
--- a/include/android/choreographer.h
+++ b/include/android/choreographer.h
@@ -61,8 +61,6 @@
*/
typedef void (*AChoreographer_refreshRateCallback)(int64_t vsyncPeriodNanos, void* data);
-#if __ANDROID_API__ >= 24
-
/**
* Get the AChoreographer instance for the current thread. This must be called
* on an ALooper thread.
@@ -86,10 +84,6 @@
long delayMillis) __INTRODUCED_IN(24)
__DEPRECATED_IN(29);
-#endif /* __ANDROID_API__ >= 24 */
-
-#if __ANDROID_API__ >= 29
-
/**
* Power a callback to be run on the next frame. The data pointer provided will
* be passed to the callback function when it's called.
@@ -111,10 +105,6 @@
AChoreographer_frameCallback64 callback, void* data,
uint32_t delayMillis) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
-
-#if __ANDROID_API__ >= 30
-
/**
* Registers a callback to be run when the display refresh rate changes. The
* data pointer provided will be passed to the callback function when it's
@@ -160,7 +150,6 @@
void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer,
AChoreographer_refreshRateCallback, void* data)
__INTRODUCED_IN(30);
-#endif /* __ANDROID_API__ >= 30 */
__END_DECLS
diff --git a/include/android/configuration.h b/include/android/configuration.h
index ccf3e59..88019ae 100644
--- a/include/android/configuration.h
+++ b/include/android/configuration.h
@@ -645,14 +645,12 @@
*/
void AConfiguration_setScreenLong(AConfiguration* config, int32_t screenLong);
-#if __ANDROID_API__ >= 30
/**
* Return the current ACONFIGURATION_SCREENROUND_* set in the configuration.
*
* Available since API level 30.
*/
int32_t AConfiguration_getScreenRound(AConfiguration* config) __INTRODUCED_IN(30);
-#endif
/**
* Set the current screen round in the configuration.
@@ -712,7 +710,6 @@
*/
void AConfiguration_setSmallestScreenWidthDp(AConfiguration* config, int32_t value);
-#if __ANDROID_API__ >= 17
/**
* Return the configuration's layout direction, or
* ACONFIGURATION_LAYOUTDIR_ANY if not set.
@@ -727,7 +724,6 @@
* Available since API level 17.
*/
void AConfiguration_setLayoutDirection(AConfiguration* config, int32_t value) __INTRODUCED_IN(17);
-#endif /* __ANDROID_API__ >= 17 */
/**
* Perform a diff between two configurations. Returns a bit mask of
diff --git a/include/android/font.h b/include/android/font.h
index 1618096..a172618 100644
--- a/include/android/font.h
+++ b/include/android/font.h
@@ -51,8 +51,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 29
-
enum {
/** The minimum value fot the font weight value. */
AFONT_WEIGHT_MIN = 0,
@@ -297,8 +295,6 @@
float AFont_getAxisValue(const AFont* _Nonnull font, uint32_t axisIndex)
__INTRODUCED_IN(29);
-#endif // __ANDROID_API__ >= 29
-
__END_DECLS
#endif // ANDROID_FONT_H
diff --git a/include/android/font_matcher.h b/include/android/font_matcher.h
index d4bd892..49e478c 100644
--- a/include/android/font_matcher.h
+++ b/include/android/font_matcher.h
@@ -97,8 +97,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 29
-
enum {
/** A family variant value for the system default variant. */
AFAMILY_VARIANT_DEFAULT = 0,
@@ -217,8 +215,6 @@
const uint32_t textLength,
uint32_t* _Nullable runLengthOut) __INTRODUCED_IN(29);
-#endif // __ANDROID_API__ >= 29
-
__END_DECLS
#endif // ANDROID_FONT_MATCHER_H
diff --git a/include/android/imagedecoder.h b/include/android/imagedecoder.h
index c7a8939..819a6a4 100644
--- a/include/android/imagedecoder.h
+++ b/include/android/imagedecoder.h
@@ -139,8 +139,6 @@
ANDROID_IMAGE_DECODER_INVALID_STATE = -11,
};
-#if __ANDROID_API__ >= 31
-
/**
* Return a constant string value representing the error code.
*
@@ -155,8 +153,6 @@
*/
const char* _Nullable AImageDecoder_resultToString(int)__INTRODUCED_IN(31);
-#endif // __ANDROID_API__ >= 31
-
struct AImageDecoder;
/**
@@ -179,8 +175,6 @@
*/
typedef struct AImageDecoder AImageDecoder;
-#if __ANDROID_API__ >= 30
-
/**
* Create a new {@link AImageDecoder} from an {@link AAsset}.
*
@@ -469,8 +463,6 @@
*/
int AImageDecoder_setCrop(AImageDecoder* _Nonnull decoder, ARect crop) __INTRODUCED_IN(30);
-#endif // __ANDROID_API__ >= 30
-
struct AImageDecoderHeaderInfo;
/**
* Opaque handle for representing information about the encoded image.
@@ -483,8 +475,6 @@
*/
typedef struct AImageDecoderHeaderInfo AImageDecoderHeaderInfo;
-#if __ANDROID_API__ >= 30
-
/**
* Return an opaque handle for reading header info.
*
@@ -672,10 +662,6 @@
void* _Nonnull pixels, size_t stride,
size_t size) __INTRODUCED_IN(30);
-#endif // __ANDROID_API__ >= 30
-
-#if __ANDROID_API__ >= 31
-
/**
* Return true iff the image is animated - i.e. has multiple frames.
*
@@ -690,8 +676,6 @@
bool AImageDecoder_isAnimated(AImageDecoder* _Nonnull decoder)
__INTRODUCED_IN(31);
-#endif // __ANDROID_API__ >= 31
-
enum {
/*
* Reported by {@link AImageDecoder_getRepeatCount} if the
@@ -702,8 +686,6 @@
ANDROID_IMAGE_DECODER_INFINITE = INT32_MAX,
};
-#if __ANDROID_API__ >= 31
-
/**
* Report how many times the animation should repeat.
*
@@ -793,8 +775,6 @@
int AImageDecoder_rewind(AImageDecoder* _Nonnull decoder)
__INTRODUCED_IN(31);
-#endif // __ANDROID_API__ >= 31
-
struct AImageDecoderFrameInfo;
/**
@@ -810,8 +790,6 @@
*/
typedef struct AImageDecoderFrameInfo AImageDecoderFrameInfo;
-#if __ANDROID_API__ >= 31
-
/**
* Create an uninitialized AImageDecoderFrameInfo.
*
@@ -922,8 +900,6 @@
bool AImageDecoderFrameInfo_hasAlphaWithinBounds(
const AImageDecoderFrameInfo* _Nonnull info) __INTRODUCED_IN(31);
-#endif // __ANDROID_API__ >= 31
-
/**
* How a frame is “disposed” before showing the next one.
*
@@ -947,8 +923,6 @@
ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS = 3,
};
-#if __ANDROID_API__ >= 31
-
/**
* Return how this frame is “disposed” before showing the next one.
*
@@ -969,8 +943,6 @@
int32_t AImageDecoderFrameInfo_getDisposeOp(
const AImageDecoderFrameInfo* _Nonnull info) __INTRODUCED_IN(31);
-#endif // __ANDROID_API__ >= 31
-
/**
* How a frame is blended with the previous frame.
*
@@ -989,8 +961,6 @@
ANDROID_IMAGE_DECODER_BLEND_OP_SRC_OVER = 2,
};
-#if __ANDROID_API__ >= 31
-
/**
* Return how this frame is blended with the previous frame.
*
@@ -1047,8 +1017,6 @@
__INTRODUCED_IN(31);
-#endif // __ANDROID_API__ >= 31
-
#ifdef __cplusplus
}
#endif
diff --git a/include/android/input.h b/include/android/input.h
index b5d399e..b70d424 100644
--- a/include/android/input.h
+++ b/include/android/input.h
@@ -856,8 +856,10 @@
AINPUT_SOURCE_TOUCH_NAVIGATION = 0x00200000 | AINPUT_SOURCE_CLASS_NONE,
/** joystick */
AINPUT_SOURCE_JOYSTICK = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
+ /** HDMI */
+ AINPUT_SOURCE_HDMI = 0x02000000 | AINPUT_SOURCE_CLASS_BUTTON,
/** sensor */
- AINPUT_SOURCE_SENSOR = 0x02000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
+ AINPUT_SOURCE_SENSOR = 0x04000000 | AINPUT_SOURCE_UNKNOWN,
/** rotary encoder */
AINPUT_SOURCE_ROTARY_ENCODER = 0x00400000 | AINPUT_SOURCE_CLASS_NONE,
diff --git a/include/android/multinetwork.h b/include/android/multinetwork.h
index c6d1c94..424299d 100644
--- a/include/android/multinetwork.h
+++ b/include/android/multinetwork.h
@@ -60,8 +60,6 @@
* on failure with an appropriate errno value set.
*/
-#if __ANDROID_API__ >= 23
-
/**
* Set the network to be used by the given socket file descriptor.
*
@@ -111,10 +109,6 @@
const char *node, const char *service,
const struct addrinfo *hints, struct addrinfo **res) __INTRODUCED_IN(23);
-#endif /* __ANDROID_API__ >= 23 */
-
-#if __ANDROID_API__ >= 29
-
/**
* Possible values of the flags argument to android_res_nsend and android_res_nquery.
* Values are ORed together.
@@ -187,8 +181,6 @@
*/
void android_res_cancel(int nsend_fd) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
-
__END_DECLS
#endif // ANDROID_MULTINETWORK_H
diff --git a/include/android/native_window_jni.h b/include/android/native_window_jni.h
index 3a77ffe..071ec79 100644
--- a/include/android/native_window_jni.h
+++ b/include/android/native_window_jni.h
@@ -44,7 +44,6 @@
*/
ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface);
-#if __ANDROID_API__ >= 26
/**
* Return a Java Surface object derived from the ANativeWindow, for interacting
* with it through Java code. The returned Java object acquires a reference on
@@ -55,7 +54,6 @@
* Available since API level 26.
*/
jobject ANativeWindow_toSurface(JNIEnv* env, ANativeWindow* window) __INTRODUCED_IN(26);
-#endif
#ifdef __cplusplus
};
diff --git a/include/android/sensor.h b/include/android/sensor.h
index eb40779..6447844 100644
--- a/include/android/sensor.h
+++ b/include/android/sensor.h
@@ -52,6 +52,13 @@
#include <math.h>
#include <stdint.h>
+#if !defined(__INTRODUCED_IN)
+#define __INTRODUCED_IN(__api_level) /* nothing */
+#endif
+#if !defined(__DEPRECATED_IN)
+#define __DEPRECATED_IN(__api_level) __attribute__((__deprecated__))
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -553,13 +560,8 @@
* ASensorManager* sensorManager = ASensorManager_getInstance();
*
*/
-#if __ANDROID_API__ >= 26
-__attribute__ ((deprecated)) ASensorManager* ASensorManager_getInstance();
-#else
-ASensorManager* ASensorManager_getInstance();
-#endif
+ASensorManager* ASensorManager_getInstance() __DEPRECATED_IN(26);
-#if __ANDROID_API__ >= 26
/**
* Get a reference to the sensor manager. ASensorManager is a singleton
* per package as different packages may have access to different sensors.
@@ -571,7 +573,6 @@
* Available since API level 26.
*/
ASensorManager* ASensorManager_getInstanceForPackage(const char* packageName) __INTRODUCED_IN(26);
-#endif
/**
* Returns the list of available sensors.
@@ -584,7 +585,6 @@
*/
ASensor const* ASensorManager_getDefaultSensor(ASensorManager* manager, int type);
-#if __ANDROID_API__ >= 21
/**
* Returns the default sensor with the given type and wakeUp properties or NULL if no sensor
* of this type and wakeUp properties exists.
@@ -592,7 +592,6 @@
* Available since API level 21.
*/
ASensor const* ASensorManager_getDefaultSensorEx(ASensorManager* manager, int type, bool wakeUp) __INTRODUCED_IN(21);
-#endif
/**
* Creates a new sensor event queue and associate it with a looper.
@@ -609,7 +608,6 @@
*/
int ASensorManager_destroyEventQueue(ASensorManager* manager, ASensorEventQueue* queue);
-#if __ANDROID_API__ >= 26
/**
* Create direct channel based on shared memory
*
@@ -706,7 +704,6 @@
*/
int ASensorManager_configureDirectReport(ASensorManager* manager,
ASensor const* sensor, int channelId, int rate) __INTRODUCED_IN(26);
-#endif /* __ANDROID_API__ >= 26 */
/*****************************************************************************/
@@ -795,7 +792,6 @@
*/
ssize_t ASensorEventQueue_getEvents(ASensorEventQueue* queue, ASensorEvent* events, size_t count);
-#if __ANDROID_API__ >= 29
/**
* Request that {@link ASENSOR_TYPE_ADDITIONAL_INFO} events to be delivered on
* the given {@link ASensorEventQueue}.
@@ -819,7 +815,6 @@
* \return 0 on success or a negative error code on failure
*/
int ASensorEventQueue_requestAdditionalInfoEvents(ASensorEventQueue* queue, bool enable) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
/*****************************************************************************/
@@ -850,7 +845,6 @@
*/
int ASensor_getMinDelay(ASensor const* sensor);
-#if __ANDROID_API__ >= 21
/**
* Returns the maximum size of batches for this sensor. Batches will often be
* smaller, as the hardware fifo might be used for other sensors.
@@ -886,9 +880,7 @@
* Available since API level 21.
*/
bool ASensor_isWakeUpSensor(ASensor const* sensor) __INTRODUCED_IN(21);
-#endif /* __ANDROID_API__ >= 21 */
-#if __ANDROID_API__ >= 26
/**
* Test if sensor supports a certain type of direct channel.
*
@@ -914,9 +906,7 @@
* does not support direct report.
*/
int ASensor_getHighestDirectReportRateLevel(ASensor const* sensor) __INTRODUCED_IN(26);
-#endif /* __ANDROID_API__ >= 26 */
-#if __ANDROID_API__ >= 29
/**
* Returns the sensor's handle.
*
@@ -934,7 +924,6 @@
* Available since API level 29.
*/
int ASensor_getHandle(ASensor const* sensor) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
#ifdef __cplusplus
};
diff --git a/include/android/sharedmem.h b/include/android/sharedmem.h
index 5f74682..7994aa9 100644
--- a/include/android/sharedmem.h
+++ b/include/android/sharedmem.h
@@ -50,8 +50,6 @@
extern "C" {
#endif
-#if __ANDROID_API__ >= 26
-
/**
* Create a shared memory region.
*
@@ -121,8 +119,6 @@
*/
int ASharedMemory_setProt(int fd, int prot) __INTRODUCED_IN(26);
-#endif // __ANDROID_API__ >= 26
-
#ifdef __cplusplus
};
#endif
diff --git a/include/android/sharedmem_jni.h b/include/android/sharedmem_jni.h
index 13e56e6..bbac785 100644
--- a/include/android/sharedmem_jni.h
+++ b/include/android/sharedmem_jni.h
@@ -52,8 +52,6 @@
extern "C" {
#endif
-#if __ANDROID_API__ >= 27
-
/**
* Returns a dup'd FD from the given Java android.os.SharedMemory object. The returned file
* descriptor has all the same properties & capabilities as the FD returned from
@@ -72,8 +70,6 @@
*/
int ASharedMemory_dupFromJava(JNIEnv* env, jobject sharedMemory) __INTRODUCED_IN(27);
-#endif // __ANDROID_API__ >= 27
-
#ifdef __cplusplus
};
#endif
diff --git a/include/android/surface_control.h b/include/android/surface_control.h
index 7a74248..98fd875 100644
--- a/include/android/surface_control.h
+++ b/include/android/surface_control.h
@@ -35,8 +35,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 29
-
struct ASurfaceControl;
/**
@@ -409,10 +407,6 @@
struct AHdrMetadata_cta861_3* metadata)
__INTRODUCED_IN(29);
-#endif // __ANDROID_API__ >= 29
-
-#if __ANDROID_API__ >= 30
-
/**
* Same as ASurfaceTransaction_setFrameRateWithSeamlessness(transaction, surface_control,
* frameRate, compatibility, true).
@@ -425,10 +419,6 @@
ASurfaceControl* surface_control, float frameRate,
int8_t compatibility) __INTRODUCED_IN(30);
-#endif // __ANDROID_API__ >= 30
-
-#if __ANDROID_API__ >= 31
-
/**
* Sets the intended frame rate for \a surface_control.
*
@@ -462,7 +452,6 @@
int8_t compatibility, bool shouldBeSeamless)
__INTRODUCED_IN(31);
-#endif // __ANDROID_API__ >= 31
__END_DECLS
#endif // ANDROID_SURFACE_CONTROL_H
diff --git a/include/android/surface_texture.h b/include/android/surface_texture.h
index dde7eaa..b227b32 100644
--- a/include/android/surface_texture.h
+++ b/include/android/surface_texture.h
@@ -59,8 +59,6 @@
*/
typedef struct ASurfaceTexture ASurfaceTexture;
-#if __ANDROID_API__ >= 28
-
/**
* Release the reference to the native ASurfaceTexture acquired with
* ASurfaceTexture_fromSurfaceTexture().
@@ -175,8 +173,6 @@
*/
int64_t ASurfaceTexture_getTimestamp(ASurfaceTexture* st) __INTRODUCED_IN(28);
-#endif /* __ANDROID_API__ >= 28 */
-
__END_DECLS
#endif /* ANDROID_NATIVE_SURFACE_TEXTURE_H */
diff --git a/include/android/surface_texture_jni.h b/include/android/surface_texture_jni.h
index 2266d54..e40686d 100644
--- a/include/android/surface_texture_jni.h
+++ b/include/android/surface_texture_jni.h
@@ -32,8 +32,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 28
-
/**
* Get a reference to the native ASurfaceTexture from the corresponding java object.
*
@@ -52,8 +50,6 @@
*/
ASurfaceTexture* ASurfaceTexture_fromSurfaceTexture(JNIEnv* env, jobject surfacetexture) __INTRODUCED_IN(28);
-#endif
-
__END_DECLS
#endif /* ANDROID_NATIVE_SURFACE_TEXTURE_JNI_H */
diff --git a/include/android/system_fonts.h b/include/android/system_fonts.h
index 6fd7d2c..b0bbb95 100644
--- a/include/android/system_fonts.h
+++ b/include/android/system_fonts.h
@@ -87,8 +87,6 @@
__BEGIN_DECLS
-#if __ANDROID_API__ >= 29
-
/**
* ASystemFontIterator provides access to the system font configuration.
*
@@ -128,8 +126,6 @@
*/
AFont* _Nullable ASystemFontIterator_next(ASystemFontIterator* _Nonnull iterator) __INTRODUCED_IN(29);
-#endif // __ANDROID_API__ >= 29
-
__END_DECLS
#endif // ANDROID_SYSTEM_FONTS_H
diff --git a/include/android/trace.h b/include/android/trace.h
index dbad6f6..dcefffb 100644
--- a/include/android/trace.h
+++ b/include/android/trace.h
@@ -40,8 +40,6 @@
extern "C" {
#endif
-#if __ANDROID_API__ >= 23
-
/**
* Returns true if tracing is enabled. Use this to avoid expensive computation only necessary
* when tracing is enabled.
@@ -72,10 +70,6 @@
*/
void ATrace_endSection() __INTRODUCED_IN(23);
-#endif /* __ANDROID_API__ >= 23 */
-
-#if __ANDROID_API__ >= 29
-
/**
* Writes a trace message to indicate that a given section of code has
* begun. Must be followed by a call to {@link ATrace_endAsyncSection} with the same
@@ -112,8 +106,6 @@
*/
void ATrace_setCounter(const char* counterName, int64_t counterValue) __INTRODUCED_IN(29);
-#endif /* __ANDROID_API__ >= 29 */
-
#ifdef __cplusplus
}
#endif
diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h
index 23692e9..2bd7bd2 100644
--- a/include/input/InputDevice.h
+++ b/include/input/InputDevice.h
@@ -213,6 +213,9 @@
inline void setVibrator(bool hasVibrator) { mHasVibrator = hasVibrator; }
inline bool hasVibrator() const { return mHasVibrator; }
+ inline void setHasBattery(bool hasBattery) { mHasBattery = hasBattery; }
+ inline bool hasBattery() const { return mHasBattery; }
+
inline void setButtonUnderPad(bool hasButton) { mHasButtonUnderPad = hasButton; }
inline bool hasButtonUnderPad() const { return mHasButtonUnderPad; }
@@ -239,6 +242,7 @@
int32_t mKeyboardType;
std::shared_ptr<KeyCharacterMap> mKeyCharacterMap;
bool mHasVibrator;
+ bool mHasBattery;
bool mHasButtonUnderPad;
bool mHasSensor;
diff --git a/libs/binder/IpPrefix.cpp b/libs/binder/IpPrefix.cpp
index 8d62266..4edc493 100644
--- a/libs/binder/IpPrefix.cpp
+++ b/libs/binder/IpPrefix.cpp
@@ -24,12 +24,10 @@
#include <log/log.h>
#include <utils/Errors.h>
-using android::BAD_TYPE;
using android::BAD_VALUE;
using android::NO_ERROR;
using android::Parcel;
using android::status_t;
-using android::UNEXPECTED_NULL;
namespace android {
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 440c98c..b9d00fe 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -2291,7 +2291,7 @@
ssize_t written = TEMP_FAILURE_RETRY(
::write(comm, &message, sizeof(message)));
- if (written == -1 || written != sizeof(message)) {
+ if (written != sizeof(message)) {
ALOGW("Failed to detach ParcelFileDescriptor written: %zd err: %s",
written, strerror(errno));
return BAD_TYPE;
diff --git a/libs/binder/PersistableBundle.cpp b/libs/binder/PersistableBundle.cpp
index c807cfe..406fee0 100644
--- a/libs/binder/PersistableBundle.cpp
+++ b/libs/binder/PersistableBundle.cpp
@@ -31,7 +31,6 @@
using android::BAD_VALUE;
using android::NO_ERROR;
using android::Parcel;
-using android::sp;
using android::status_t;
using android::UNEXPECTED_NULL;
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 454fbd0..3c90681 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -597,13 +597,6 @@
return STATUS_INVALID_OPERATION;
}
- if (!binder->isRemote()) {
- LOG(WARNING) << "A binder object at " << binder
- << " is being transacted on, however, this object is in the same process as "
- "its proxy. Transacting with this binder is expensive compared to just "
- "calling the corresponding functionality in the same process.";
- }
-
*in = new AParcel(binder);
status_t status = (*in)->get()->writeInterfaceToken(clazz->getInterfaceDescriptor());
binder_status_t ret = PruneStatusT(status);
diff --git a/libs/binder/rust/tests/serialization.rs b/libs/binder/rust/tests/serialization.rs
index 2ae13f4..2bf3d03 100644
--- a/libs/binder/rust/tests/serialization.rs
+++ b/libs/binder/rust/tests/serialization.rs
@@ -25,7 +25,6 @@
use binder::parcel::ParcelFileDescriptor;
use std::ffi::{c_void, CStr, CString};
-use std::panic::{self, AssertUnwindSafe};
use std::sync::Once;
#[allow(
@@ -73,22 +72,9 @@
impl ReadParcelTest for () {}
-fn on_transact(
- _service: &dyn ReadParcelTest,
- code: TransactionCode,
- parcel: &Parcel,
- reply: &mut Parcel,
-) -> Result<()> {
- panic::catch_unwind(AssertUnwindSafe(|| transact_inner(code, parcel, reply))).unwrap_or_else(
- |e| {
- eprintln!("Failure in Rust: {:?}", e.downcast_ref::<String>());
- Err(StatusCode::FAILED_TRANSACTION)
- },
- )
-}
-
#[allow(clippy::float_cmp)]
-fn transact_inner(code: TransactionCode, parcel: &Parcel, reply: &mut Parcel) -> Result<()> {
+fn on_transact(_service: &dyn ReadParcelTest, code: TransactionCode,
+ parcel: &Parcel, reply: &mut Parcel) -> Result<()> {
match code {
bindings::Transaction_TEST_BOOL => {
assert_eq!(parcel.read::<bool>()?, true);
@@ -296,7 +282,7 @@
))?;
}
bindings::Transaction_TEST_FAIL => {
- panic!("Testing expected failure");
+ return Err(StatusCode::FAILED_TRANSACTION)
}
_ => return Err(StatusCode::UNKNOWN_TRANSACTION),
}
diff --git a/libs/cputimeinstate/cputimeinstate.cpp b/libs/cputimeinstate/cputimeinstate.cpp
index 462f0db..7e9bb7d 100644
--- a/libs/cputimeinstate/cputimeinstate.cpp
+++ b/libs/cputimeinstate/cputimeinstate.cpp
@@ -155,10 +155,14 @@
return true;
}
-static bool attachTracepointProgram(const std::string &eventType, const std::string &eventName) {
+static int retrieveProgramFd(const std::string &eventType, const std::string &eventName) {
std::string path = StringPrintf(BPF_FS_PATH "prog_time_in_state_tracepoint_%s_%s",
eventType.c_str(), eventName.c_str());
- int prog_fd = retrieveProgram(path.c_str());
+ return retrieveProgram(path.c_str());
+}
+
+static bool attachTracepointProgram(const std::string &eventType, const std::string &eventName) {
+ int prog_fd = retrieveProgramFd(eventType, eventName);
if (prog_fd < 0) return false;
return bpf_attach_tracepoint(prog_fd, eventType.c_str(), eventName.c_str()) >= 0;
}
@@ -174,6 +178,17 @@
return {};
}
+// Check if tracking is expected to work without activating it.
+bool isTrackingUidTimesSupported() {
+ auto freqs = getCpuFreqs();
+ if (!freqs || freqs->empty()) return false;
+ if (gTracking) return true;
+ if (retrieveProgramFd("sched", "sched_switch") < 0) return false;
+ if (retrieveProgramFd("power", "cpu_frequency") < 0) return false;
+ if (retrieveProgramFd("sched", "sched_process_free") < 0) return false;
+ return true;
+}
+
// Start tracking and aggregating data to be reported by getUidCpuFreqTimes and getUidsCpuFreqTimes.
// Returns true on success, false otherwise.
// Tracking is active only once a live process has successfully called this function; if the calling
diff --git a/libs/cputimeinstate/cputimeinstate.h b/libs/cputimeinstate/cputimeinstate.h
index 46de669..4145374 100644
--- a/libs/cputimeinstate/cputimeinstate.h
+++ b/libs/cputimeinstate/cputimeinstate.h
@@ -22,6 +22,7 @@
namespace android {
namespace bpf {
+bool isTrackingUidTimesSupported();
bool startTrackingUidTimes();
std::optional<std::vector<std::vector<uint64_t>>> getTotalCpuFreqTimes();
std::optional<std::vector<std::vector<uint64_t>>> getUidCpuFreqTimes(uint32_t uid);
diff --git a/libs/cputimeinstate/testtimeinstate.cpp b/libs/cputimeinstate/testtimeinstate.cpp
index d25b2e9..2112b10 100644
--- a/libs/cputimeinstate/testtimeinstate.cpp
+++ b/libs/cputimeinstate/testtimeinstate.cpp
@@ -40,6 +40,11 @@
using std::vector;
+TEST(TimeInStateTest, IsTrackingSupported) {
+ isTrackingUidTimesSupported();
+ SUCCEED();
+}
+
TEST(TimeInStateTest, TotalTimeInState) {
auto times = getTotalCpuFreqTimes();
ASSERT_TRUE(times.has_value());
diff --git a/libs/dumputils/dump_utils.cpp b/libs/dumputils/dump_utils.cpp
index 143fa13..8a82c2a 100644
--- a/libs/dumputils/dump_utils.cpp
+++ b/libs/dumputils/dump_utils.cpp
@@ -53,7 +53,6 @@
/* list of hal interface to dump containing process during native dumps */
static const char* hal_interfaces_to_dump[] {
- "android.hardware.audio@2.0::IDevicesFactory",
"android.hardware.audio@4.0::IDevicesFactory",
"android.hardware.audio@5.0::IDevicesFactory",
"android.hardware.audio@6.0::IDevicesFactory",
diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp
index c6c9a8f..2ad484a 100644
--- a/libs/gui/DisplayEventDispatcher.cpp
+++ b/libs/gui/DisplayEventDispatcher.cpp
@@ -36,7 +36,9 @@
DisplayEventDispatcher::DisplayEventDispatcher(
const sp<Looper>& looper, ISurfaceComposer::VsyncSource vsyncSource,
ISurfaceComposer::EventRegistrationFlags eventRegistration)
- : mLooper(looper), mReceiver(vsyncSource, eventRegistration), mWaitingForVsync(false) {
+ : mLooper(looper),
+ mReceiver(vsyncSource, eventRegistration),
+ mVsyncState(VsyncState::Unregistered) {
ALOGV("dispatcher %p ~ Initializing display event dispatcher.", this);
}
@@ -66,26 +68,37 @@
}
status_t DisplayEventDispatcher::scheduleVsync() {
- if (!mWaitingForVsync) {
- ALOGV("dispatcher %p ~ Scheduling vsync.", this);
+ switch (mVsyncState) {
+ case VsyncState::Unregistered: {
+ ALOGV("dispatcher %p ~ Scheduling vsync.", this);
- // Drain all pending events.
- nsecs_t vsyncTimestamp;
- PhysicalDisplayId vsyncDisplayId;
- uint32_t vsyncCount;
- VsyncEventData vsyncEventData;
- if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount, &vsyncEventData)) {
- ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "", this,
- ns2ms(static_cast<nsecs_t>(vsyncTimestamp)));
+ // Drain all pending events.
+ nsecs_t vsyncTimestamp;
+ PhysicalDisplayId vsyncDisplayId;
+ uint32_t vsyncCount;
+ VsyncEventData vsyncEventData;
+ if (processPendingEvents(&vsyncTimestamp, &vsyncDisplayId, &vsyncCount,
+ &vsyncEventData)) {
+ ALOGE("dispatcher %p ~ last event processed while scheduling was for %" PRId64 "",
+ this, ns2ms(static_cast<nsecs_t>(vsyncTimestamp)));
+ }
+
+ status_t status = mReceiver.setVsyncRate(1);
+ if (status) {
+ ALOGW("Failed to set vsync rate, status=%d", status);
+ return status;
+ }
+
+ mVsyncState = VsyncState::RegisteredAndWaitingForVsync;
+ break;
}
-
- status_t status = mReceiver.requestNextVsync();
- if (status) {
- ALOGW("Failed to request next vsync, status=%d", status);
- return status;
+ case VsyncState::Registered: {
+ mVsyncState = VsyncState::RegisteredAndWaitingForVsync;
+ break;
}
-
- mWaitingForVsync = true;
+ case VsyncState::RegisteredAndWaitingForVsync: {
+ break;
+ }
}
return OK;
}
@@ -123,8 +136,23 @@
", displayId=%s, count=%d, vsyncId=%" PRId64,
this, ns2ms(vsyncTimestamp), to_string(vsyncDisplayId).c_str(), vsyncCount,
vsyncEventData.id);
- mWaitingForVsync = false;
- dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData);
+ switch (mVsyncState) {
+ case VsyncState::Unregistered:
+ ALOGW("Received unexpected VSYNC event");
+ break;
+ case VsyncState::RegisteredAndWaitingForVsync:
+ mVsyncState = VsyncState::Registered;
+ dispatchVsync(vsyncTimestamp, vsyncDisplayId, vsyncCount, vsyncEventData);
+ break;
+ case VsyncState::Registered:
+ status_t status = mReceiver.setVsyncRate(0);
+ if (status) {
+ ALOGW("Failed to reset vsync rate, status=%d", status);
+ return status;
+ }
+ mVsyncState = VsyncState::Unregistered;
+ break;
+ }
}
return 1; // keep the callback
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 3f314cd..fff3305 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -426,9 +426,6 @@
what |= eReparentChildren;
reparentSurfaceControl = other.reparentSurfaceControl;
}
- if (other.what & eDetachChildren) {
- what |= eDetachChildren;
- }
if (other.what & eRelativeLayerChanged) {
what |= eRelativeLayerChanged;
what &= ~eLayerChanged;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index a1bdc03..550803d 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1386,19 +1386,6 @@
return *this;
}
-SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::detachChildren(
- const sp<SurfaceControl>& sc) {
- layer_state_t* s = getLayerState(sc);
- if (!s) {
- mStatus = BAD_INDEX;
- return *this;
- }
- s->what |= layer_state_t::eDetachChildren;
-
- registerSurfaceControlForCallback(sc);
- return *this;
-}
-
#ifndef NO_INPUT
SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInputWindowInfo(
const sp<SurfaceControl>& sc,
diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h
index f446dd8..4175a49 100644
--- a/libs/gui/include/gui/DisplayEventDispatcher.h
+++ b/libs/gui/include/gui/DisplayEventDispatcher.h
@@ -52,7 +52,20 @@
private:
sp<Looper> mLooper;
DisplayEventReceiver mReceiver;
- bool mWaitingForVsync;
+ // The state of vsync event registration and whether the client is expecting
+ // an event or not.
+ enum class VsyncState {
+ // The dispatcher is not registered for vsync events.
+ Unregistered,
+ // The dispatcher is registered to receive vsync events but should not dispatch it to the
+ // client as the client is not expecting a vsync event.
+ Registered,
+
+ // The dispatcher is registered to receive vsync events and supposed to dispatch it to
+ // the client.
+ RegisteredAndWaitingForVsync,
+ };
+ VsyncState mVsyncState;
std::vector<FrameRateOverride> mFrameRateOverrides;
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 2668108..2f9a0c0 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -102,7 +102,7 @@
/* was ScalingModeChanged, now available 0x00000400, */
eShadowRadiusChanged = 0x00000800,
eReparentChildren = 0x00001000,
- eDetachChildren = 0x00002000,
+ /* was eDetachChildren, now available 0x00002000, */
eRelativeLayerChanged = 0x00004000,
eReparent = 0x00008000,
eColorChanged = 0x00010000,
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index bed5c44..e7abfe6 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -508,18 +508,6 @@
// Set the framenumber generated by the graphics producer to mimic BufferQueue behaviour.
Transaction& setFrameNumber(const sp<SurfaceControl>& sc, uint64_t frameNumber);
- // Detaches all child surfaces (and their children recursively)
- // from their SurfaceControl.
- // The child SurfaceControls will not throw exceptions or return errors,
- // but transactions will have no effect.
- // The child surfaces will continue to follow their parent surfaces,
- // and remain eligible for rendering, but their relative state will be
- // frozen. We use this in the WindowManager, in app shutdown/relaunch
- // scenarios, where the app would otherwise clean up its child Surfaces.
- // Sometimes the WindowManager needs to extend their lifetime slightly
- // in order to perform an exit animation or prevent flicker.
- Transaction& detachChildren(const sp<SurfaceControl>& sc);
-
#ifndef NO_INPUT
Transaction& setInputWindowInfo(const sp<SurfaceControl>& sc, const InputWindowInfo& info);
Transaction& setFocusedWindow(const FocusRequest& request);
diff --git a/libs/input/InputDevice.cpp b/libs/input/InputDevice.cpp
index 2ed441d..698cf6e 100644
--- a/libs/input/InputDevice.cpp
+++ b/libs/input/InputDevice.cpp
@@ -166,6 +166,7 @@
mKeyboardType(other.mKeyboardType),
mKeyCharacterMap(other.mKeyCharacterMap),
mHasVibrator(other.mHasVibrator),
+ mHasBattery(other.mHasBattery),
mHasButtonUnderPad(other.mHasButtonUnderPad),
mHasSensor(other.mHasSensor),
mMotionRanges(other.mMotionRanges),
@@ -187,6 +188,7 @@
mSources = 0;
mKeyboardType = AINPUT_KEYBOARD_TYPE_NONE;
mHasVibrator = false;
+ mHasBattery = false;
mHasButtonUnderPad = false;
mHasSensor = false;
mMotionRanges.clear();
diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp
index 6d91916..6b085a3 100644
--- a/libs/nativedisplay/AChoreographer.cpp
+++ b/libs/nativedisplay/AChoreographer.cpp
@@ -21,7 +21,7 @@
#include <gui/DisplayEventDispatcher.h>
#include <gui/ISurfaceComposer.h>
#include <gui/SurfaceComposerClient.h>
-#include <nativehelper/JNIHelp.h>
+#include <jni.h>
#include <private/android/choreographer.h>
#include <utils/Looper.h>
#include <utils/Timers.h>
diff --git a/libs/nativedisplay/Android.bp b/libs/nativedisplay/Android.bp
index f56b3a2..6574ae6 100644
--- a/libs/nativedisplay/Android.bp
+++ b/libs/nativedisplay/Android.bp
@@ -53,15 +53,13 @@
"libcutils",
"libEGL",
"libGLESv2",
- "libnativehelper",
],
- export_shared_lib_headers: [
- "libnativehelper",
- ],
+ export_header_lib_headers: ["jni_headers"],
header_libs: [
+ "jni_headers",
"libnativedisplay_headers",
+ "libnativehelper_header_only",
],
-
}
diff --git a/libs/nativedisplay/include-private/private/android/choreographer.h b/libs/nativedisplay/include-private/private/android/choreographer.h
index d3a4a66..0f4fd45 100644
--- a/libs/nativedisplay/include-private/private/android/choreographer.h
+++ b/libs/nativedisplay/include-private/private/android/choreographer.h
@@ -18,7 +18,7 @@
#include <apex/choreographer.h>
#include <inttypes.h>
-#include <nativehelper/JNIHelp.h>
+#include <jni.h>
namespace android {
diff --git a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
index f371667..85fe42f 100644
--- a/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
+++ b/libs/nativedisplay/include/surfacetexture/surface_texture_platform.h
@@ -19,7 +19,7 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include <nativehelper/JNIHelp.h>
+#include <jni.h>
#include <system/graphics.h>
// This file provides a facade API on top of SurfaceTexture, which avoids using
diff --git a/libs/nativedisplay/surfacetexture/surface_texture.cpp b/libs/nativedisplay/surfacetexture/surface_texture.cpp
index ebe4484..c214ab7 100644
--- a/libs/nativedisplay/surfacetexture/surface_texture.cpp
+++ b/libs/nativedisplay/surfacetexture/surface_texture.cpp
@@ -29,8 +29,7 @@
#include <mutex>
#include <jni.h>
-#include <nativehelper/JNIHelp.h>
-#include <nativehelper/ScopedLocalRef.h>
+#include <nativehelper/scoped_local_ref.h>
struct ASurfaceTexture {
android::sp<android::SurfaceTexture> consumer;
diff --git a/libs/nativewindow/include/android/hardware_buffer.h b/libs/nativewindow/include/android/hardware_buffer.h
index 4fcca9e..20a1f74 100644
--- a/libs/nativewindow/include/android/hardware_buffer.h
+++ b/libs/nativewindow/include/android/hardware_buffer.h
@@ -334,8 +334,6 @@
// clang-format on
-#if __ANDROID_API__ >= 26
-
/**
* Allocates a buffer that matches the passed AHardwareBuffer_Desc.
*
@@ -478,10 +476,6 @@
AHardwareBuffer* _Nullable* _Nonnull outBuffer)
__INTRODUCED_IN(26);
-#endif // __ANDROID_API__ >= 26
-
-#if __ANDROID_API__ >= 29
-
/**
* Lock a potentially multi-planar AHardwareBuffer for direct CPU access.
*
@@ -551,10 +545,6 @@
int32_t* _Nonnull outBytesPerPixel,
int32_t* _Nonnull outBytesPerStride) __INTRODUCED_IN(29);
-#endif // __ANDROID_API__ >= 29
-
-#if __ANDROID_API__ >= 31
-
/**
* Get the system wide unique id for an AHardwareBuffer.
*
@@ -566,8 +556,6 @@
int AHardwareBuffer_getId(const AHardwareBuffer* _Nonnull buffer, uint64_t* _Nonnull outId)
__INTRODUCED_IN(31);
-#endif // __ANDROID_API__ >= 31
-
__END_DECLS
#endif // ANDROID_HARDWARE_BUFFER_H
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index deea59b..285f2fb 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -186,8 +186,6 @@
*/
int32_t ANativeWindow_unlockAndPost(ANativeWindow* window);
-#if __ANDROID_API__ >= 26
-
/**
* Set a transform that will be applied to future buffers posted to the window.
*
@@ -198,10 +196,6 @@
*/
int32_t ANativeWindow_setBuffersTransform(ANativeWindow* window, int32_t transform) __INTRODUCED_IN(26);
-#endif // __ANDROID_API__ >= 26
-
-#if __ANDROID_API__ >= 28
-
/**
* All buffers queued after this call will be associated with the dataSpace
* parameter specified.
@@ -230,10 +224,6 @@
*/
int32_t ANativeWindow_getBuffersDataSpace(ANativeWindow* window) __INTRODUCED_IN(28);
-#endif // __ANDROID_API__ >= 28
-
-#if __ANDROID_API__ >= 30
-
/** Compatibility value for ANativeWindow_setFrameRate. */
enum ANativeWindow_FrameRateCompatibility {
/**
@@ -275,11 +265,7 @@
*
* Available since API level 30.
*/
-void ANativeWindow_tryAllocateBuffers(ANativeWindow* window);
-
-#endif // __ANDROID_API__ >= 30
-
-#if __ANDROID_API__ >= 31
+void ANativeWindow_tryAllocateBuffers(ANativeWindow* window) __INTRODUCED_IN(30);
/**
* Sets the intended frame rate for this window.
@@ -322,8 +308,6 @@
int32_t ANativeWindow_setFrameRateWithSeamlessness(ANativeWindow* window, float frameRate,
int8_t compatibility, bool shouldBeSeamless) __INTRODUCED_IN(31);
-#endif // __ANDROID_API__ >= 31
-
#ifdef __cplusplus
};
#endif
diff --git a/libs/sensorprivacy/SensorPrivacyManager.cpp b/libs/sensorprivacy/SensorPrivacyManager.cpp
index 7bddee6..4714469 100644
--- a/libs/sensorprivacy/SensorPrivacyManager.cpp
+++ b/libs/sensorprivacy/SensorPrivacyManager.cpp
@@ -64,13 +64,15 @@
}
}
-void SensorPrivacyManager::addIndividualSensorPrivacyListener(int userId, int sensor,
+status_t SensorPrivacyManager::addIndividualSensorPrivacyListener(int userId, int sensor,
const sp<hardware::ISensorPrivacyListener>& listener)
{
sp<hardware::ISensorPrivacyManager> service = getService();
if (service != nullptr) {
- service->addIndividualSensorPrivacyListener(userId, sensor, listener);
+ return service->addIndividualSensorPrivacyListener(userId, sensor, listener)
+ .transactionError();
}
+ return UNEXPECTED_NULL;
}
void SensorPrivacyManager::removeSensorPrivacyListener(
@@ -106,6 +108,19 @@
return false;
}
+status_t SensorPrivacyManager::isIndividualSensorPrivacyEnabled(int userId, int sensor,
+ bool &returnVal)
+{
+ sp<hardware::ISensorPrivacyManager> service = getService();
+ if (service != nullptr) {
+ binder::Status res = service->isIndividualSensorPrivacyEnabled(userId, sensor, &returnVal);
+ return res.transactionError();
+ }
+ // if the SensorPrivacyManager is not available then assume sensor privacy is disabled
+ returnVal = false;
+ return UNKNOWN_ERROR;
+}
+
status_t SensorPrivacyManager::linkToDeath(const sp<IBinder::DeathRecipient>& recipient)
{
sp<hardware::ISensorPrivacyManager> service = getService();
diff --git a/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h b/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h
index bd7c726..12778e1 100644
--- a/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h
+++ b/libs/sensorprivacy/include/sensorprivacy/SensorPrivacyManager.h
@@ -36,11 +36,12 @@
SensorPrivacyManager();
void addSensorPrivacyListener(const sp<hardware::ISensorPrivacyListener>& listener);
- void addIndividualSensorPrivacyListener(int userId, int sensor,
+ status_t addIndividualSensorPrivacyListener(int userId, int sensor,
const sp<hardware::ISensorPrivacyListener>& listener);
void removeSensorPrivacyListener(const sp<hardware::ISensorPrivacyListener>& listener);
bool isSensorPrivacyEnabled();
bool isIndividualSensorPrivacyEnabled(int userId, int sensor);
+ status_t isIndividualSensorPrivacyEnabled(int userId, int sensor, bool &result);
status_t linkToDeath(const sp<IBinder::DeathRecipient>& recipient);
status_t unlinkToDeath(const sp<IBinder::DeathRecipient>& recipient);
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index ea9b483..69aea84 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -108,6 +108,10 @@
virtual bool isVibrating(int32_t deviceId) = 0;
virtual std::vector<int32_t> getVibratorIds(int32_t deviceId) = 0;
+ /* Get battery level of a particular input device. */
+ virtual std::optional<int32_t> getBatteryCapacity(int32_t deviceId) = 0;
+ /* Get battery status of a particular input device. */
+ virtual std::optional<int32_t> getBatteryStatus(int32_t deviceId) = 0;
/* Return true if the device can send input events to the specified display. */
virtual bool canDispatchToDisplay(int32_t deviceId, int32_t displayId) = 0;
diff --git a/services/inputflinger/reader/Android.bp b/services/inputflinger/reader/Android.bp
index abda4ef..7f979f2 100644
--- a/services/inputflinger/reader/Android.bp
+++ b/services/inputflinger/reader/Android.bp
@@ -30,6 +30,7 @@
"mapper/accumulator/CursorScrollAccumulator.cpp",
"mapper/accumulator/SingleTouchMotionAccumulator.cpp",
"mapper/accumulator/TouchButtonAccumulator.cpp",
+ "mapper/BatteryInputMapper.cpp",
"mapper/CursorInputMapper.cpp",
"mapper/ExternalStylusInputMapper.cpp",
"mapper/InputMapper.cpp",
@@ -60,7 +61,11 @@
"libui",
"libutils",
],
+ static_libs: [
+ "libc++fs",
+ ],
header_libs: [
+ "libbatteryservice_headers",
"libinputreader_headers",
],
}
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index b97ff90..8f8c051 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -29,11 +29,14 @@
#include <sys/inotify.h>
#include <sys/ioctl.h>
#include <sys/limits.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
#include <unistd.h>
#define LOG_TAG "EventHub"
// #define LOG_NDEBUG 0
+#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <cutils/properties.h>
#include <input/KeyCharacterMap.h>
@@ -64,6 +67,23 @@
static constexpr int32_t FF_STRONG_MAGNITUDE_CHANNEL_IDX = 0;
static constexpr int32_t FF_WEAK_MAGNITUDE_CHANNEL_IDX = 1;
+// must be kept in sync with definitions in kernel /drivers/power/supply/power_supply_sysfs.c
+static const std::unordered_map<std::string, int32_t> BATTERY_STATUS =
+ {{"Unknown", BATTERY_STATUS_UNKNOWN},
+ {"Charging", BATTERY_STATUS_CHARGING},
+ {"Discharging", BATTERY_STATUS_DISCHARGING},
+ {"Not charging", BATTERY_STATUS_NOT_CHARGING},
+ {"Full", BATTERY_STATUS_FULL}};
+
+// Mapping taken from
+// https://gitlab.freedesktop.org/upower/upower/-/blob/master/src/linux/up-device-supply.c#L484
+static const std::unordered_map<std::string, int32_t> BATTERY_LEVEL = {{"Critical", 5},
+ {"Low", 10},
+ {"Normal", 55},
+ {"High", 70},
+ {"Full", 100},
+ {"Unknown", 50}};
+
static inline const char* toString(bool value) {
return value ? "true" : "false";
}
@@ -127,6 +147,73 @@
return inputEventTime;
}
+/**
+ * Returns the sysfs root path of the input device
+ *
+ */
+static std::filesystem::path getSysfsRootPath(const char* devicePath) {
+ std::error_code errorCode;
+
+ // Stat the device path to get the major and minor number of the character file
+ struct stat statbuf;
+ if (stat(devicePath, &statbuf) == -1) {
+ ALOGE("Could not stat device %s due to error: %s.", devicePath, std::strerror(errno));
+ return std::filesystem::path();
+ }
+
+ unsigned int major_num = major(statbuf.st_rdev);
+ unsigned int minor_num = minor(statbuf.st_rdev);
+
+ // Realpath "/sys/dev/char/{major}:{minor}" to get the sysfs path to the input event
+ auto sysfsPath = std::filesystem::path("/sys/dev/char/");
+ sysfsPath /= std::to_string(major_num) + ":" + std::to_string(minor_num);
+ sysfsPath = std::filesystem::canonical(sysfsPath, errorCode);
+
+ // Make sure nothing went wrong in call to canonical()
+ if (errorCode) {
+ ALOGW("Could not run filesystem::canonical() due to error %d : %s.", errorCode.value(),
+ errorCode.message().c_str());
+ return std::filesystem::path();
+ }
+
+ // Continue to go up a directory until we reach a directory named "input"
+ while (sysfsPath != "/" && sysfsPath.filename() != "input") {
+ sysfsPath = sysfsPath.parent_path();
+ }
+
+ // Then go up one more and you will be at the sysfs root of the device
+ sysfsPath = sysfsPath.parent_path();
+
+ // Make sure we didn't reach root path and that directory actually exists
+ if (sysfsPath == "/" || !std::filesystem::exists(sysfsPath, errorCode)) {
+ if (errorCode) {
+ ALOGW("Could not run filesystem::exists() due to error %d : %s.", errorCode.value(),
+ errorCode.message().c_str());
+ }
+
+ // Not found
+ return std::filesystem::path();
+ }
+
+ return sysfsPath;
+}
+
+/**
+ * Returns the power supply node in sys fs
+ *
+ */
+static std::filesystem::path findPowerSupplyNode(const std::filesystem::path& sysfsRootPath) {
+ for (auto path = sysfsRootPath; path != "/"; path = path.parent_path()) {
+ std::error_code errorCode;
+ auto iter = std::filesystem::directory_iterator(path / "power_supply", errorCode);
+ if (!errorCode && iter != std::filesystem::directory_iterator()) {
+ return iter->path();
+ }
+ }
+ // Not found
+ return std::filesystem::path();
+}
+
// --- Global Functions ---
Flags<InputDeviceClass> getAbsAxisUsage(int32_t axis, Flags<InputDeviceClass> deviceClasses) {
@@ -976,6 +1063,56 @@
return nullptr;
}
+std::optional<int32_t> EventHub::getBatteryCapacity(int32_t deviceId) const {
+ std::scoped_lock _l(mLock);
+ Device* device = getDeviceLocked(deviceId);
+ std::string buffer;
+
+ if (!device || (device->sysfsBatteryPath.empty())) {
+ return std::nullopt;
+ }
+
+ // Some devices report battery capacity as an integer through the "capacity" file
+ if (base::ReadFileToString(device->sysfsBatteryPath / "capacity", &buffer)) {
+ return std::stoi(buffer);
+ }
+
+ // Other devices report capacity as an enum value POWER_SUPPLY_CAPACITY_LEVEL_XXX
+ // These values are taken from kernel source code include/linux/power_supply.h
+ if (base::ReadFileToString(device->sysfsBatteryPath / "capacity_level", &buffer)) {
+ const auto it = BATTERY_LEVEL.find(buffer);
+ if (it != BATTERY_LEVEL.end()) {
+ return it->second;
+ }
+ }
+ return std::nullopt;
+}
+
+std::optional<int32_t> EventHub::getBatteryStatus(int32_t deviceId) const {
+ std::scoped_lock _l(mLock);
+ Device* device = getDeviceLocked(deviceId);
+ std::string buffer;
+
+ if (!device || (device->sysfsBatteryPath.empty())) {
+ return std::nullopt;
+ }
+
+ if (!base::ReadFileToString(device->sysfsBatteryPath / "status", &buffer)) {
+ ALOGE("Failed to read sysfs battery info: %s", strerror(errno));
+ return std::nullopt;
+ }
+
+ // Remove trailing new line
+ buffer.erase(std::remove(buffer.begin(), buffer.end(), '\n'), buffer.end());
+ const auto it = BATTERY_STATUS.find(buffer);
+
+ if (it != BATTERY_STATUS.end()) {
+ return it->second;
+ }
+
+ return std::nullopt;
+}
+
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
ALOG_ASSERT(bufferSize >= 1);
@@ -1584,6 +1721,18 @@
return -1;
}
+ // Grab the device's sysfs path
+ device->sysfsRootPath = getSysfsRootPath(devicePath.c_str());
+
+ if (!device->sysfsRootPath.empty()) {
+ device->sysfsBatteryPath = findPowerSupplyNode(device->sysfsRootPath);
+
+ // Check if a battery exists
+ if (!device->sysfsBatteryPath.empty()) {
+ device->classes |= InputDeviceClass::BATTERY;
+ }
+ }
+
// Determine whether the device has a mic.
if (device->deviceHasMicLocked()) {
device->classes |= InputDeviceClass::MIC;
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index 3e6910d..8fc6f4a 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -21,6 +21,7 @@
#include <input/Flags.h>
#include <algorithm>
+#include "BatteryInputMapper.h"
#include "CursorInputMapper.h"
#include "ExternalStylusInputMapper.h"
#include "InputReaderContext.h"
@@ -160,6 +161,11 @@
mappers.push_back(std::make_unique<VibratorInputMapper>(*contextPtr));
}
+ // Battery-like devices.
+ if (classes.test(InputDeviceClass::BATTERY)) {
+ mappers.push_back(std::make_unique<BatteryInputMapper>(*contextPtr));
+ }
+
// Keyboard-like devices.
uint32_t keyboardSource = 0;
int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
@@ -490,6 +496,15 @@
for_each_mapper([when](InputMapper& mapper) { mapper.cancelTouch(when); });
}
+std::optional<int32_t> InputDevice::getBatteryCapacity() {
+ return first_in_mappers<int32_t>(
+ [](InputMapper& mapper) { return mapper.getBatteryCapacity(); });
+}
+
+std::optional<int32_t> InputDevice::getBatteryStatus() {
+ return first_in_mappers<int32_t>([](InputMapper& mapper) { return mapper.getBatteryStatus(); });
+}
+
int32_t InputDevice::getMetaState() {
int32_t result = 0;
for_each_mapper([&result](InputMapper& mapper) { result |= mapper.getMetaState(); });
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 7c448e4..de5d0e6 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -673,6 +673,26 @@
}
}
+std::optional<int32_t> InputReader::getBatteryCapacity(int32_t deviceId) {
+ std::scoped_lock _l(mLock);
+
+ InputDevice* device = findInputDeviceLocked(deviceId);
+ if (device) {
+ return device->getBatteryCapacity();
+ }
+ return std::nullopt;
+}
+
+std::optional<int32_t> InputReader::getBatteryStatus(int32_t deviceId) {
+ std::scoped_lock _l(mLock);
+
+ InputDevice* device = findInputDeviceLocked(deviceId);
+ if (device) {
+ return device->getBatteryStatus();
+ }
+ return std::nullopt;
+}
+
bool InputReader::isInputDeviceEnabled(int32_t deviceId) {
std::scoped_lock _l(mLock);
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index 2cea017..30967df 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -23,6 +23,9 @@
#include <vector>
#include <input/Flags.h>
+#include <filesystem>
+
+#include <batteryservice/BatteryService.h>
#include <input/Input.h>
#include <input/InputDevice.h>
#include <input/KeyCharacterMap.h>
@@ -121,6 +124,9 @@
/* The input device has a sensor like accelerometer, gyro, etc */
SENSOR = 0x00002000,
+ /* The input device has a battery */
+ BATTERY = 0x00004000,
+
/* The input device is virtual (not a real device, not part of UI configuration). */
VIRTUAL = 0x40000000,
@@ -242,6 +248,12 @@
virtual void cancelVibrate(int32_t deviceId) = 0;
virtual std::vector<int32_t> getVibratorIds(int32_t deviceId) = 0;
+ /* Query battery level. */
+ virtual std::optional<int32_t> getBatteryCapacity(int32_t deviceId) const = 0;
+
+ /* Query battery status. */
+ virtual std::optional<int32_t> getBatteryStatus(int32_t deviceId) const = 0;
+
/* Requests the EventHub to reopen all input devices on the next call to getEvents(). */
virtual void requestReopenDevices() = 0;
@@ -404,6 +416,10 @@
void monitor() override final;
+ std::optional<int32_t> getBatteryCapacity(int32_t deviceId) const override final;
+
+ std::optional<int32_t> getBatteryStatus(int32_t deviceId) const override final;
+
bool isDeviceEnabled(int32_t deviceId) override final;
status_t enableDevice(int32_t deviceId) override final;
@@ -442,6 +458,10 @@
bool ffEffectPlaying;
int16_t ffEffectId; // initially -1
+ // The paths are invalid when .empty() returns true
+ std::filesystem::path sysfsRootPath;
+ std::filesystem::path sysfsBatteryPath;
+
int32_t controllerNumber;
Device(int fd, int32_t id, const std::string& path,
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index 5af76b7..e4186c8 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -92,6 +92,9 @@
void disableSensor(InputDeviceSensorType sensorType);
void flushSensor(InputDeviceSensorType sensorType);
+ std::optional<int32_t> getBatteryCapacity();
+ std::optional<int32_t> getBatteryStatus();
+
int32_t getMetaState();
void updateMetaState(int32_t keyCode);
@@ -287,6 +290,12 @@
inline std::vector<int32_t> getVibratorIds() { return mEventHub->getVibratorIds(mId); }
+ inline std::optional<int32_t> getBatteryCapacity() {
+ return mEventHub->getBatteryCapacity(mId);
+ }
+
+ inline std::optional<int32_t> getBatteryStatus() { return mEventHub->getBatteryStatus(mId); }
+
inline bool hasAbsoluteAxis(int32_t code) const {
RawAbsoluteAxisInfo info;
mEventHub->getAbsoluteAxisInfo(mId, code, &info);
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 7be932a..e2558bc 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -95,6 +95,10 @@
void flushSensor(int32_t deviceId, InputDeviceSensorType sensorType) override;
+ std::optional<int32_t> getBatteryCapacity(int32_t deviceId) override;
+
+ std::optional<int32_t> getBatteryStatus(int32_t deviceId) override;
+
protected:
// These members are protected so they can be instrumented by test cases.
virtual std::shared_ptr<InputDevice> createDeviceLocked(int32_t deviceId,
diff --git a/services/inputflinger/reader/mapper/BatteryInputMapper.cpp b/services/inputflinger/reader/mapper/BatteryInputMapper.cpp
new file mode 100644
index 0000000..afdc5ab
--- /dev/null
+++ b/services/inputflinger/reader/mapper/BatteryInputMapper.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "../Macros.h"
+
+#include "BatteryInputMapper.h"
+
+namespace android {
+
+BatteryInputMapper::BatteryInputMapper(InputDeviceContext& deviceContext)
+ : InputMapper(deviceContext) {}
+
+uint32_t BatteryInputMapper::getSources() {
+ return 0;
+}
+
+void BatteryInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
+ InputMapper::populateDeviceInfo(info);
+
+ info->setHasBattery(true);
+}
+
+void BatteryInputMapper::process(const RawEvent* rawEvent) {}
+
+std::optional<int32_t> BatteryInputMapper::getBatteryCapacity() {
+ return getDeviceContext().getBatteryCapacity();
+}
+
+std::optional<int32_t> BatteryInputMapper::getBatteryStatus() {
+ return getDeviceContext().getBatteryStatus();
+}
+
+void BatteryInputMapper::dump(std::string& dump) {
+ dump += INDENT2 "Battery Input Mapper:\n";
+ dump += getBatteryCapacity().has_value()
+ ? StringPrintf(INDENT3 "Capacity: %d\n", getBatteryCapacity().value())
+ : StringPrintf(INDENT3 "Capacity: Unknown");
+
+ std::string status;
+ switch (getBatteryStatus().value_or(BATTERY_STATUS_UNKNOWN)) {
+ case BATTERY_STATUS_CHARGING:
+ status = "Charging";
+ break;
+ case BATTERY_STATUS_DISCHARGING:
+ status = "Discharging";
+ break;
+ case BATTERY_STATUS_NOT_CHARGING:
+ status = "Not charging";
+ break;
+ case BATTERY_STATUS_FULL:
+ status = "Full";
+ break;
+ default:
+ status = "Unknown";
+ }
+ dump += StringPrintf(INDENT3 "Status: %s\n", status.c_str());
+}
+
+} // namespace android
diff --git a/services/inputflinger/reader/mapper/BatteryInputMapper.h b/services/inputflinger/reader/mapper/BatteryInputMapper.h
new file mode 100644
index 0000000..4fe373e
--- /dev/null
+++ b/services/inputflinger/reader/mapper/BatteryInputMapper.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _UI_INPUTREADER_BATTERY_INPUT_MAPPER_H
+#define _UI_INPUTREADER_BATTERY_INPUT_MAPPER_H
+
+#include "InputMapper.h"
+
+namespace android {
+
+class BatteryInputMapper : public InputMapper {
+public:
+ explicit BatteryInputMapper(InputDeviceContext& deviceContext);
+ virtual ~BatteryInputMapper(){};
+
+ uint32_t getSources() override;
+ void populateDeviceInfo(InputDeviceInfo* deviceInfo) override;
+ void process(const RawEvent* rawEvent) override;
+
+ std::optional<int32_t> getBatteryCapacity() override;
+ std::optional<int32_t> getBatteryStatus() override;
+
+ void dump(std::string& dump) override;
+};
+
+} // namespace android
+
+#endif // _UI_INPUTREADER_BATTERY_INPUT_MAPPER_H
diff --git a/services/inputflinger/reader/mapper/InputMapper.h b/services/inputflinger/reader/mapper/InputMapper.h
index 6ca6ec9..44af998 100644
--- a/services/inputflinger/reader/mapper/InputMapper.h
+++ b/services/inputflinger/reader/mapper/InputMapper.h
@@ -72,6 +72,9 @@
virtual void disableSensor(InputDeviceSensorType sensorType);
virtual void flushSensor(InputDeviceSensorType sensorType);
+ virtual std::optional<int32_t> getBatteryCapacity() { return std::nullopt; }
+ virtual std::optional<int32_t> getBatteryStatus() { return std::nullopt; }
+
virtual int32_t getMetaState();
virtual void updateMetaState(int32_t keyCode);
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 36da8dd..0e88312 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <BatteryInputMapper.h>
#include <CursorInputMapper.h>
#include <InputDevice.h>
#include <InputMapper.h>
@@ -67,6 +68,8 @@
static constexpr int32_t FIRST_TRACKING_ID = 0;
static constexpr int32_t SECOND_TRACKING_ID = 1;
static constexpr int32_t THIRD_TRACKING_ID = 2;
+static constexpr int32_t BATTERY_STATUS = 4;
+static constexpr int32_t BATTERY_CAPACITY = 66;
// Error tolerance for floating point assertions.
static const float EPSILON = 0.001f;
@@ -863,6 +866,10 @@
std::vector<int32_t> getVibratorIds(int32_t deviceId) override { return mVibrators; };
+ std::optional<int32_t> getBatteryCapacity(int32_t) const override { return BATTERY_CAPACITY; }
+
+ std::optional<int32_t> getBatteryStatus(int32_t) const override { return BATTERY_STATUS; }
+
virtual bool isExternal(int32_t) const {
return false;
}
@@ -1924,6 +1931,52 @@
ASSERT_EQ(mReader->getVibratorIds(deviceId).size(), 2U);
}
+class FakeBatteryInputMapper : public FakeInputMapper {
+public:
+ FakeBatteryInputMapper(InputDeviceContext& deviceContext, uint32_t sources)
+ : FakeInputMapper(deviceContext, sources) {}
+
+ std::optional<int32_t> getBatteryCapacity() override {
+ return getDeviceContext().getBatteryCapacity();
+ }
+
+ std::optional<int32_t> getBatteryStatus() override {
+ return getDeviceContext().getBatteryStatus();
+ }
+};
+
+TEST_F(InputReaderTest, BatteryGetCapacity) {
+ constexpr int32_t deviceId = END_RESERVED_ID + 1000;
+ Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
+ constexpr int32_t eventHubId = 1;
+ const char* DEVICE_LOCATION = "BLUETOOTH";
+ std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
+ FakeBatteryInputMapper& mapper =
+ device->addMapper<FakeBatteryInputMapper>(eventHubId, AINPUT_SOURCE_KEYBOARD);
+ mReader->pushNextDevice(device);
+
+ ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
+ ASSERT_NO_FATAL_FAILURE(mapper.assertConfigureWasCalled());
+
+ ASSERT_EQ(mReader->getBatteryCapacity(deviceId), BATTERY_CAPACITY);
+}
+
+TEST_F(InputReaderTest, BatteryGetStatus) {
+ constexpr int32_t deviceId = END_RESERVED_ID + 1000;
+ Flags<InputDeviceClass> deviceClass = InputDeviceClass::KEYBOARD | InputDeviceClass::BATTERY;
+ constexpr int32_t eventHubId = 1;
+ const char* DEVICE_LOCATION = "BLUETOOTH";
+ std::shared_ptr<InputDevice> device = mReader->newDevice(deviceId, "fake", DEVICE_LOCATION);
+ FakeBatteryInputMapper& mapper =
+ device->addMapper<FakeBatteryInputMapper>(eventHubId, AINPUT_SOURCE_KEYBOARD);
+ mReader->pushNextDevice(device);
+
+ ASSERT_NO_FATAL_FAILURE(addDevice(eventHubId, "fake", deviceClass, nullptr));
+ ASSERT_NO_FATAL_FAILURE(mapper.assertConfigureWasCalled());
+
+ ASSERT_EQ(mReader->getBatteryStatus(deviceId), BATTERY_STATUS);
+}
+
// --- InputReaderIntegrationTest ---
// These tests create and interact with the InputReader only through its interface.
@@ -2799,6 +2852,32 @@
mapper.flushSensor(InputDeviceSensorType::GYROSCOPE);
}
+// --- BatteryInputMapperTest ---
+class BatteryInputMapperTest : public InputMapperTest {
+protected:
+ void SetUp() override { InputMapperTest::SetUp(DEVICE_CLASSES | InputDeviceClass::BATTERY); }
+};
+
+TEST_F(BatteryInputMapperTest, GetSources) {
+ BatteryInputMapper& mapper = addMapperAndConfigure<BatteryInputMapper>();
+
+ ASSERT_EQ(AINPUT_SOURCE_UNKNOWN, mapper.getSources());
+}
+
+TEST_F(BatteryInputMapperTest, GetBatteryCapacity) {
+ BatteryInputMapper& mapper = addMapperAndConfigure<BatteryInputMapper>();
+
+ ASSERT_TRUE(mapper.getBatteryCapacity());
+ ASSERT_EQ(*mapper.getBatteryCapacity(), BATTERY_CAPACITY);
+}
+
+TEST_F(BatteryInputMapperTest, GetBatteryStatus) {
+ BatteryInputMapper& mapper = addMapperAndConfigure<BatteryInputMapper>();
+
+ ASSERT_TRUE(mapper.getBatteryStatus());
+ ASSERT_EQ(*mapper.getBatteryStatus(), BATTERY_STATUS);
+}
+
// --- KeyboardInputMapperTest ---
class KeyboardInputMapperTest : public InputMapperTest {
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index 39ae2fd..ec81ff7 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -377,7 +377,7 @@
displayId && mFlinger->getHwComposer().isConnected(*displayId)) {
// The HWC doesn't support present fences, so use the refresh
// timestamp instead.
- const nsecs_t actualPresentTime = mFlinger->getHwComposer().getRefreshTimestamp(*displayId);
+ const nsecs_t actualPresentTime = display->getRefreshTimestamp();
mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime);
mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(), mCurrentFrameNumber,
actualPresentTime,
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 0cc15c2..3dc62e3 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -216,8 +216,7 @@
// Returns true if the most recent Transaction applied to CurrentState will be presented.
return (getSidebandStreamChanged() || getAutoRefresh() ||
(mCurrentState.modified &&
- (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr))) &&
- !mLayerDetached;
+ (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr)));
}
/* TODO: vhau uncomment once deferred transaction migration complete in
@@ -461,11 +460,6 @@
return willPresent;
}
-void BufferStateLayer::forceSendCallbacks() {
- mFlinger->getTransactionCompletedThread().finalizePendingCallbackHandles(
- mCurrentState.callbackHandles, std::vector<JankData>());
-}
-
bool BufferStateLayer::setTransparentRegionHint(const Region& transparent) {
mCurrentState.transparentRegionHint = transparent;
mCurrentState.modified = true;
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index f638caa..b93d567 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -80,7 +80,6 @@
bool setApi(int32_t api) override;
bool setSidebandStream(const sp<NativeHandle>& sidebandStream) override;
bool setTransactionCompletedListeners(const std::vector<sp<CallbackHandle>>& handles) override;
- void forceSendCallbacks() override;
bool addFrameEvent(const sp<Fence>& acquireFence, nsecs_t postedTime,
nsecs_t requestedPresentTime) override;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h
index 6559ed8..4502eee 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/DisplaySurface.h
@@ -16,6 +16,7 @@
#pragma once
+#include <ui/Size.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/StrongPointer.h>
@@ -71,7 +72,7 @@
virtual void dumpAsString(String8& result) const = 0;
- virtual void resizeBuffers(const uint32_t w, const uint32_t h) = 0;
+ virtual void resizeBuffers(const ui::Size&) = 0;
virtual const sp<Fence>& getClientTargetAcquireFence() const = 0;
};
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplaySurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplaySurface.h
index 31b5f95..168e433d 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplaySurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/DisplaySurface.h
@@ -18,6 +18,7 @@
#include <compositionengine/DisplaySurface.h>
#include <gmock/gmock.h>
+#include <ui/Size.h>
#include <utils/String8.h>
namespace android::compositionengine::mock {
@@ -32,7 +33,7 @@
MOCK_METHOD0(advanceFrame, status_t());
MOCK_METHOD0(onFrameCommitted, void());
MOCK_CONST_METHOD1(dumpAsString, void(String8& result));
- MOCK_METHOD2(resizeBuffers, void(uint32_t, uint32_t));
+ MOCK_METHOD1(resizeBuffers, void(const ui::Size&));
MOCK_CONST_METHOD0(getClientTargetAcquireFence, const sp<Fence>&());
};
diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
index b47f7fd..3bef77d 100644
--- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
@@ -96,8 +96,7 @@
}
void RenderSurface::setDisplaySize(const ui::Size& size) {
- mDisplaySurface->resizeBuffers(static_cast<uint32_t>(size.width),
- static_cast<uint32_t>(size.height));
+ mDisplaySurface->resizeBuffers(size);
mSize = size;
}
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index 3133e90..ab00385 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -85,16 +85,15 @@
MOCK_CONST_METHOD0(updatesDeviceProductInfoOnHotplugReconnect, bool());
MOCK_METHOD2(onVsync, bool(hal::HWDisplayId, int64_t));
MOCK_METHOD2(setVsyncEnabled, void(PhysicalDisplayId, hal::Vsync));
- MOCK_CONST_METHOD1(getRefreshTimestamp, nsecs_t(PhysicalDisplayId));
MOCK_CONST_METHOD1(isConnected, bool(PhysicalDisplayId));
- MOCK_CONST_METHOD1(getModes, DisplayModes(PhysicalDisplayId));
- MOCK_CONST_METHOD1(getActiveMode, DisplayModePtr(PhysicalDisplayId));
+ MOCK_CONST_METHOD1(getModes, std::vector<HWComposer::HWCDisplayMode>(PhysicalDisplayId));
+ MOCK_CONST_METHOD1(getActiveMode, std::optional<hal::HWConfigId>(PhysicalDisplayId));
MOCK_CONST_METHOD1(getColorModes, std::vector<ui::ColorMode>(PhysicalDisplayId));
MOCK_METHOD3(setActiveColorMode, status_t(PhysicalDisplayId, ui::ColorMode, ui::RenderIntent));
MOCK_CONST_METHOD0(isUsingVrComposer, bool());
MOCK_CONST_METHOD1(getDisplayConnectionType, DisplayConnectionType(PhysicalDisplayId));
MOCK_CONST_METHOD1(isVsyncPeriodSwitchSupported, bool(PhysicalDisplayId));
- MOCK_CONST_METHOD1(getDisplayVsyncPeriod, nsecs_t(PhysicalDisplayId));
+ MOCK_CONST_METHOD2(getDisplayVsyncPeriod, status_t(PhysicalDisplayId, nsecs_t*));
MOCK_METHOD4(setActiveModeWithConstraints,
status_t(PhysicalDisplayId, hal::HWConfigId,
const hal::VsyncPeriodChangeConstraints&,
diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
index cd39733..5ef5d7b 100644
--- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp
@@ -119,9 +119,10 @@
*/
TEST_F(RenderSurfaceTest, setDisplaySizeAppliesChange) {
- EXPECT_CALL(*mDisplaySurface, resizeBuffers(640, 480)).Times(1);
+ const ui::Size size(640, 480);
+ EXPECT_CALL(*mDisplaySurface, resizeBuffers(size)).Times(1);
- mSurface.setDisplaySize(ui::Size(640, 480));
+ mSurface.setDisplaySize(size);
}
/*
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index b4a3ed1..a785968 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -179,6 +179,31 @@
return nullptr;
}
+nsecs_t DisplayDevice::getVsyncPeriodFromHWC() const {
+ const auto physicalId = getPhysicalId();
+ if (!mHwComposer.isConnected(physicalId)) {
+ return 0;
+ }
+
+ nsecs_t vsyncPeriod;
+ const auto status = mHwComposer.getDisplayVsyncPeriod(physicalId, &vsyncPeriod);
+ if (status == NO_ERROR) {
+ return vsyncPeriod;
+ }
+
+ return getActiveMode()->getFps().getPeriodNsecs();
+}
+
+nsecs_t DisplayDevice::getRefreshTimestamp() const {
+ const nsecs_t now = systemTime(CLOCK_MONOTONIC);
+ const auto vsyncPeriodNanos = getVsyncPeriodFromHWC();
+ return now - ((now - mLastHwVsync) % vsyncPeriodNanos);
+}
+
+void DisplayDevice::onVsync(nsecs_t timestamp) {
+ mLastHwVsync = timestamp;
+}
+
ui::Dataspace DisplayDevice::getCompositionDataSpace() const {
return mCompositionDisplay->getState().dataspace;
}
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index 6f07964..b4db933 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -176,6 +176,10 @@
// set-top boxes after a hotplug reconnect.
DisplayModePtr getMode(DisplayModeId) const;
+ void onVsync(nsecs_t timestamp);
+ nsecs_t getVsyncPeriodFromHWC() const;
+ nsecs_t getRefreshTimestamp() const;
+
// release HWC resources (if any) for removable displays
void disconnect();
@@ -207,6 +211,8 @@
DisplayModeId mActiveModeId;
const DisplayModes mSupportedModes;
+ std::atomic<nsecs_t> mLastHwVsync = 0;
+
// TODO(b/74619554): Remove special cases for primary display.
const bool mIsPrimary;
diff --git a/services/surfaceflinger/DisplayHardware/DisplayMode.h b/services/surfaceflinger/DisplayHardware/DisplayMode.h
index 61c1b61..31d1245 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayMode.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayMode.h
@@ -22,6 +22,7 @@
#include <android-base/stringprintf.h>
#include <android/configuration.h>
+#include <ui/Size.h>
#include <utils/Timers.h>
#include <cstddef>
@@ -113,6 +114,7 @@
int32_t getWidth() const { return mWidth; }
int32_t getHeight() const { return mHeight; }
+ ui::Size getSize() const { return {mWidth, mHeight}; }
Fps getFps() const { return mFps; }
nsecs_t getVsyncPeriod() const { return mFps.getPeriodNsecs(); }
float getDpiX() const { return mDpiX; }
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
index 3e856bb..f7fc162 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
@@ -58,11 +58,10 @@
FramebufferSurface::FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId,
const sp<IGraphicBufferConsumer>& consumer,
- uint32_t maxWidth, uint32_t maxHeight)
+ const ui::Size& size, const ui::Size& maxSize)
: ConsumerBase(consumer),
mDisplayId(displayId),
- mMaxWidth(maxWidth),
- mMaxHeight(maxHeight),
+ mMaxSize(maxSize),
mCurrentBufferSlot(-1),
mCurrentBuffer(),
mCurrentFence(Fence::NO_FENCE),
@@ -77,15 +76,14 @@
mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |
GRALLOC_USAGE_HW_RENDER |
GRALLOC_USAGE_HW_COMPOSER);
- const auto& activeMode = mHwc.getActiveMode(displayId);
- ui::Size limitedSize = limitFramebufferSize(activeMode->getWidth(), activeMode->getHeight());
+ const auto limitedSize = limitFramebufferSize(size);
mConsumer->setDefaultBufferSize(limitedSize.width, limitedSize.height);
mConsumer->setMaxAcquiredBufferCount(
SurfaceFlinger::maxFrameBufferAcquiredBuffers - 1);
}
-void FramebufferSurface::resizeBuffers(uint32_t width, uint32_t height) {
- ui::Size limitedSize = limitFramebufferSize(width, height);
+void FramebufferSurface::resizeBuffers(const ui::Size& newSize) {
+ const auto limitedSize = limitFramebufferSize(newSize);
mConsumer->setDefaultBufferSize(limitedSize.width, limitedSize.height);
}
@@ -181,24 +179,24 @@
}
}
-ui::Size FramebufferSurface::limitFramebufferSize(uint32_t width, uint32_t height) {
- ui::Size framebufferSize(width, height);
- bool wasLimited = true;
- if (width > mMaxWidth && mMaxWidth != 0) {
- float aspectRatio = float(width) / float(height);
- framebufferSize.height = mMaxWidth / aspectRatio;
- framebufferSize.width = mMaxWidth;
+ui::Size FramebufferSurface::limitFramebufferSize(const ui::Size& size) {
+ ui::Size limitedSize = size;
+ bool wasLimited = false;
+ if (size.width > mMaxSize.width && mMaxSize.width != 0) {
+ const float aspectRatio = static_cast<float>(size.width) / size.height;
+ limitedSize.height = mMaxSize.width / aspectRatio;
+ limitedSize.width = mMaxSize.width;
wasLimited = true;
}
- if (height > mMaxHeight && mMaxHeight != 0) {
- float aspectRatio = float(width) / float(height);
- framebufferSize.height = mMaxHeight;
- framebufferSize.width = mMaxHeight * aspectRatio;
+ if (size.height > mMaxSize.height && mMaxSize.height != 0) {
+ const float aspectRatio = static_cast<float>(size.width) / size.height;
+ limitedSize.height = mMaxSize.height;
+ limitedSize.width = mMaxSize.height * aspectRatio;
wasLimited = true;
}
ALOGI_IF(wasLimited, "framebuffer size has been limited to [%dx%d] from [%dx%d]",
- framebufferSize.width, framebufferSize.height, width, height);
- return framebufferSize;
+ limitedSize.width, limitedSize.height, size.width, size.height);
+ return limitedSize;
}
void FramebufferSurface::dumpAsString(String8& result) const {
diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
index 759943a..5d1e131 100644
--- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
+++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.h
@@ -41,8 +41,8 @@
class FramebufferSurface : public ConsumerBase, public compositionengine::DisplaySurface {
public:
FramebufferSurface(HWComposer& hwc, PhysicalDisplayId displayId,
- const sp<IGraphicBufferConsumer>& consumer, uint32_t maxWidth,
- uint32_t maxHeight);
+ const sp<IGraphicBufferConsumer>& consumer, const ui::Size& size,
+ const ui::Size& maxSize);
virtual status_t beginFrame(bool mustRecompose);
virtual status_t prepareFrame(CompositionType compositionType);
@@ -50,7 +50,7 @@
virtual void onFrameCommitted();
virtual void dumpAsString(String8& result) const;
- virtual void resizeBuffers(uint32_t width, uint32_t height);
+ virtual void resizeBuffers(const ui::Size&) override;
virtual const sp<Fence>& getClientTargetAcquireFence() const override;
@@ -62,7 +62,7 @@
virtual void dumpLocked(String8& result, const char* prefix) const;
// Limits the width and height by the maximum width specified in the constructor.
- ui::Size limitFramebufferSize(uint32_t width, uint32_t height);
+ ui::Size limitFramebufferSize(const ui::Size&);
// nextBuffer waits for and then latches the next buffer from the
// BufferQueue and releases the previously latched buffer to the
@@ -74,11 +74,7 @@
// Framebuffer size has a dimension limitation in pixels based on the graphics capabilities of
// the device.
- const uint32_t mMaxWidth;
-
- // Framebuffer size has a dimension limitation in pixels based on the graphics capabilities of
- // the device.
- const uint32_t mMaxHeight;
+ const ui::Size mMaxSize;
// mCurrentBufferIndex is the slot index of the current buffer or
// INVALID_BUFFER_SLOT to indicate that either there is no current buffer
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 46dc54e..b9a8e4b 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -223,8 +223,6 @@
__FUNCTION__, to_string(*displayId).c_str());
{
- std::lock_guard lock(displayData.lastHwVsyncLock);
-
// There have been reports of HWCs that signal several vsync events
// with the same timestamp when turning the display off and on. This
// is a bug in the HWC implementation, but filter the extra events
@@ -295,11 +293,10 @@
hal::DisplayType::PHYSICAL);
newDisplay->setConnected(true);
displayData.hwcDisplay = std::move(newDisplay);
- loadModes(displayData, hwcDisplayId);
}
int32_t HWComposer::getAttribute(hal::HWDisplayId hwcDisplayId, hal::HWConfigId configId,
- hal::Attribute attribute) {
+ hal::Attribute attribute) const {
int32_t value = 0;
auto error = static_cast<hal::Error>(
mComposer->getDisplayAttribute(hwcDisplayId, configId, attribute, &value));
@@ -308,30 +305,6 @@
return value;
}
-void HWComposer::loadModes(DisplayData& displayData, hal::HWDisplayId hwcDisplayId) {
- ALOGV("[HWC display %" PRIu64 "] %s", hwcDisplayId, __FUNCTION__);
-
- std::vector<hal::HWConfigId> configIds;
- auto error = static_cast<hal::Error>(mComposer->getDisplayConfigs(hwcDisplayId, &configIds));
- RETURN_IF_HWC_ERROR_FOR("getDisplayConfigs", error, *toPhysicalDisplayId(hwcDisplayId));
-
- displayData.modes.clear();
- for (auto configId : configIds) {
- auto mode = DisplayMode::Builder(configId)
- .setId(DisplayModeId(displayData.modes.size()))
- .setWidth(getAttribute(hwcDisplayId, configId, hal::Attribute::WIDTH))
- .setHeight(getAttribute(hwcDisplayId, configId, hal::Attribute::HEIGHT))
- .setVsyncPeriod(getAttribute(hwcDisplayId, configId,
- hal::Attribute::VSYNC_PERIOD))
- .setDpiX(getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_X))
- .setDpiY(getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_Y))
- .setConfigGroup(getAttribute(hwcDisplayId, configId,
- hal::Attribute::CONFIG_GROUP))
- .build();
- displayData.modes.push_back(std::move(mode));
- }
-}
-
HWC2::Layer* HWComposer::createLayer(HalDisplayId displayId) {
RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
@@ -348,55 +321,50 @@
RETURN_IF_HWC_ERROR(error, displayId);
}
-nsecs_t HWComposer::getRefreshTimestamp(PhysicalDisplayId displayId) const {
- RETURN_IF_INVALID_DISPLAY(displayId, 0);
- const auto& displayData = mDisplayData.at(displayId);
- // this returns the last refresh timestamp.
- // if the last one is not available, we estimate it based on
- // the refresh period and whatever closest timestamp we have.
- std::lock_guard lock(displayData.lastHwVsyncLock);
- nsecs_t now = systemTime(CLOCK_MONOTONIC);
- auto vsyncPeriodNanos = getDisplayVsyncPeriod(displayId);
- return now - ((now - displayData.lastHwVsync) % vsyncPeriodNanos);
-}
-
bool HWComposer::isConnected(PhysicalDisplayId displayId) const {
RETURN_IF_INVALID_DISPLAY(displayId, false);
return mDisplayData.at(displayId).hwcDisplay->isConnected();
}
-DisplayModes HWComposer::getModes(PhysicalDisplayId displayId) const {
+std::vector<HWComposer::HWCDisplayMode> HWComposer::getModes(PhysicalDisplayId displayId) const {
RETURN_IF_INVALID_DISPLAY(displayId, {});
- // We cache the modes when the DisplayData is created on hotplug. If the modes need to
- // change HWC will send a hotplug event which will recreate displayData.
- return mDisplayData.at(displayId).modes;
+ const auto hwcDisplayId = mDisplayData.at(displayId).hwcDisplay->getId();
+ std::vector<hal::HWConfigId> configIds;
+ auto error = static_cast<hal::Error>(mComposer->getDisplayConfigs(hwcDisplayId, &configIds));
+ RETURN_IF_HWC_ERROR_FOR("getDisplayConfigs", error, *toPhysicalDisplayId(hwcDisplayId), {});
+
+ std::vector<HWCDisplayMode> modes;
+ modes.reserve(configIds.size());
+ for (auto configId : configIds) {
+ modes.push_back(HWCDisplayMode{
+ .hwcId = configId,
+ .width = getAttribute(hwcDisplayId, configId, hal::Attribute::WIDTH),
+ .height = getAttribute(hwcDisplayId, configId, hal::Attribute::HEIGHT),
+ .vsyncPeriod = getAttribute(hwcDisplayId, configId, hal::Attribute::VSYNC_PERIOD),
+ .dpiX = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_X),
+ .dpiY = getAttribute(hwcDisplayId, configId, hal::Attribute::DPI_Y),
+ .configGroup = getAttribute(hwcDisplayId, configId, hal::Attribute::CONFIG_GROUP),
+ });
+ }
+
+ return modes;
}
-DisplayModePtr HWComposer::getActiveMode(PhysicalDisplayId displayId) const {
- RETURN_IF_INVALID_DISPLAY(displayId, nullptr);
+std::optional<hal::HWConfigId> HWComposer::getActiveMode(PhysicalDisplayId displayId) const {
+ RETURN_IF_INVALID_DISPLAY(displayId, std::nullopt);
const auto hwcId = *fromPhysicalDisplayId(displayId);
ALOGV("[%" PRIu64 "] getActiveMode", hwcId);
hal::HWConfigId configId;
auto error = static_cast<hal::Error>(mComposer->getActiveConfig(hwcId, &configId));
- const auto& modes = mDisplayData.at(displayId).modes;
if (error == hal::Error::BAD_CONFIG) {
LOG_DISPLAY_ERROR(displayId, "No active mode");
- return nullptr;
+ return std::nullopt;
}
- RETURN_IF_HWC_ERROR(error, displayId, nullptr);
-
- const auto it = std::find_if(modes.begin(), modes.end(),
- [configId](auto mode) { return mode->getHwcId() == configId; });
- if (it == modes.end()) {
- LOG_DISPLAY_ERROR(displayId, "Unknown mode");
- return nullptr;
- }
-
- return *it;
+ return configId;
}
// Composer 2.4
@@ -421,27 +389,20 @@
return mDisplayData.at(displayId).hwcDisplay->isVsyncPeriodSwitchSupported();
}
-nsecs_t HWComposer::getDisplayVsyncPeriod(PhysicalDisplayId displayId) const {
+status_t HWComposer::getDisplayVsyncPeriod(PhysicalDisplayId displayId,
+ nsecs_t* outVsyncPeriod) const {
RETURN_IF_INVALID_DISPLAY(displayId, 0);
- if (isVsyncPeriodSwitchSupported(displayId)) {
- const auto hwcId = *fromPhysicalDisplayId(displayId);
- Hwc2::VsyncPeriodNanos vsyncPeriodNanos = 0;
- auto error =
- static_cast<hal::Error>(mComposer->getDisplayVsyncPeriod(hwcId, &vsyncPeriodNanos));
- RETURN_IF_HWC_ERROR(error, displayId, 0);
- return static_cast<nsecs_t>(vsyncPeriodNanos);
+ if (!isVsyncPeriodSwitchSupported(displayId)) {
+ return INVALID_OPERATION;
}
-
- // Get the default vsync period
- auto mode = getActiveMode(displayId);
-
- if (!mode) {
- // HWC has updated the display modes and hasn't notified us yet.
- RETURN_IF_HWC_ERROR(hal::Error::BAD_CONFIG, displayId, 0);
- }
-
- return mode->getVsyncPeriod();
+ const auto hwcId = *fromPhysicalDisplayId(displayId);
+ Hwc2::VsyncPeriodNanos vsyncPeriodNanos = 0;
+ auto error =
+ static_cast<hal::Error>(mComposer->getDisplayVsyncPeriod(hwcId, &vsyncPeriodNanos));
+ RETURN_IF_HWC_ERROR(error, displayId, 0);
+ *outVsyncPeriod = static_cast<nsecs_t>(vsyncPeriodNanos);
+ return NO_ERROR;
}
std::vector<ui::ColorMode> HWComposer::getColorModes(PhysicalDisplayId displayId) const {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 1ffe276..f9c8e2e 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -83,6 +83,16 @@
ClientTargetProperty clientTargetProperty;
};
+ struct HWCDisplayMode {
+ hal::HWConfigId hwcId;
+ int32_t width = -1;
+ int32_t height = -1;
+ nsecs_t vsyncPeriod = -1;
+ int32_t dpiX = -1;
+ int32_t dpiY = -1;
+ int32_t configGroup = -1;
+ };
+
virtual ~HWComposer();
virtual void setConfiguration(HWC2::ComposerCallback* callback, int32_t sequenceId) = 0;
@@ -182,12 +192,11 @@
virtual bool onVsync(hal::HWDisplayId, int64_t timestamp) = 0;
virtual void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) = 0;
- virtual nsecs_t getRefreshTimestamp(PhysicalDisplayId) const = 0;
virtual bool isConnected(PhysicalDisplayId) const = 0;
- virtual DisplayModes getModes(PhysicalDisplayId) const = 0;
+ virtual std::vector<HWCDisplayMode> getModes(PhysicalDisplayId) const = 0;
- virtual DisplayModePtr getActiveMode(PhysicalDisplayId) const = 0;
+ virtual std::optional<hal::HWConfigId> getActiveMode(PhysicalDisplayId) const = 0;
virtual std::vector<ui::ColorMode> getColorModes(PhysicalDisplayId) const = 0;
@@ -197,7 +206,8 @@
// Composer 2.4
virtual DisplayConnectionType getDisplayConnectionType(PhysicalDisplayId) const = 0;
virtual bool isVsyncPeriodSwitchSupported(PhysicalDisplayId) const = 0;
- virtual nsecs_t getDisplayVsyncPeriod(PhysicalDisplayId) const = 0;
+ virtual status_t getDisplayVsyncPeriod(PhysicalDisplayId displayId,
+ nsecs_t* outVsyncPeriod) const = 0;
virtual status_t setActiveModeWithConstraints(PhysicalDisplayId, hal::HWConfigId,
const hal::VsyncPeriodChangeConstraints&,
hal::VsyncPeriodChangeTimeline* outTimeline) = 0;
@@ -314,12 +324,11 @@
bool onVsync(hal::HWDisplayId, int64_t timestamp) override;
void setVsyncEnabled(PhysicalDisplayId, hal::Vsync enabled) override;
- nsecs_t getRefreshTimestamp(PhysicalDisplayId) const override;
bool isConnected(PhysicalDisplayId) const override;
- DisplayModes getModes(PhysicalDisplayId) const override;
+ std::vector<HWCDisplayMode> getModes(PhysicalDisplayId) const override;
- DisplayModePtr getActiveMode(PhysicalDisplayId) const override;
+ std::optional<hal::HWConfigId> getActiveMode(PhysicalDisplayId) const override;
std::vector<ui::ColorMode> getColorModes(PhysicalDisplayId) const override;
@@ -328,7 +337,8 @@
// Composer 2.4
DisplayConnectionType getDisplayConnectionType(PhysicalDisplayId) const override;
bool isVsyncPeriodSwitchSupported(PhysicalDisplayId) const override;
- nsecs_t getDisplayVsyncPeriod(PhysicalDisplayId displayId) const override;
+ status_t getDisplayVsyncPeriod(PhysicalDisplayId displayId,
+ nsecs_t* outVsyncPeriod) const override;
status_t setActiveModeWithConstraints(PhysicalDisplayId, hal::HWConfigId,
const hal::VsyncPeriodChangeConstraints&,
hal::VsyncPeriodChangeTimeline* outTimeline) override;
@@ -365,7 +375,6 @@
std::unordered_map<HWC2::Layer*, sp<Fence>> releaseFences;
buffer_handle_t outbufHandle = nullptr;
sp<Fence> outbufAcquireFence = Fence::NO_FENCE;
- DisplayModes modes;
bool validateWasSkipped;
hal::Error presentError;
@@ -375,8 +384,7 @@
std::mutex vsyncEnabledLock;
hal::Vsync vsyncEnabled GUARDED_BY(vsyncEnabledLock) = hal::Vsync::DISABLE;
- mutable std::mutex lastHwVsyncLock;
- nsecs_t lastHwVsync GUARDED_BY(lastHwVsyncLock) = 0;
+ nsecs_t lastHwVsync = 0;
};
std::optional<DisplayIdentificationInfo> onHotplugConnect(hal::HWDisplayId);
@@ -384,8 +392,7 @@
bool shouldIgnoreHotplugConnect(hal::HWDisplayId, bool hasDisplayIdentificationData) const;
int32_t getAttribute(hal::HWDisplayId hwcDisplayId, hal::HWConfigId configId,
- hal::Attribute attribute);
- void loadModes(DisplayData& displayData, hal::HWDisplayId hwcDisplayId);
+ hal::Attribute attribute) const;
void loadCapabilities();
void loadLayerMetadataSupport();
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 2ac67cb..e26ab11 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -291,11 +291,11 @@
void VirtualDisplaySurface::dumpAsString(String8& /* result */) const {
}
-void VirtualDisplaySurface::resizeBuffers(const uint32_t w, const uint32_t h) {
- mQueueBufferOutput.width = w;
- mQueueBufferOutput.height = h;
- mSinkBufferWidth = w;
- mSinkBufferHeight = h;
+void VirtualDisplaySurface::resizeBuffers(const ui::Size& newSize) {
+ mQueueBufferOutput.width = newSize.width;
+ mQueueBufferOutput.height = newSize.height;
+ mSinkBufferWidth = newSize.width;
+ mSinkBufferHeight = newSize.height;
}
const sp<Fence>& VirtualDisplaySurface::getClientTargetAcquireFence() const {
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index fba0e3b..bbb6306 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -90,7 +90,7 @@
virtual status_t advanceFrame();
virtual void onFrameCommitted();
virtual void dumpAsString(String8& result) const;
- virtual void resizeBuffers(const uint32_t w, const uint32_t h);
+ virtual void resizeBuffers(const ui::Size&) override;
virtual const sp<Fence>& getClientTargetAcquireFence() const override;
private:
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index f6440d3..08a5f0f 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1000,19 +1000,6 @@
uint32_t Layer::doTransaction(uint32_t flags) {
ATRACE_CALL();
- if (mLayerDetached) {
- // Ensure BLAST buffer callbacks are processed.
- // detachChildren and mLayerDetached were implemented to avoid geometry updates
- // to layers in the cases of animation. For BufferQueue layers buffers are still
- // consumed as normal. This is useful as otherwise the client could get hung
- // inevitably waiting on a buffer to return. We recreate this semantic for BufferQueue
- // even though it is a little consistent. detachChildren is shortly slated for removal
- // by the hierarchy mirroring work so we don't need to worry about it too much.
- forceSendCallbacks();
- mCurrentState.callbackHandles = {};
- return flags;
- }
-
if (mChildrenChanged) {
flags |= eVisibleRegion;
mChildrenChanged = false;
@@ -1519,12 +1506,6 @@
void Layer::deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber) {
ATRACE_CALL();
- if (mLayerDetached) {
- // If the layer is detached, then we don't defer this transaction since we will not
- // commit the pending state while the layer is detached. Adding sync points may cause
- // the barrier layer to wait for the states to be committed before dequeuing a buffer.
- return;
- }
mCurrentState.barrierLayer_legacy = barrierLayer;
mCurrentState.barrierFrameNumber = frameNumber;
@@ -1810,10 +1791,6 @@
}
void Layer::reparentChildren(const sp<Layer>& newParent) {
- if (attachChildren()) {
- setTransactionFlags(eTransactionNeeded);
- }
-
for (const sp<Layer>& child : mCurrentChildren) {
newParent->addChild(child);
}
@@ -1849,17 +1826,6 @@
}
bool Layer::reparent(const sp<IBinder>& newParentHandle) {
- bool callSetTransactionFlags = false;
-
- // While layers are detached, we allow most operations
- // and simply halt performing the actual transaction. However
- // for reparent != null we would enter the mRemovedFromCurrentState
- // state, regardless of whether doTransaction was called, and
- // so we need to prevent the update here.
- if (mLayerDetached && newParentHandle == nullptr) {
- return false;
- }
-
sp<Layer> newParent;
if (newParentHandle != nullptr) {
auto handle = static_cast<Handle*>(newParentHandle.get());
@@ -1886,52 +1852,13 @@
} else {
onRemovedFromCurrentState();
}
-
- if (mLayerDetached) {
- mLayerDetached = false;
- callSetTransactionFlags = true;
- }
} else {
onRemovedFromCurrentState();
}
- if (attachChildren() || callSetTransactionFlags) {
- setTransactionFlags(eTransactionNeeded);
- }
return true;
}
-bool Layer::detachChildren() {
- for (const sp<Layer>& child : mCurrentChildren) {
- sp<Client> parentClient = mClientRef.promote();
- sp<Client> client(child->mClientRef.promote());
- if (client != nullptr && parentClient != client) {
- child->mLayerDetached = true;
- child->detachChildren();
- child->removeRemoteSyncPoints();
- }
- }
-
- return true;
-}
-
-bool Layer::attachChildren() {
- bool changed = false;
- for (const sp<Layer>& child : mCurrentChildren) {
- sp<Client> parentClient = mClientRef.promote();
- sp<Client> client(child->mClientRef.promote());
- if (client != nullptr && parentClient != client) {
- if (child->mLayerDetached) {
- child->mLayerDetached = false;
- child->attachChildren();
- changed = true;
- }
- }
- }
-
- return changed;
-}
-
bool Layer::setColorTransform(const mat4& matrix) {
static const mat4 identityMatrix = mat4();
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 0660a4a..4b40c8e 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -434,7 +434,6 @@
virtual bool setMetadata(const LayerMetadata& data);
virtual void setChildrenDrawingParent(const sp<Layer>&);
virtual bool reparent(const sp<IBinder>& newParentHandle);
- virtual bool detachChildren();
virtual bool setColorTransform(const mat4& matrix);
virtual mat4 getColorTransform() const;
virtual bool hasColorTransform() const;
@@ -461,7 +460,6 @@
const std::vector<sp<CallbackHandle>>& /*handles*/) {
return false;
};
- virtual void forceSendCallbacks() {}
virtual bool addFrameEvent(const sp<Fence>& /*acquireFence*/, nsecs_t /*postedTime*/,
nsecs_t /*requestedPresentTime*/) {
return false;
@@ -666,8 +664,6 @@
bool reparentChildren(const sp<IBinder>& newParentHandle);
void reparentChildren(const sp<Layer>& newParent);
- bool attachChildren();
- bool isLayerDetached() const { return mLayerDetached; }
bool setShadowRadius(float shadowRadius);
// Before color management is introduced, contents on Android have to be
@@ -1104,8 +1100,6 @@
wp<Layer> mDrawingParent;
// Can only be accessed with the SF state lock held.
- bool mLayerDetached{false};
- // Can only be accessed with the SF state lock held.
bool mChildrenChanged{false};
// Window types from WindowManager.LayoutParams
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index c12a7b1..f90c130 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -303,6 +303,10 @@
std::lock_guard<std::mutex> lock(mMutex);
const auto request = rate == 0 ? VSyncRequest::None : static_cast<VSyncRequest>(rate);
+ if (request != VSyncRequest::None && connection->resyncCallback) {
+ connection->resyncCallback();
+ }
+
if (connection->vsyncRequest != request) {
connection->vsyncRequest = request;
mCondition.notify_all();
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index a63a3d7..e9b5875 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -68,6 +68,7 @@
#include <ui/ColorSpace.h>
#include <ui/DebugUtils.h>
#include <ui/DisplayConfig.h>
+#include <ui/DisplayId.h>
#include <ui/DisplayInfo.h>
#include <ui/DisplayStatInfo.h>
#include <ui/DisplayState.h>
@@ -275,7 +276,6 @@
const String16 sAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER");
const String16 sRotateSurfaceFlinger("android.permission.ROTATE_SURFACE_FLINGER");
const String16 sReadFramebuffer("android.permission.READ_FRAME_BUFFER");
-const String16 sUseBackgroundBlur("android.permission.USE_BACKGROUND_BLUR");
const String16 sDump("android.permission.DUMP");
const char* KERNEL_IDLE_TIMER_PROP = "graphics.display.kernel_idle_timer.enabled";
@@ -333,10 +333,6 @@
PermissionCache::checkPermission(sRotateSurfaceFlinger, pid, uid);
}
-bool originalCallerCanUseBlurs(int originPid, int originUid) {
- return PermissionCache::checkPermission(sUseBackgroundBlur, originPid, originUid);
-}
-
SurfaceFlingerBE::SurfaceFlingerBE() : mHwcServiceName(getHwcServiceName()) {}
SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag)
@@ -1586,12 +1582,11 @@
}
nsecs_t SurfaceFlinger::getVsyncPeriodFromHWC() const {
- const auto displayId = getInternalDisplayIdLocked();
- if (!displayId || !getHwComposer().isConnected(*displayId)) {
- return 0;
+ if (const auto display = getDefaultDisplayDeviceLocked()) {
+ return display->getVsyncPeriodFromHWC();
}
- return getHwComposer().getDisplayVsyncPeriod(*displayId);
+ return 0;
}
void SurfaceFlinger::onVsyncReceived(int32_t sequenceId, hal::HWDisplayId hwcDisplayId,
@@ -1605,6 +1600,12 @@
return;
}
+ if (const auto displayId = getHwComposer().toPhysicalDisplayId(hwcDisplayId)) {
+ auto token = getPhysicalDisplayTokenLocked(*displayId);
+ auto display = getDisplayDeviceLocked(token);
+ display->onVsync(timestamp);
+ }
+
if (!getHwComposer().onVsync(hwcDisplayId, timestamp)) {
return;
}
@@ -1943,19 +1944,16 @@
bool SurfaceFlinger::handleMessageTransaction() {
ATRACE_CALL();
+
+ if (getTransactionFlags(eTransactionFlushNeeded)) {
+ flushTransactionQueues();
+ }
uint32_t transactionFlags = peekTransactionFlags();
-
- bool flushedATransaction = flushTransactionQueues();
-
bool runHandleTransaction =
- (transactionFlags && (transactionFlags != eTransactionFlushNeeded)) ||
- flushedATransaction ||
- mForceTraversal;
+ ((transactionFlags & (~eTransactionFlushNeeded)) != 0) || mForceTraversal;
if (runHandleTransaction) {
handleTransaction(eTransactionMask);
- } else {
- getTransactionFlags(eTransactionFlushNeeded);
}
if (transactionFlushNeeded()) {
@@ -2223,8 +2221,7 @@
} else if (isDisplayConnected) {
// The HWC doesn't support present fences, so use the refresh
// timestamp instead.
- const nsecs_t presentTime =
- getHwComposer().getRefreshTimestamp(display->getPhysicalId());
+ const nsecs_t presentTime = display->getRefreshTimestamp();
mAnimFrameTracker.setActualPresentTime(presentTime);
}
mAnimFrameTracker.advanceFrame();
@@ -2361,6 +2358,24 @@
// here the transaction has been committed
}
+DisplayModes SurfaceFlinger::loadSupportedDisplayModes(PhysicalDisplayId displayId) const {
+ const auto hwcModes = getHwComposer().getModes(displayId);
+ DisplayModes modes;
+ size_t nextModeId = 0;
+ for (const auto& hwcMode : hwcModes) {
+ modes.push_back(DisplayMode::Builder(hwcMode.hwcId)
+ .setId(DisplayModeId{nextModeId++})
+ .setWidth(hwcMode.width)
+ .setHeight(hwcMode.height)
+ .setVsyncPeriod(hwcMode.vsyncPeriod)
+ .setDpiX(hwcMode.dpiX)
+ .setDpiY(hwcMode.dpiY)
+ .setConfigGroup(hwcMode.configGroup)
+ .build());
+ }
+ return modes;
+}
+
void SurfaceFlinger::processDisplayHotplugEventsLocked() {
for (const auto& event : mPendingHotplugEvents) {
std::optional<DisplayIdentificationInfo> info =
@@ -2374,8 +2389,14 @@
const auto it = mPhysicalDisplayTokens.find(displayId);
if (event.connection == hal::Connection::CONNECTED) {
- auto supportedModes = getHwComposer().getModes(displayId);
- const auto activeMode = getHwComposer().getActiveMode(displayId);
+ auto supportedModes = loadSupportedDisplayModes(displayId);
+ const auto activeModeHwcId = getHwComposer().getActiveMode(displayId);
+ LOG_ALWAYS_FATAL_IF(!activeModeHwcId, "HWC returned no active config");
+
+ const auto activeMode = *std::find_if(supportedModes.begin(), supportedModes.end(),
+ [activeModeHwcId](const DisplayModePtr& mode) {
+ return mode->getHwcId() == *activeModeHwcId;
+ });
// TODO(b/175678215) Handle the case when activeMode is not in supportedModes
if (it == mPhysicalDisplayTokens.end()) {
@@ -2526,17 +2547,15 @@
void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,
const DisplayDeviceState& state) {
- int width = 0;
- int height = 0;
+ ui::Size resolution(0, 0);
ui::PixelFormat pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_UNKNOWN);
if (state.physical) {
- width = state.physical->activeMode->getWidth();
- height = state.physical->activeMode->getHeight();
+ resolution = state.physical->activeMode->getSize();
pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_RGBA_8888);
} else if (state.surface != nullptr) {
- int status = state.surface->query(NATIVE_WINDOW_WIDTH, &width);
+ int status = state.surface->query(NATIVE_WINDOW_WIDTH, &resolution.width);
ALOGE_IF(status != NO_ERROR, "Unable to query width (%d)", status);
- status = state.surface->query(NATIVE_WINDOW_HEIGHT, &height);
+ status = state.surface->query(NATIVE_WINDOW_HEIGHT, &resolution.height);
ALOGE_IF(status != NO_ERROR, "Unable to query height (%d)", status);
int intPixelFormat;
status = state.surface->query(NATIVE_WINDOW_FORMAT, &intPixelFormat);
@@ -2553,7 +2572,7 @@
if (const auto& physical = state.physical) {
builder.setPhysical({physical->id, physical->type});
}
- builder.setPixels(ui::Size(width, height));
+ builder.setPixels(resolution);
builder.setPixelFormat(pixelFormat);
builder.setIsSecure(state.isSecure);
builder.setLayerStackId(state.layerStack);
@@ -2588,7 +2607,8 @@
const auto physicalId = PhysicalDisplayId::tryCast(displayId);
LOG_FATAL_IF(!physicalId);
displaySurface = new FramebufferSurface(getHwComposer(), *physicalId, bqConsumer,
- maxGraphicsWidth, maxGraphicsHeight);
+ state.physical->activeMode->getSize(),
+ ui::Size(maxGraphicsWidth, maxGraphicsHeight));
producer = bqProducer;
}
@@ -2864,7 +2884,6 @@
});
}
- commitInputWindowCommands();
commitTransaction();
}
@@ -2905,11 +2924,6 @@
: nullptr);
}
-void SurfaceFlinger::commitInputWindowCommands() {
- mInputWindowCommands.merge(mPendingInputWindowCommands);
- mPendingInputWindowCommands.clear();
-}
-
void SurfaceFlinger::updateCursorAsync() {
compositionengine::CompositionRefreshArgs refreshArgs;
for (const auto& [_, display] : ON_MAIN_THREAD(mDisplays)) {
@@ -3272,17 +3286,16 @@
mForceTraversal = true;
}
-bool SurfaceFlinger::flushTransactionQueues() {
+void SurfaceFlinger::flushTransactionQueues() {
// to prevent onHandleDestroyed from being called while the lock is held,
// we must keep a copy of the transactions (specifically the composer
// states) around outside the scope of the lock
std::vector<const TransactionState> transactions;
- bool flushedATransaction = false;
{
- Mutex::Autolock _l(mStateLock);
-
- auto it = mTransactionQueues.begin();
- while (it != mTransactionQueues.end()) {
+ Mutex::Autolock _l(mQueueLock);
+ // Collect transactions from pending transaction queue.
+ auto it = mPendingTransactionQueues.begin();
+ while (it != mPendingTransactionQueues.end()) {
auto& [applyToken, transactionQueue] = *it;
while (!transactionQueue.empty()) {
@@ -3294,31 +3307,55 @@
break;
}
transactions.push_back(transaction);
- applyTransactionState(transaction.frameTimelineInfo, transaction.states,
- transaction.displays, transaction.flags,
- mPendingInputWindowCommands, transaction.desiredPresentTime,
- transaction.isAutoTimestamp, transaction.buffer,
- transaction.postTime, transaction.privileged,
- transaction.hasListenerCallbacks,
- transaction.listenerCallbacks, transaction.originPid,
- transaction.originUid, transaction.id, /*isMainThread*/ true);
transactionQueue.pop();
- flushedATransaction = true;
}
if (transactionQueue.empty()) {
- it = mTransactionQueues.erase(it);
- mTransactionCV.broadcast();
+ it = mPendingTransactionQueues.erase(it);
+ mTransactionQueueCV.broadcast();
} else {
it = std::next(it, 1);
}
}
+
+ // Collect transactions from current transaction queue or queue to pending transactions.
+ // Case 1: push to pending when transactionIsReadyToBeApplied is false.
+ // Case 2: push to pending when there exist a pending queue.
+ // Case 3: others are ready to apply.
+ while (!mTransactionQueue.empty()) {
+ const auto& transaction = mTransactionQueue.front();
+ bool pendingTransactions = mPendingTransactionQueues.find(transaction.applyToken) !=
+ mPendingTransactionQueues.end();
+ // Call transactionIsReadyToBeApplied first in case we need to
+ // incrementPendingBufferCount if the transaction contains a buffer.
+ if (!transactionIsReadyToBeApplied(transaction.isAutoTimestamp,
+ transaction.desiredPresentTime, transaction.states,
+ true) ||
+ pendingTransactions) {
+ mPendingTransactionQueues[transaction.applyToken].push(transaction);
+ } else {
+ transactions.push_back(transaction);
+ }
+ mTransactionQueue.pop();
+ }
}
- return flushedATransaction;
+
+ // Now apply all transactions.
+ Mutex::Autolock _l(mStateLock);
+ for (const auto& transaction : transactions) {
+ applyTransactionState(transaction.frameTimelineInfo, transaction.states,
+ transaction.displays, transaction.flags,
+ transaction.inputWindowCommands, transaction.desiredPresentTime,
+ transaction.isAutoTimestamp, transaction.buffer, transaction.postTime,
+ transaction.privileged, transaction.hasListenerCallbacks,
+ transaction.listenerCallbacks, transaction.originPid,
+ transaction.originUid, transaction.id);
+ }
}
bool SurfaceFlinger::transactionFlushNeeded() {
- return !mTransactionQueues.empty();
+ Mutex::Autolock _l(mQueueLock);
+ return !mPendingTransactionQueues.empty();
}
bool SurfaceFlinger::transactionIsReadyToBeApplied(bool isAutoTimestamp, int64_t desiredPresentTime,
@@ -3339,8 +3376,10 @@
continue;
}
if (s.acquireFence && s.acquireFence->getStatus() == Fence::Status::Unsignaled) {
- ready = false;
+ ready = false;
}
+
+ Mutex::Autolock _l(mStateLock);
sp<Layer> layer = nullptr;
if (s.surface) {
layer = fromHandleLocked(s.surface).promote();
@@ -3381,94 +3420,125 @@
const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) {
ATRACE_CALL();
- const int64_t postTime = systemTime();
+ {
+ Mutex::Autolock _l(mQueueLock);
- bool privileged = callingThreadHasUnscopedSurfaceFlingerAccess();
+ const int64_t postTime = systemTime();
+ bool privileged = callingThreadHasUnscopedSurfaceFlingerAccess();
- Mutex::Autolock _l(mStateLock);
+ IPCThreadState* ipc = IPCThreadState::self();
+ const int originPid = ipc->getCallingPid();
+ const int originUid = ipc->getCallingUid();
- // If its TransactionQueue already has a pending TransactionState or if it is pending
- auto itr = mTransactionQueues.find(applyToken);
- // if this is an animation frame, wait until prior animation frame has
- // been applied by SF
- if (flags & eAnimation) {
- while (itr != mTransactionQueues.end()) {
- status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
- if (CC_UNLIKELY(err != NO_ERROR)) {
- ALOGW_IF(err == TIMED_OUT,
- "setTransactionState timed out "
- "waiting for animation frame to apply");
- break;
+ // If its TransactionQueue already has a pending TransactionState or if it is pending
+ auto itr = mPendingTransactionQueues.find(applyToken);
+ // if this is an animation frame, wait until prior animation frame has
+ // been applied by SF
+ if (flags & eAnimation) {
+ while (itr != mPendingTransactionQueues.end()) {
+ status_t err = mTransactionQueueCV.waitRelative(mQueueLock, s2ns(5));
+ if (CC_UNLIKELY(err != NO_ERROR)) {
+ ALOGW_IF(err == TIMED_OUT,
+ "setTransactionState timed out "
+ "waiting for animation frame to apply");
+ break;
+ }
+ itr = mPendingTransactionQueues.find(applyToken);
}
- itr = mTransactionQueues.find(applyToken);
}
+
+ const bool pendingTransactions = itr != mPendingTransactionQueues.end();
+ // Expected present time is computed and cached on invalidate, so it may be stale.
+ if (!pendingTransactions) {
+ const auto now = systemTime();
+ const bool nextVsyncPending = now < mExpectedPresentTime.load();
+ const DisplayStatInfo stats = mScheduler->getDisplayStatInfo(now);
+ mExpectedPresentTime = calculateExpectedPresentTime(stats);
+ // The transaction might arrive just before the next vsync but after
+ // invalidate was called. In that case we need to get the next vsync
+ // afterwards.
+ if (nextVsyncPending) {
+ mExpectedPresentTime += stats.vsyncPeriod;
+ }
+ }
+
+ mTransactionQueue.emplace(frameTimelineInfo, states, displays, flags, applyToken,
+ inputWindowCommands, desiredPresentTime, isAutoTimestamp,
+ uncacheBuffer, postTime, privileged, hasListenerCallbacks,
+ listenerCallbacks, originPid, originUid, transactionId);
+
+ if (pendingTransactions ||
+ (!isAutoTimestamp && desiredPresentTime > mExpectedPresentTime.load())) {
+ setTransactionFlags(eTransactionFlushNeeded);
+ return NO_ERROR;
+ }
+
+ // TODO(b/159125966): Remove eEarlyWakeup completely as no client should use this flag
+ if (flags & eEarlyWakeup) {
+ ALOGW("eEarlyWakeup is deprecated. Use eExplicitEarlyWakeup[Start|End]");
+ }
+
+ if (!privileged && (flags & (eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd))) {
+ ALOGE("Only WindowManager is allowed to use eExplicitEarlyWakeup[Start|End] flags");
+ flags &= ~(eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd);
+ }
+
+ const auto schedule = [](uint32_t flags) {
+ if (flags & eEarlyWakeup) return TransactionSchedule::Early;
+ if (flags & eExplicitEarlyWakeupEnd) return TransactionSchedule::EarlyEnd;
+ if (flags & eExplicitEarlyWakeupStart) return TransactionSchedule::EarlyStart;
+ return TransactionSchedule::Late;
+ }(flags);
+ setTransactionFlags(eTransactionFlushNeeded, schedule);
}
- const bool pendingTransactions = itr != mTransactionQueues.end();
- // Expected present time is computed and cached on invalidate, so it may be stale.
- if (!pendingTransactions) {
- const auto now = systemTime();
- const bool nextVsyncPending = now < mExpectedPresentTime.load();
- const DisplayStatInfo stats = mScheduler->getDisplayStatInfo(now);
- mExpectedPresentTime = calculateExpectedPresentTime(stats);
- // The transaction might arrive just before the next vsync but after
- // invalidate was called. In that case we need to get the next vsync
- // afterwards.
- if (nextVsyncPending) {
- mExpectedPresentTime += stats.vsyncPeriod;
- }
- }
-
- IPCThreadState* ipc = IPCThreadState::self();
- const int originPid = ipc->getCallingPid();
- const int originUid = ipc->getCallingUid();
-
- // Call transactionIsReadyToBeApplied first in case we need to incrementPendingBufferCount
- // if the transaction contains a buffer.
- if (!transactionIsReadyToBeApplied(isAutoTimestamp, desiredPresentTime, states, true) ||
- pendingTransactions) {
- mTransactionQueues[applyToken].emplace(frameTimelineInfo, states, displays, flags,
- desiredPresentTime, isAutoTimestamp, uncacheBuffer,
- postTime, privileged, hasListenerCallbacks,
- listenerCallbacks, originPid, originUid,
- transactionId);
- setTransactionFlags(eTransactionFlushNeeded);
+ // if this is a synchronous transaction, wait for it to take effect
+ // before returning.
+ const bool synchronous = flags & eSynchronous;
+ const bool syncInput = inputWindowCommands.syncInputWindows;
+ if (!synchronous && !syncInput) {
return NO_ERROR;
}
- applyTransactionState(frameTimelineInfo, states, displays, flags, inputWindowCommands,
- desiredPresentTime, isAutoTimestamp, uncacheBuffer, postTime, privileged,
- hasListenerCallbacks, listenerCallbacks, originPid, originUid,
- transactionId, /*isMainThread*/ false);
+ Mutex::Autolock _l(mStateLock);
+ if (synchronous) {
+ mTransactionPending = true;
+ }
+ if (syncInput) {
+ mPendingSyncInputWindows = true;
+ }
+
+ // applyTransactionState can be called by either the main SF thread or by
+ // another process through setTransactionState. While a given process may wish
+ // to wait on synchronous transactions, the main SF thread should never
+ // be blocked. Therefore, we only wait if isMainThread is false.
+ while (mTransactionPending || mPendingSyncInputWindows) {
+ status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
+ if (CC_UNLIKELY(err != NO_ERROR)) {
+ // just in case something goes wrong in SF, return to the
+ // called after a few seconds.
+ ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
+ mTransactionPending = false;
+ mPendingSyncInputWindows = false;
+ break;
+ }
+ }
+
return NO_ERROR;
}
-void SurfaceFlinger::applyTransactionState(
- const FrameTimelineInfo& frameTimelineInfo, const Vector<ComposerState>& states,
- const Vector<DisplayState>& displays, uint32_t flags,
- const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime,
- bool isAutoTimestamp, const client_cache_t& uncacheBuffer, const int64_t postTime,
- bool privileged, bool hasListenerCallbacks,
- const std::vector<ListenerCallbacks>& listenerCallbacks, int originPid, int originUid,
- uint64_t transactionId, bool isMainThread) {
+void SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelineInfo,
+ const Vector<ComposerState>& states,
+ const Vector<DisplayState>& displays, uint32_t flags,
+ const InputWindowCommands& inputWindowCommands,
+ const int64_t desiredPresentTime, bool isAutoTimestamp,
+ const client_cache_t& uncacheBuffer,
+ const int64_t postTime, bool privileged,
+ bool hasListenerCallbacks,
+ const std::vector<ListenerCallbacks>& listenerCallbacks,
+ int originPid, int originUid, uint64_t transactionId) {
uint32_t transactionFlags = 0;
- if (flags & eAnimation) {
- // For window updates that are part of an animation we must wait for
- // previous animation "frames" to be handled.
- while (!isMainThread && mAnimTransactionPending) {
- status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
- if (CC_UNLIKELY(err != NO_ERROR)) {
- // just in case something goes wrong in SF, return to the
- // caller after a few seconds.
- ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out "
- "waiting for previous animation frame");
- mAnimTransactionPending = false;
- break;
- }
- }
- }
-
for (const DisplayState& display : displays) {
transactionFlags |= setDisplayStateLocked(display);
}
@@ -3486,8 +3556,7 @@
for (const ComposerState& state : states) {
clientStateFlags |=
setClientStateLocked(frameTimelineInfo, state, desiredPresentTime, isAutoTimestamp,
- postTime, privileged, listenerCallbacksWithSurfaces, originPid,
- originUid);
+ postTime, privileged, listenerCallbacksWithSurfaces);
if ((flags & eAnimation) && state.state.surface) {
if (const auto layer = fromHandleLocked(state.state.surface).promote(); layer) {
mScheduler->recordLayerHistory(layer.get(),
@@ -3527,80 +3596,25 @@
transactionFlags = eTransactionNeeded;
}
- // If we are on the main thread, we are about to preform a traversal. Clear the traversal bit
- // so we don't have to wake up again next frame to preform an uneeded traversal.
- if (isMainThread && (transactionFlags & eTraversalNeeded)) {
- transactionFlags = transactionFlags & (~eTraversalNeeded);
- mForceTraversal = true;
- }
-
- const auto schedule = [](uint32_t flags) {
- if (flags & eEarlyWakeup) return TransactionSchedule::Early;
- if (flags & eExplicitEarlyWakeupEnd) return TransactionSchedule::EarlyEnd;
- if (flags & eExplicitEarlyWakeupStart) return TransactionSchedule::EarlyStart;
- return TransactionSchedule::Late;
- }(flags);
-
if (transactionFlags) {
if (mInterceptor->isEnabled()) {
mInterceptor->saveTransaction(states, mCurrentState.displays, displays, flags,
originPid, originUid, transactionId);
}
- // TODO(b/159125966): Remove eEarlyWakeup completly as no client should use this flag
- if (flags & eEarlyWakeup) {
- ALOGW("eEarlyWakeup is deprecated. Use eExplicitEarlyWakeup[Start|End]");
+ // We are on the main thread, we are about to preform a traversal. Clear the traversal bit
+ // so we don't have to wake up again next frame to preform an unnecessary traversal.
+ if (transactionFlags & eTraversalNeeded) {
+ transactionFlags = transactionFlags & (~eTraversalNeeded);
+ mForceTraversal = true;
}
-
- if (!privileged && (flags & (eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd))) {
- ALOGE("Only WindowManager is allowed to use eExplicitEarlyWakeup[Start|End] flags");
- flags &= ~(eExplicitEarlyWakeupStart | eExplicitEarlyWakeupEnd);
+ if (transactionFlags) {
+ setTransactionFlags(transactionFlags);
}
- // this triggers the transaction
- setTransactionFlags(transactionFlags, schedule);
-
if (flags & eAnimation) {
mAnimTransactionPending = true;
}
-
- // if this is a synchronous transaction, wait for it to take effect
- // before returning.
- const bool synchronous = flags & eSynchronous;
- const bool syncInput = inputWindowCommands.syncInputWindows;
- if (!synchronous && !syncInput) {
- return;
- }
-
- if (synchronous) {
- mTransactionPending = true;
- }
- if (syncInput) {
- mPendingSyncInputWindows = true;
- }
-
-
- // applyTransactionState can be called by either the main SF thread or by
- // another process through setTransactionState. While a given process may wish
- // to wait on synchronous transactions, the main SF thread should never
- // be blocked. Therefore, we only wait if isMainThread is false.
- while (!isMainThread && (mTransactionPending || mPendingSyncInputWindows)) {
- status_t err = mTransactionCV.waitRelative(mStateLock, s2ns(5));
- if (CC_UNLIKELY(err != NO_ERROR)) {
- // just in case something goes wrong in SF, return to the
- // called after a few seconds.
- ALOGW_IF(err == TIMED_OUT, "setTransactionState timed out!");
- mTransactionPending = false;
- mPendingSyncInputWindows = false;
- break;
- }
- }
- } else {
- // Update VsyncModulator state machine even if transaction is not needed.
- if (schedule == TransactionSchedule::EarlyStart ||
- schedule == TransactionSchedule::EarlyEnd) {
- modulateVsync(&VsyncModulator::setTransactionSchedule, schedule);
- }
}
}
@@ -3667,8 +3681,7 @@
uint32_t SurfaceFlinger::setClientStateLocked(
const FrameTimelineInfo& frameTimelineInfo, const ComposerState& composerState,
int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, bool privileged,
- std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>& listenerCallbacks,
- int originPid, int originUid) {
+ std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>& listenerCallbacks) {
const layer_state_t& s = composerState.state;
for (auto& listener : s.listeners) {
@@ -3814,14 +3827,10 @@
if (layer->setCornerRadius(s.cornerRadius))
flags |= eTraversalNeeded;
}
-
- if (what & layer_state_t::eBackgroundBlurRadiusChanged && !mDisableBlurs && mSupportsBlur &&
- originalCallerCanUseBlurs(originPid, originUid)) {
+ if (what & layer_state_t::eBackgroundBlurRadiusChanged && !mDisableBlurs && mSupportsBlur) {
if (layer->setBackgroundBlurRadius(s.backgroundBlurRadius)) flags |= eTraversalNeeded;
}
-
- if (what & layer_state_t::eBlurRegionsChanged &&
- originalCallerCanUseBlurs(originPid, originUid)) {
+ if (what & layer_state_t::eBlurRegionsChanged) {
if (layer->setBlurRegions(s.blurRegions)) flags |= eTraversalNeeded;
}
if (what & layer_state_t::eLayerStackChanged) {
@@ -3855,9 +3864,6 @@
flags |= eTransactionNeeded|eTraversalNeeded;
}
}
- if (what & layer_state_t::eDetachChildren) {
- layer->detachChildren();
- }
if (what & layer_state_t::eTransformChanged) {
if (layer->setTransform(s.transform)) flags |= eTraversalNeeded;
}
@@ -3999,7 +4005,7 @@
}
uint32_t SurfaceFlinger::addInputWindowCommands(const InputWindowCommands& inputWindowCommands) {
- bool hasChanges = mPendingInputWindowCommands.merge(inputWindowCommands);
+ bool hasChanges = mInputWindowCommands.merge(inputWindowCommands);
return hasChanges ? eTraversalNeeded : 0;
}
@@ -4264,9 +4270,11 @@
d.width = 0;
d.height = 0;
displays.add(d);
- setTransactionState(FrameTimelineInfo{}, state, displays, 0, nullptr,
- mPendingInputWindowCommands, systemTime(), true, {}, false, {},
- 0 /* Undefined transactionId */);
+
+ // It should be on the main thread, apply it directly.
+ applyTransactionState(FrameTimelineInfo{}, state, displays, 0, mInputWindowCommands,
+ systemTime(), true, {}, systemTime(), true, false, {}, getpid(), getuid(),
+ 0 /* Undefined transactionId */);
setPowerModeInternal(display, hal::PowerMode::ON);
const nsecs_t vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
@@ -4843,15 +4851,12 @@
" gpu_to_cpu_unsupported : %d\n",
mTransactionFlags.load(), !mGpuToCpuSupported);
- if (const auto displayId = getInternalDisplayIdLocked();
- displayId && getHwComposer().isConnected(*displayId)) {
- const auto activeConfig = getHwComposer().getActiveMode(*displayId);
+ if (const auto display = getDefaultDisplayDeviceLocked()) {
std::string fps, xDpi, yDpi;
- if (activeConfig) {
- const auto vsyncPeriod = getHwComposer().getDisplayVsyncPeriod(*displayId);
- fps = base::StringPrintf("%s", to_string(Fps::fromPeriodNsecs(vsyncPeriod)).c_str());
- xDpi = base::StringPrintf("%.2f", activeConfig->getDpiX());
- yDpi = base::StringPrintf("%.2f", activeConfig->getDpiY());
+ if (const auto activeMode = display->getActiveMode()) {
+ fps = to_string(activeMode->getFps());
+ xDpi = base::StringPrintf("%.2f", activeMode->getDpiX());
+ yDpi = base::StringPrintf("%.2f", activeMode->getDpiY());
} else {
fps = "unknown";
xDpi = "unknown";
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index ec73b09..66fc4f0 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -345,8 +345,8 @@
virtual uint32_t setClientStateLocked(
const FrameTimelineInfo& info, const ComposerState& composerState,
int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, bool privileged,
- std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>& listenerCallbacks,
- int originPid, int originUid) REQUIRES(mStateLock);
+ std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>& listenerCallbacks)
+ REQUIRES(mStateLock);
virtual void commitTransactionLocked();
// Used internally by computeLayerBounds() to gets the clip rectangle to use for the
@@ -438,15 +438,18 @@
TransactionState(const FrameTimelineInfo& frameTimelineInfo,
const Vector<ComposerState>& composerStates,
const Vector<DisplayState>& displayStates, uint32_t transactionFlags,
- int64_t desiredPresentTime, bool isAutoTimestamp,
- const client_cache_t& uncacheBuffer, int64_t postTime, bool privileged,
- bool hasListenerCallbacks,
+ const sp<IBinder>& applyToken,
+ const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
+ bool isAutoTimestamp, const client_cache_t& uncacheBuffer,
+ int64_t postTime, bool privileged, bool hasListenerCallbacks,
std::vector<ListenerCallbacks> listenerCallbacks, int originPid,
int originUid, uint64_t transactionId)
: frameTimelineInfo(frameTimelineInfo),
states(composerStates),
displays(displayStates),
flags(transactionFlags),
+ applyToken(applyToken),
+ inputWindowCommands(inputWindowCommands),
desiredPresentTime(desiredPresentTime),
isAutoTimestamp(isAutoTimestamp),
buffer(uncacheBuffer),
@@ -462,6 +465,8 @@
Vector<ComposerState> states;
Vector<DisplayState> displays;
uint32_t flags;
+ sp<IBinder> applyToken;
+ InputWindowCommands inputWindowCommands;
const int64_t desiredPresentTime;
const bool isAutoTimestamp;
client_cache_t buffer;
@@ -736,10 +741,10 @@
const client_cache_t& uncacheBuffer, const int64_t postTime,
bool privileged, bool hasListenerCallbacks,
const std::vector<ListenerCallbacks>& listenerCallbacks,
- int originPid, int originUid, uint64_t transactionId,
- bool isMainThread = false) REQUIRES(mStateLock);
- // Returns true if at least one transaction was flushed
- bool flushTransactionQueues();
+ int originPid, int originUid, uint64_t transactionId)
+ REQUIRES(mStateLock);
+ // flush pending transaction that was presented after desiredPresentTime.
+ void flushTransactionQueues();
// Returns true if there is at least one transaction that needs to be flushed
bool transactionFlushNeeded();
uint32_t getTransactionFlags(uint32_t flags);
@@ -757,7 +762,7 @@
void commitOffscreenLayers();
bool transactionIsReadyToBeApplied(bool isAutoTimestamp, int64_t desiredPresentTime,
const Vector<ComposerState>& states,
- bool updateTransactionCounters = false) REQUIRES(mStateLock);
+ bool updateTransactionCounters = false);
uint32_t setDisplayStateLocked(const DisplayState& s) REQUIRES(mStateLock);
uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands)
REQUIRES(mStateLock);
@@ -897,6 +902,7 @@
/*
* Display management
*/
+ DisplayModes loadSupportedDisplayModes(PhysicalDisplayId) const;
sp<DisplayDevice> setupNewDisplayDeviceInternal(
const wp<IBinder>& displayToken,
std::shared_ptr<compositionengine::Display> compositionDisplay,
@@ -1177,8 +1183,11 @@
uint32_t mTexturePoolSize = 0;
std::vector<uint32_t> mTexturePool;
- std::unordered_map<sp<IBinder>, std::queue<TransactionState>, IListenerHash> mTransactionQueues;
-
+ mutable Mutex mQueueLock;
+ Condition mTransactionQueueCV;
+ std::unordered_map<sp<IBinder>, std::queue<TransactionState>, IListenerHash>
+ mPendingTransactionQueues GUARDED_BY(mQueueLock);
+ std::queue<TransactionState> mTransactionQueue GUARDED_BY(mQueueLock);
/*
* Feature prototyping
*/
@@ -1256,7 +1265,6 @@
const float mEmulatedDisplayDensity;
sp<os::IInputFlinger> mInputFlinger;
- InputWindowCommands mPendingInputWindowCommands GUARDED_BY(mStateLock);
// Should only be accessed by the main thread.
InputWindowCommands mInputWindowCommands;
diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp
index 3548923..61005c9 100644
--- a/services/surfaceflinger/SurfaceInterceptor.cpp
+++ b/services/surfaceflinger/SurfaceInterceptor.cpp
@@ -150,7 +150,6 @@
layer_state_t::eLayerHidden | layer_state_t::eLayerOpaque |
layer_state_t::eLayerSecure);
addReparentLocked(transaction, layerId, getLayerIdFromWeakRef(layer->mCurrentParent));
- addDetachChildrenLocked(transaction, layerId, layer->isLayerDetached());
addRelativeParentLocked(transaction, layerId,
getLayerIdFromWeakRef(layer->mCurrentState.zOrderRelativeOf),
layer->mCurrentState.z);
@@ -409,13 +408,6 @@
overrideChange->set_parent_id(parentId);
}
-void SurfaceInterceptor::addDetachChildrenLocked(Transaction* transaction, int32_t layerId,
- bool detached) {
- SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
- DetachChildrenChange* overrideChange(change->mutable_detach_children());
- overrideChange->set_detach_children(detached);
-}
-
void SurfaceInterceptor::addRelativeParentLocked(Transaction* transaction, int32_t layerId,
int32_t parentId, int z) {
SurfaceChange* change(createSurfaceChangeLocked(transaction, layerId));
@@ -498,9 +490,6 @@
addReparentChildrenLocked(transaction, layerId,
getLayerIdFromHandle(state.reparentSurfaceControl->getHandle()));
}
- if (state.what & layer_state_t::eDetachChildren) {
- addDetachChildrenLocked(transaction, layerId, true);
- }
if (state.what & layer_state_t::eRelativeLayerChanged) {
addRelativeParentLocked(transaction, layerId,
getLayerIdFromHandle(
diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h
index 3df79c6..3e27e83 100644
--- a/services/surfaceflinger/SurfaceInterceptor.h
+++ b/services/surfaceflinger/SurfaceInterceptor.h
@@ -177,7 +177,6 @@
uint64_t transactionId);
void addReparentLocked(Transaction* transaction, int32_t layerId, int32_t parentId);
void addReparentChildrenLocked(Transaction* transaction, int32_t layerId, int32_t parentId);
- void addDetachChildrenLocked(Transaction* transaction, int32_t layerId, bool detached);
void addRelativeParentLocked(Transaction* transaction, int32_t layerId, int32_t parentId,
int z);
void addShadowRadiusLocked(Transaction* transaction, int32_t layerId, float shadowRadius);
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp
index e8b24b4..cfaf229 100644
--- a/services/surfaceflinger/tests/Android.bp
+++ b/services/surfaceflinger/tests/Android.bp
@@ -21,7 +21,6 @@
"CommonTypes_test.cpp",
"Credentials_test.cpp",
"DereferenceSurfaceControl_test.cpp",
- "DetachChildren_test.cpp",
"DisplayConfigs_test.cpp",
"EffectLayer_test.cpp",
"InvalidHandles_test.cpp",
diff --git a/services/surfaceflinger/tests/DetachChildren_test.cpp b/services/surfaceflinger/tests/DetachChildren_test.cpp
deleted file mode 100644
index abf8b1a..0000000
--- a/services/surfaceflinger/tests/DetachChildren_test.cpp
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Copyright (C) 2020 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 clang diagnostic push
-#pragma clang diagnostic ignored "-Wconversion"
-
-#include "LayerTransactionTest.h"
-
-namespace android {
-
-class DetachChildren : public LayerTransactionTest {
-protected:
- virtual void SetUp() {
- LayerTransactionTest::SetUp();
-
- mMainSurface = createLayer(String8("Main Test Surface"), mMainSurfaceBounds.width(),
- mMainSurfaceBounds.height(), 0, mBlackBgSurface.get());
-
- ASSERT_TRUE(mMainSurface != nullptr);
- ASSERT_TRUE(mMainSurface->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(mMainSurface, mMainSurfaceColor);
-
- asTransaction([&](Transaction& t) {
- t.setLayer(mMainSurface, INT32_MAX - 1)
- .setPosition(mMainSurface, mMainSurfaceBounds.left, mMainSurfaceBounds.top)
- .show(mMainSurface);
- });
- }
-
- virtual void TearDown() {
- LayerTransactionTest::TearDown();
- mMainSurface = 0;
- }
-
- sp<SurfaceControl> mMainSurface;
- Color mMainSurfaceColor = {195, 63, 63, 255};
- Rect mMainSurfaceBounds = Rect(64, 64, 128, 128);
- std::unique_ptr<ScreenCapture> mCapture;
-};
-
-TEST_F(DetachChildren, RelativesAreNotDetached) {
- Color relativeColor = {10, 10, 10, 255};
- Rect relBounds = Rect(64, 64, 74, 74);
-
- sp<SurfaceControl> relative =
- createLayer(String8("relativeTestSurface"), relBounds.width(), relBounds.height(), 0);
- TransactionUtils::fillSurfaceRGBA8(relative, relativeColor);
-
- Transaction{}
- .setRelativeLayer(relative, mMainSurface, 1)
- .setPosition(relative, relBounds.left, relBounds.top)
- .apply();
-
- {
- // The relative should be on top of the FG control.
- mCapture = screenshot();
- mCapture->expectColor(relBounds, relativeColor);
- }
- Transaction{}.detachChildren(mMainSurface).apply();
-
- {
- // Nothing should change at this point.
- mCapture = screenshot();
- mCapture->expectColor(relBounds, relativeColor);
- }
-
- Transaction{}.hide(relative).apply();
-
- {
- // Ensure that the relative was actually hidden, rather than
- // being left in the detached but visible state.
- mCapture = screenshot();
- mCapture->expectColor(mMainSurfaceBounds, mMainSurfaceColor);
- }
-}
-
-TEST_F(DetachChildren, DetachChildrenSameClient) {
- Color childColor = {200, 200, 200, 255};
- Rect childBounds = Rect(74, 74, 84, 84);
- sp<SurfaceControl> child = createLayer(String8("Child surface"), childBounds.width(),
- childBounds.height(), 0, mMainSurface.get());
- ASSERT_TRUE(child->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(child, childColor);
-
- asTransaction([&](Transaction& t) {
- t.show(child);
- t.setPosition(child, childBounds.left - mMainSurfaceBounds.left,
- childBounds.top - mMainSurfaceBounds.top);
- });
-
- {
- mCapture = screenshot();
- // Expect main color around the child surface
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectColor(childBounds, childColor);
- }
-
- asTransaction([&](Transaction& t) { t.detachChildren(mMainSurface); });
-
- asTransaction([&](Transaction& t) { t.hide(child); });
-
- // Since the child has the same client as the parent, it will not get
- // detached and will be hidden.
- {
- mCapture = screenshot();
- mCapture->expectColor(mMainSurfaceBounds, mMainSurfaceColor);
- }
-}
-
-TEST_F(DetachChildren, DetachChildrenDifferentClient) {
- Color childColor = {200, 200, 200, 255};
- Rect childBounds = Rect(74, 74, 84, 84);
-
- sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
- sp<SurfaceControl> childNewClient =
- createSurface(newComposerClient, "New Child Test Surface", childBounds.width(),
- childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
- ASSERT_TRUE(childNewClient->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor);
-
- asTransaction([&](Transaction& t) {
- t.show(childNewClient);
- t.setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left,
- childBounds.top - mMainSurfaceBounds.top);
- });
-
- {
- mCapture = screenshot();
- // Expect main color around the child surface
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectColor(childBounds, childColor);
- }
-
- asTransaction([&](Transaction& t) { t.detachChildren(mMainSurface); });
-
- asTransaction([&](Transaction& t) { t.hide(childNewClient); });
-
- // Nothing should have changed.
- {
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectColor(childBounds, childColor);
- }
-}
-
-TEST_F(DetachChildren, DetachChildrenThenAttach) {
- Color childColor = {200, 200, 200, 255};
- Rect childBounds = Rect(74, 74, 84, 84);
-
- sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
- sp<SurfaceControl> childNewClient =
- createSurface(newComposerClient, "New Child Test Surface", childBounds.width(),
- childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
- ASSERT_TRUE(childNewClient->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor);
-
- Transaction()
- .show(childNewClient)
- .setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left,
- childBounds.top - mMainSurfaceBounds.top)
- .apply();
-
- {
- mCapture = screenshot();
- // Expect main color around the child surface
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectColor(childBounds, childColor);
- }
-
- Transaction().detachChildren(mMainSurface).apply();
- Transaction().hide(childNewClient).apply();
-
- // Nothing should have changed.
- {
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectColor(childBounds, childColor);
- }
-
- Color newParentColor = Color::RED;
- Rect newParentBounds = Rect(20, 20, 52, 52);
- sp<SurfaceControl> newParentSurface =
- createLayer(String8("New Parent Surface"), newParentBounds.width(),
- newParentBounds.height(), 0);
- TransactionUtils::fillSurfaceRGBA8(newParentSurface, newParentColor);
- Transaction()
- .setLayer(newParentSurface, INT32_MAX - 1)
- .show(newParentSurface)
- .setPosition(newParentSurface, newParentBounds.left, newParentBounds.top)
- .reparent(childNewClient, newParentSurface)
- .apply();
- {
- mCapture = screenshot();
- // Child is now hidden.
- mCapture->expectColor(newParentBounds, newParentColor);
- }
-}
-
-TEST_F(DetachChildren, DetachChildrenWithDeferredTransaction) {
- Color childColor = {200, 200, 200, 255};
- Rect childBounds = Rect(74, 74, 84, 84);
-
- sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
- sp<SurfaceControl> childNewClient =
- createSurface(newComposerClient, "New Child Test Surface", childBounds.width(),
- childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
- ASSERT_TRUE(childNewClient->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor);
-
- Transaction()
- .show(childNewClient)
- .setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left,
- childBounds.top - mMainSurfaceBounds.top)
- .apply();
-
- {
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectColor(childBounds, childColor);
- }
-
- Transaction()
- .deferTransactionUntil_legacy(childNewClient, mMainSurface,
- mMainSurface->getSurface()->getNextFrameNumber())
- .apply();
- Transaction().detachChildren(mMainSurface).apply();
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mMainSurface, Color::RED,
- mMainSurfaceBounds.width(),
- mMainSurfaceBounds.height()));
-
- // BufferLayer can still dequeue buffers even though there's a detached layer with a
- // deferred transaction.
- {
- SCOPED_TRACE("new buffer");
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, Color::RED);
- mCapture->expectColor(childBounds, childColor);
- }
-}
-
-/**
- * Tests that a deferring transaction on an already detached layer will be dropped gracefully and
- * allow the barrier layer to dequeue buffers.
- *
- * Fixes b/150924737 - buffer cannot be latched because it waits for a detached layer
- * to commit its pending states.
- */
-TEST_F(DetachChildren, DeferredTransactionOnDetachedChildren) {
- Color childColor = {200, 200, 200, 255};
- Rect childBounds = Rect(74, 74, 84, 84);
-
- sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
- sp<SurfaceControl> childNewClient =
- createSurface(newComposerClient, "New Child Test Surface", childBounds.width(),
- childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
- ASSERT_TRUE(childNewClient->isValid());
-
- TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor);
-
- Transaction()
- .show(childNewClient)
- .setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left,
- childBounds.top - mMainSurfaceBounds.top)
- .apply();
-
- {
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectColor(childBounds, childColor);
- }
-
- Transaction().detachChildren(mMainSurface).apply();
- Transaction()
- .setCrop_legacy(childNewClient, {0, 0, childBounds.width(), childBounds.height()})
- .deferTransactionUntil_legacy(childNewClient, mMainSurface,
- mMainSurface->getSurface()->getNextFrameNumber())
- .apply();
-
- ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mMainSurface, Color::RED,
- mMainSurfaceBounds.width(),
- mMainSurfaceBounds.height()));
-
- // BufferLayer can still dequeue buffers even though there's a detached layer with a
- // deferred transaction.
- {
- SCOPED_TRACE("new buffer");
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, Color::RED);
- mCapture->expectColor(childBounds, childColor);
- }
-}
-
-TEST_F(DetachChildren, ReparentParentLayerOfDetachedChildren) {
- Color childColor = {200, 200, 200, 255};
- Rect childBounds = Rect(74, 74, 94, 94);
- Color grandchildColor = Color::RED;
- Rect grandchildBounds = Rect(80, 80, 90, 90);
-
- sp<SurfaceComposerClient> newClient1 = new SurfaceComposerClient;
- sp<SurfaceComposerClient> newClient2 = new SurfaceComposerClient;
-
- sp<SurfaceControl> childSurface =
- createSurface(newClient1, "Child surface", childBounds.width(), childBounds.height(),
- PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get());
- sp<SurfaceControl> grandchildSurface =
- createSurface(newClient2, "Grandchild Surface", grandchildBounds.width(),
- grandchildBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, childSurface.get());
-
- TransactionUtils::fillSurfaceRGBA8(childSurface, childColor);
- TransactionUtils::fillSurfaceRGBA8(grandchildSurface, grandchildColor);
-
- Transaction()
- .show(childSurface)
- .show(grandchildSurface)
- .setPosition(childSurface, childBounds.left - mMainSurfaceBounds.left,
- childBounds.top - mMainSurfaceBounds.top)
- .setPosition(grandchildSurface, grandchildBounds.left - childBounds.left,
- grandchildBounds.top - childBounds.top)
- .apply();
-
- {
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectBorder(grandchildBounds, childColor);
- mCapture->expectColor(grandchildBounds, grandchildColor);
- }
-
- Transaction().detachChildren(childSurface).apply();
-
- // Remove main surface offscreen
- Transaction().reparent(mMainSurface, nullptr).apply();
- {
- mCapture = screenshot();
- mCapture->expectColor(mMainSurfaceBounds, Color::BLACK);
- }
-
- Transaction().reparent(mMainSurface, mBlackBgSurface).apply();
- {
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectBorder(grandchildBounds, childColor);
- mCapture->expectColor(grandchildBounds, grandchildColor);
- }
-
- Transaction().hide(grandchildSurface).apply();
-
- // grandchild is still detached so it will not hide
- {
- mCapture = screenshot();
- mCapture->expectBorder(childBounds, mMainSurfaceColor);
- mCapture->expectBorder(grandchildBounds, childColor);
- mCapture->expectColor(grandchildBounds, grandchildColor);
- }
-}
-
-} // namespace android
-
-// TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wconversion"
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
index 8dc9a12..fa88ca5 100644
--- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
+++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp
@@ -194,7 +194,6 @@
bool deferredTransactionUpdateFound(const SurfaceChange& change, bool foundDeferred);
bool reparentUpdateFound(const SurfaceChange& change, bool found);
bool relativeParentUpdateFound(const SurfaceChange& change, bool found);
- bool detachChildrenUpdateFound(const SurfaceChange& change, bool found);
bool reparentChildrenUpdateFound(const SurfaceChange& change, bool found);
bool shadowRadiusUpdateFound(const SurfaceChange& change, bool found);
bool surfaceUpdateFound(const Trace& trace, SurfaceChange::SurfaceChangeCase changeCase);
@@ -232,7 +231,6 @@
void deferredTransactionUpdate(Transaction&);
void reparentUpdate(Transaction&);
void relativeParentUpdate(Transaction&);
- void detachChildrenUpdate(Transaction&);
void reparentChildrenUpdate(Transaction&);
void shadowRadiusUpdate(Transaction&);
void surfaceCreation(Transaction&);
@@ -412,10 +410,6 @@
t.setRelativeLayer(mBGSurfaceControl, mFGSurfaceControl, RELATIVE_Z);
}
-void SurfaceInterceptorTest::detachChildrenUpdate(Transaction& t) {
- t.detachChildren(mBGSurfaceControl);
-}
-
void SurfaceInterceptorTest::reparentChildrenUpdate(Transaction& t) {
t.reparentChildren(mBGSurfaceControl, mFGSurfaceControl);
}
@@ -452,7 +446,6 @@
runInTransaction(&SurfaceInterceptorTest::deferredTransactionUpdate);
runInTransaction(&SurfaceInterceptorTest::reparentUpdate);
runInTransaction(&SurfaceInterceptorTest::reparentChildrenUpdate);
- runInTransaction(&SurfaceInterceptorTest::detachChildrenUpdate);
runInTransaction(&SurfaceInterceptorTest::relativeParentUpdate);
runInTransaction(&SurfaceInterceptorTest::shadowRadiusUpdate);
}
@@ -667,16 +660,6 @@
return found;
}
-bool SurfaceInterceptorTest::detachChildrenUpdateFound(const SurfaceChange& change, bool found) {
- bool detachChildren(change.detach_children().detach_children());
- if (detachChildren && !found) {
- found = true;
- } else if (detachChildren && found) {
- []() { FAIL(); }();
- }
- return found;
-}
-
bool SurfaceInterceptorTest::reparentChildrenUpdateFound(const SurfaceChange& change, bool found) {
bool hasId(change.reparent_children().parent_id() == mFGLayerId);
if (hasId && !found) {
@@ -761,9 +744,6 @@
case SurfaceChange::SurfaceChangeCase::kRelativeParent:
foundUpdate = relativeParentUpdateFound(change, foundUpdate);
break;
- case SurfaceChange::SurfaceChangeCase::kDetachChildren:
- foundUpdate = detachChildrenUpdateFound(change, foundUpdate);
- break;
case SurfaceChange::SurfaceChangeCase::kShadowRadius:
foundUpdate = shadowRadiusUpdateFound(change, foundUpdate);
break;
@@ -793,7 +773,6 @@
ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kReparent));
ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kReparentChildren));
ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kRelativeParent));
- ASSERT_TRUE(surfaceUpdateFound(trace, SurfaceChange::SurfaceChangeCase::kDetachChildren));
}
bool SurfaceInterceptorTest::surfaceCreationFound(const Increment& increment, bool foundSurface) {
@@ -968,11 +947,6 @@
SurfaceChange::SurfaceChangeCase::kRelativeParent);
}
-TEST_F(SurfaceInterceptorTest, InterceptDetachChildrenUpdateWorks) {
- captureTest(&SurfaceInterceptorTest::detachChildrenUpdate,
- SurfaceChange::SurfaceChangeCase::kDetachChildren);
-}
-
TEST_F(SurfaceInterceptorTest, InterceptShadowRadiusUpdateWorks) {
captureTest(&SurfaceInterceptorTest::shadowRadiusUpdate,
SurfaceChange::SurfaceChangeCase::kShadowRadius);
diff --git a/services/surfaceflinger/tests/TransactionTestHarnesses.h b/services/surfaceflinger/tests/TransactionTestHarnesses.h
index a361b1e..33823d7 100644
--- a/services/surfaceflinger/tests/TransactionTestHarnesses.h
+++ b/services/surfaceflinger/tests/TransactionTestHarnesses.h
@@ -57,6 +57,8 @@
// Sample usage bits from screenrecord
GRALLOC_USAGE_HW_VIDEO_ENCODER |
GRALLOC_USAGE_SW_READ_OFTEN);
+ sp<BufferListener> listener = new BufferListener(this);
+ itemConsumer->setFrameAvailableListener(listener);
vDisplay = SurfaceComposerClient::createDisplay(String8("VirtualDisplay"),
false /*secure*/);
@@ -68,6 +70,13 @@
Rect(displayState.layerStackSpaceRect), Rect(resolution));
t.apply();
SurfaceComposerClient::Transaction().apply(true);
+
+ std::unique_lock lock(mMutex);
+ mAvailable = false;
+ // Wait for frame buffer ready.
+ mCondition.wait_for(lock, std::chrono::seconds(2),
+ [this]() NO_THREAD_SAFETY_ANALYSIS { return mAvailable; });
+
BufferItem item;
itemConsumer->acquireBuffer(&item, 0, true);
auto sc = std::make_unique<ScreenCapture>(item.mGraphicBuffer);
@@ -80,6 +89,23 @@
protected:
LayerTransactionTest* mDelegate;
RenderPath mRenderPath;
+ std::mutex mMutex;
+ std::condition_variable mCondition;
+ bool mAvailable = false;
+
+ void onFrameAvailable() {
+ std::unique_lock lock(mMutex);
+ mAvailable = true;
+ mCondition.notify_all();
+ }
+
+ class BufferListener : public ConsumerBase::FrameAvailableListener {
+ public:
+ BufferListener(LayerRenderPathTestHarness* owner) : mOwner(owner) {}
+ LayerRenderPathTestHarness* mOwner;
+
+ void onFrameAvailable(const BufferItem& /*item*/) { mOwner->onFrameAvailable(); }
+ };
};
class LayerTypeTransactionHarness : public LayerTransactionTest {
diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
index bd49728..efa15f1 100644
--- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
+++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp
@@ -63,9 +63,7 @@
// Mock test helpers
using ::testing::_;
-using ::testing::AtLeast;
using ::testing::DoAll;
-using ::testing::Invoke;
using ::testing::Return;
using ::testing::SetArgPointee;
@@ -74,9 +72,11 @@
using Display = V2_1::Display;
///////////////////////////////////////////////
-
-constexpr PhysicalDisplayId kPrimaryDisplayId = PhysicalDisplayId::fromPort(PRIMARY_DISPLAY);
-constexpr PhysicalDisplayId kExternalDisplayId = PhysicalDisplayId::fromPort(EXTERNAL_DISPLAY);
+constexpr PhysicalDisplayId physicalIdFromHwcDisplayId(Display hwcId) {
+ return PhysicalDisplayId::fromPort(hwcId);
+}
+constexpr PhysicalDisplayId kPrimaryDisplayId = physicalIdFromHwcDisplayId(PRIMARY_DISPLAY);
+constexpr PhysicalDisplayId kExternalDisplayId = physicalIdFromHwcDisplayId(EXTERNAL_DISPLAY);
struct TestColor {
public:
@@ -158,7 +158,7 @@
self->mReceivedDisplayEvents.push_back(buffer[i]);
}
}
- ALOGD_IF(n < 0, "Error reading events (%s)\n", strerror(-n));
+ ALOGD_IF(n < 0, "Error reading events (%s)", strerror(-n));
return 1;
}
@@ -174,7 +174,7 @@
void setExpectationsForConfigs(Display display, std::vector<TestConfig> testConfigs,
Config activeConfig, V2_4::VsyncPeriodNanos defaultVsyncPeriod) {
std::vector<Config> configIds;
- for (int i = 0; i < testConfigs.size(); i++) {
+ for (size_t i = 0; i < testConfigs.size(); i++) {
configIds.push_back(testConfigs[i].id);
EXPECT_CALL(*mMockComposer,
@@ -269,10 +269,10 @@
mMockComposer = nullptr;
}
- void waitForDisplayTransaction() {
+ void waitForDisplayTransaction(Display display) {
// Both a refresh and a vsync event are needed to apply pending display
// transactions.
- mFakeComposerClient->refreshDisplay(EXTERNAL_DISPLAY);
+ mFakeComposerClient->refreshDisplay(display);
mFakeComposerClient->runVSyncAndWait();
// Extra vsync and wait to avoid a 10% flake due to a race.
@@ -291,7 +291,7 @@
mReceivedDisplayEvents.pop_front();
ALOGV_IF(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG,
- "event hotplug: displayId %s, connected %d\t",
+ "event hotplug: displayId %s, connected %d",
to_string(event.header.displayId).c_str(), event.hotplug.connected);
if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_HOTPLUG &&
@@ -314,7 +314,7 @@
mReceivedDisplayEvents.pop_front();
ALOGV_IF(event.header.type == DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED,
- "event config: displayId %s, configId %d\t",
+ "event config: displayId %s, configId %d",
to_string(event.header.displayId).c_str(), event.config.configId);
if (event.header.type == DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED &&
@@ -341,7 +341,7 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::CONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
{
@@ -372,7 +372,7 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::DISCONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
mFakeComposerClient->clearFrames();
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false));
@@ -403,7 +403,7 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::CONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId);
@@ -456,7 +456,7 @@
config.refreshRate,
config.refreshRate,
config.refreshRate));
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
break;
}
@@ -487,7 +487,7 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::DISCONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
mFakeComposerClient->clearFrames();
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false));
}
@@ -510,7 +510,7 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::CONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId);
@@ -562,7 +562,7 @@
config.refreshRate,
config.refreshRate,
config.refreshRate));
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
break;
}
@@ -593,7 +593,7 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::DISCONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
mFakeComposerClient->clearFrames();
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false));
}
@@ -626,7 +626,7 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::CONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, true));
const auto display = SurfaceComposerClient::getPhysicalDisplayToken(kExternalDisplayId);
@@ -669,7 +669,7 @@
.WillOnce(Return(V2_1::Error::NONE));
}
- for (int i = 0; i < configs.size(); i++) {
+ for (size_t i = 0; i < configs.size(); i++) {
const auto& config = configs[i];
if (config.resolution.getWidth() == 800 && config.refreshRate == 1e9f / 11'111'111) {
EXPECT_EQ(NO_ERROR,
@@ -679,7 +679,7 @@
configs[i].refreshRate,
configs[i].refreshRate,
configs[i].refreshRate));
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
break;
}
@@ -726,7 +726,7 @@
config.refreshRate,
config.refreshRate,
config.refreshRate));
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
break;
}
@@ -773,7 +773,7 @@
config.refreshRate,
config.refreshRate,
config.refreshRate));
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
EXPECT_TRUE(waitForConfigChangedEvent(EXTERNAL_DISPLAY, i));
break;
}
@@ -804,7 +804,7 @@
mFakeComposerClient->hotplugDisplay(EXTERNAL_DISPLAY,
V2_1::IComposerCallback::Connection::DISCONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(EXTERNAL_DISPLAY);
mFakeComposerClient->clearFrames();
EXPECT_TRUE(waitForHotplugEvent(EXTERNAL_DISPLAY, false));
}
@@ -815,7 +815,7 @@
mFakeComposerClient->hotplugDisplay(PRIMARY_DISPLAY,
V2_1::IComposerCallback::Connection::DISCONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(PRIMARY_DISPLAY);
EXPECT_TRUE(waitForHotplugEvent(PRIMARY_DISPLAY, false));
{
@@ -840,7 +840,7 @@
mFakeComposerClient->hotplugDisplay(PRIMARY_DISPLAY,
V2_1::IComposerCallback::Connection::CONNECTED);
- waitForDisplayTransaction();
+ waitForDisplayTransaction(PRIMARY_DISPLAY);
EXPECT_TRUE(waitForHotplugEvent(PRIMARY_DISPLAY, true));
@@ -856,6 +856,121 @@
}
}
+ void Test_SubsequentHotplugConnectUpdatesDisplay(Display hwcDisplayId) {
+ ALOGD("DisplayTest::Test_SubsequentHotplugConnectUpdatesDisplay");
+
+ // Send a hotplug connected event to set up the initial display modes.
+ // The primary display is already connected so this will update it.
+ // If we're running the test of an external display this will create it.
+ setExpectationsForConfigs(hwcDisplayId,
+ {{.id = 1,
+ .w = 800,
+ .h = 1600,
+ .vsyncPeriod = 11'111'111,
+ .group = 1}},
+ /* activeConfig */ 1, 11'111'111);
+
+ mFakeComposerClient->hotplugDisplay(hwcDisplayId,
+ V2_1::IComposerCallback::Connection::CONNECTED);
+ waitForDisplayTransaction(hwcDisplayId);
+ EXPECT_TRUE(waitForHotplugEvent(hwcDisplayId, true));
+
+ const auto displayId = physicalIdFromHwcDisplayId(hwcDisplayId);
+ const auto display = SurfaceComposerClient::getPhysicalDisplayToken(displayId);
+ EXPECT_FALSE(display == nullptr);
+
+ // Verify that the active mode and the supported moded are updated
+ {
+ DisplayConfig config;
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
+ EXPECT_EQ(ui::Size(800, 1600), config.resolution);
+ EXPECT_EQ(1e9f / 11'111'111, config.refreshRate);
+
+ Vector<DisplayConfig> configs;
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs));
+ EXPECT_EQ(configs.size(), 1);
+ }
+
+ // Send another hotplug connected event
+ setExpectationsForConfigs(hwcDisplayId,
+ {
+ {.id = 1,
+ .w = 800,
+ .h = 1600,
+ .vsyncPeriod = 16'666'666,
+ .group = 1},
+ {.id = 2,
+ .w = 800,
+ .h = 1600,
+ .vsyncPeriod = 11'111'111,
+ .group = 1},
+ {.id = 3,
+ .w = 800,
+ .h = 1600,
+ .vsyncPeriod = 8'333'333,
+ .group = 1},
+ },
+ /* activeConfig */ 1, 16'666'666);
+
+ mFakeComposerClient->hotplugDisplay(hwcDisplayId,
+ V2_1::IComposerCallback::Connection::CONNECTED);
+ waitForDisplayTransaction(hwcDisplayId);
+ EXPECT_TRUE(waitForHotplugEvent(hwcDisplayId, true));
+
+ // Verify that the active mode and the supported moded are updated
+ {
+ DisplayConfig config;
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
+ EXPECT_EQ(ui::Size(800, 1600), config.resolution);
+ EXPECT_EQ(1e9f / 16'666'666, config.refreshRate);
+ }
+
+ Vector<DisplayConfig> configs;
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayConfigs(display, &configs));
+ EXPECT_EQ(configs.size(), 3);
+
+ EXPECT_EQ(ui::Size(800, 1600), configs[0].resolution);
+ EXPECT_EQ(1e9f / 16'666'666, configs[0].refreshRate);
+
+ EXPECT_EQ(ui::Size(800, 1600), configs[1].resolution);
+ EXPECT_EQ(1e9f / 11'111'111, configs[1].refreshRate);
+
+ EXPECT_EQ(ui::Size(800, 1600), configs[2].resolution);
+ EXPECT_EQ(1e9f / 8'333'333, configs[2].refreshRate);
+
+ // Verify that we are able to switch to any of the modes
+ for (int i = configs.size() - 1; i >= 0; i--) {
+ const auto hwcId = i + 1;
+ // Set up HWC expectations for the mode change
+ if (mIs2_4Client) {
+ EXPECT_CALL(*mMockComposer,
+ setActiveConfigWithConstraints(hwcDisplayId, hwcId, _, _))
+ .WillOnce(Return(V2_4::Error::NONE));
+ } else {
+ EXPECT_CALL(*mMockComposer, setActiveConfig(hwcDisplayId, hwcId))
+ .WillOnce(Return(V2_1::Error::NONE));
+ }
+
+ EXPECT_EQ(NO_ERROR,
+ SurfaceComposerClient::setDesiredDisplayConfigSpecs(display, i, false,
+ configs[i].refreshRate,
+ configs[i].refreshRate,
+ configs[i].refreshRate,
+ configs[i].refreshRate));
+ // We need to refresh twice - once to apply the pending mode change request,
+ // and once to process the change.
+ waitForDisplayTransaction(hwcDisplayId);
+ waitForDisplayTransaction(hwcDisplayId);
+ EXPECT_TRUE(waitForConfigChangedEvent(hwcDisplayId, i))
+ << "Failure while switching to mode " << i;
+
+ DisplayConfig config;
+ EXPECT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayConfig(display, &config));
+ EXPECT_EQ(ui::Size(800, 1600), config.resolution);
+ EXPECT_EQ(configs[i].refreshRate, config.refreshRate);
+ }
+ }
+
sp<V2_1::IComposer> mFakeService;
sp<SurfaceComposerClient> mComposerClient;
@@ -911,6 +1026,14 @@
Test_HotplugPrimaryDisplay();
}
+TEST_F(DisplayTest_2_1, SubsequentHotplugConnectUpdatesPrimaryDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY);
+}
+
+TEST_F(DisplayTest_2_1, SubsequentHotplugConnectUpdatesExternalDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY);
+}
+
using DisplayTest_2_2 = DisplayTest<FakeComposerService_2_2>;
TEST_F(DisplayTest_2_2, HotplugOneConfig) {
@@ -933,6 +1056,14 @@
Test_HotplugPrimaryDisplay();
}
+TEST_F(DisplayTest_2_2, SubsequentHotplugConnectUpdatesPrimaryDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY);
+}
+
+TEST_F(DisplayTest_2_2, SubsequentHotplugConnectUpdatesExternalDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY);
+}
+
using DisplayTest_2_3 = DisplayTest<FakeComposerService_2_3>;
TEST_F(DisplayTest_2_3, HotplugOneConfig) {
@@ -955,6 +1086,14 @@
Test_HotplugPrimaryDisplay();
}
+TEST_F(DisplayTest_2_3, SubsequentHotplugConnectUpdatesPrimaryDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY);
+}
+
+TEST_F(DisplayTest_2_3, SubsequentHotplugConnectUpdatesExternalDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY);
+}
+
using DisplayTest_2_4 = DisplayTest<FakeComposerService_2_4>;
TEST_F(DisplayTest_2_4, HotplugOneConfig) {
@@ -977,6 +1116,14 @@
Test_HotplugPrimaryDisplay();
}
+TEST_F(DisplayTest_2_4, SubsequentHotplugConnectUpdatesPrimaryDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(PRIMARY_DISPLAY);
+}
+
+TEST_F(DisplayTest_2_4, SubsequentHotplugConnectUpdatesExternalDisplay) {
+ Test_SubsequentHotplugConnectUpdatesDisplay(EXTERNAL_DISPLAY);
+}
+
////////////////////////////////////////////////
template <typename FakeComposerService>
@@ -1639,82 +1786,6 @@
EXPECT_TRUE(framesAreSame(referenceFrame2, Base::sFakeComposer->getLatestFrame()));
}
- void Test_DetachChildrenSameClient() {
- {
- TransactionScope ts(*Base::sFakeComposer);
- ts.show(mChild);
- ts.setPosition(mChild, 10, 10);
- ts.setPosition(Base::mFGSurfaceControl, 64, 64);
- }
-
- auto referenceFrame = Base::mBaseFrame;
- referenceFrame[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 64, 64 + 64};
- referenceFrame[CHILD_LAYER].mDisplayFrame =
- hwc_rect_t{64 + 10, 64 + 10, 64 + 10 + 10, 64 + 10 + 10};
- EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame()));
-
- {
- TransactionScope ts(*Base::sFakeComposer);
- ts.setPosition(Base::mFGSurfaceControl, 0, 0);
- ts.detachChildren(Base::mFGSurfaceControl);
- }
-
- {
- TransactionScope ts(*Base::sFakeComposer);
- ts.setPosition(Base::mFGSurfaceControl, 64, 64);
- ts.hide(mChild);
- }
-
- std::vector<RenderState> refFrame(2);
- refFrame[Base::BG_LAYER] = Base::mBaseFrame[Base::BG_LAYER];
- refFrame[Base::FG_LAYER] = Base::mBaseFrame[Base::FG_LAYER];
-
- EXPECT_TRUE(framesAreSame(refFrame, Base::sFakeComposer->getLatestFrame()));
- }
-
- void Test_DetachChildrenDifferentClient() {
- sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient;
- sp<SurfaceControl> childNewClient =
- newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10,
- PIXEL_FORMAT_RGBA_8888, 0,
- Base::mFGSurfaceControl->getHandle());
- ASSERT_TRUE(childNewClient != nullptr);
- ASSERT_TRUE(childNewClient->isValid());
- fillSurfaceRGBA8(childNewClient, LIGHT_GRAY);
-
- {
- TransactionScope ts(*Base::sFakeComposer);
- ts.hide(mChild);
- ts.show(childNewClient);
- ts.setPosition(childNewClient, 10, 10);
- ts.setPosition(Base::mFGSurfaceControl, 64, 64);
- }
-
- auto referenceFrame = Base::mBaseFrame;
- referenceFrame[Base::FG_LAYER].mDisplayFrame = hwc_rect_t{64, 64, 64 + 64, 64 + 64};
- referenceFrame[CHILD_LAYER].mDisplayFrame =
- hwc_rect_t{64 + 10, 64 + 10, 64 + 10 + 10, 64 + 10 + 10};
- EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame()));
-
- {
- TransactionScope ts(*Base::sFakeComposer);
- ts.detachChildren(Base::mFGSurfaceControl);
- ts.setPosition(Base::mFGSurfaceControl, 0, 0);
- }
-
- {
- TransactionScope ts(*Base::sFakeComposer);
- ts.setPosition(Base::mFGSurfaceControl, 64, 64);
- ts.setPosition(childNewClient, 0, 0);
- ts.hide(childNewClient);
- }
-
- // Nothing should have changed. The child control becomes a no-op
- // zombie on detach. See comments for detachChildren in the
- // SurfaceControl.h file.
- EXPECT_TRUE(framesAreSame(referenceFrame, Base::sFakeComposer->getLatestFrame()));
- }
-
// Regression test for b/37673612
void Test_ChildrenWithParentBufferTransform() {
{
@@ -1815,14 +1886,6 @@
Test_ReparentChildren();
}
-TEST_F(ChildLayerTest_2_1, DISABLED_DetachChildrenSameClient) {
- Test_DetachChildrenSameClient();
-}
-
-TEST_F(ChildLayerTest_2_1, DISABLED_DetachChildrenDifferentClient) {
- Test_DetachChildrenDifferentClient();
-}
-
// Regression test for b/37673612
TEST_F(ChildLayerTest_2_1, DISABLED_ChildrenWithParentBufferTransform) {
Test_ChildrenWithParentBufferTransform();
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index f2051d9..b696a6d 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -62,15 +62,9 @@
using testing::_;
using testing::AtLeast;
-using testing::Between;
-using testing::ByMove;
using testing::DoAll;
-using testing::Field;
-using testing::Invoke;
using testing::IsNull;
using testing::Mock;
-using testing::NotNull;
-using testing::Ref;
using testing::Return;
using testing::ReturnRef;
using testing::SetArgPointee;
@@ -86,7 +80,6 @@
constexpr int DEFAULT_DISPLAY_WIDTH = 1920;
constexpr int DEFAULT_DISPLAY_HEIGHT = 1024;
-constexpr int DEFAULT_CONFIG_ID = 0;
constexpr int DEFAULT_TEXTURE_ID = 6000;
constexpr int DEFAULT_LAYER_STACK = 7000;
@@ -147,7 +140,7 @@
EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
EXPECT_CALL(*vsyncTracker, currentPeriod())
- .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+ .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
constexpr ISchedulerCallback* kCallback = nullptr;
@@ -548,12 +541,6 @@
setupLatchedBuffer(test, layer);
}
- static void setupBufferLayerPostFrameCallExpectations(CompositionTest* test) {
- // BufferLayer::onPostComposition(), when there is no present fence
- EXPECT_CALL(*test->mComposer, getActiveConfig(HWC_DISPLAY, _))
- .WillOnce(DoAll(SetArgPointee<1>(DEFAULT_CONFIG_ID), Return(Error::NONE)));
- }
-
static void setupHwcSetGeometryCallExpectations(CompositionTest* test) {
if (!test->mDisplayOff) {
// TODO: Coverage of other values
@@ -632,8 +619,6 @@
.Times(1);
EXPECT_CALL(*test->mComposer, setLayerBuffer(HWC_DISPLAY, HWC_LAYER, _, _, _)).Times(1);
}
-
- setupBufferLayerPostFrameCallExpectations(test);
}
static void setupREBufferCompositionCommonCallExpectations(CompositionTest* test) {
@@ -793,7 +778,6 @@
static void setupInsecureREBufferCompositionCallExpectations(CompositionTest* test) {
setupInsecureREBufferCompositionCommonCallExpectations(test);
- Base::setupBufferLayerPostFrameCallExpectations(test);
}
static void setupInsecureREBufferScreenshotCompositionCallExpectations(CompositionTest* test) {
diff --git a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
index 1e24c0a..6b82170 100644
--- a/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/HWComposerTest.cpp
@@ -175,90 +175,5 @@
EXPECT_EQ(hal::Error::UNSUPPORTED, result);
}
-class HWComposerConfigsTest : public testing::Test {
-public:
- Hwc2::mock::Composer* mHal = new StrictMock<Hwc2::mock::Composer>();
- MockHWC2ComposerCallback mCallback;
-
- void setActiveConfig(Config config) {
- EXPECT_CALL(*mHal, getActiveConfig(_, _))
- .WillRepeatedly(DoAll(SetArgPointee<1>(config), Return(V2_1::Error::NONE)));
- }
-
- void setDisplayConfigs(std::vector<Config> configs) {
- EXPECT_CALL(*mHal, getDisplayConfigs(_, _))
- .WillOnce(DoAll(SetArgPointee<1>(configs), Return(V2_1::Error::NONE)));
- EXPECT_CALL(*mHal, getDisplayAttribute(_, _, _, _))
- .WillRepeatedly(DoAll(SetArgPointee<3>(1), Return(V2_1::Error::NONE)));
- }
-
- void testSetActiveModeWithConstraintsCommon(bool isVsyncPeriodSwitchSupported);
-};
-
-void HWComposerConfigsTest::testSetActiveModeWithConstraintsCommon(
- bool isVsyncPeriodSwitchSupported) {
- EXPECT_CALL(*mHal, getMaxVirtualDisplayCount()).WillOnce(Return(0));
- EXPECT_CALL(*mHal, getCapabilities()).WillOnce(Return(std::vector<hal::Capability>{}));
- EXPECT_CALL(*mHal, getLayerGenericMetadataKeys(_)).WillOnce(Return(V2_4::Error::UNSUPPORTED));
- EXPECT_CALL(*mHal, registerCallback(_));
- EXPECT_CALL(*mHal, setVsyncEnabled(_, _)).WillRepeatedly(Return(V2_1::Error::NONE));
- EXPECT_CALL(*mHal, getDisplayIdentificationData(_, _, _))
- .WillRepeatedly(Return(V2_1::Error::UNSUPPORTED));
- EXPECT_CALL(*mHal, setClientTargetSlotCount(_)).WillRepeatedly(Return(V2_1::Error::NONE));
-
- EXPECT_CALL(*mHal, isVsyncPeriodSwitchSupported())
- .WillRepeatedly(Return(isVsyncPeriodSwitchSupported));
-
- if (isVsyncPeriodSwitchSupported) {
- EXPECT_CALL(*mHal, setActiveConfigWithConstraints(_, _, _, _))
- .WillRepeatedly(Return(V2_4::Error::NONE));
- } else {
- EXPECT_CALL(*mHal, setActiveConfig(_, _)).WillRepeatedly(Return(V2_1::Error::NONE));
- }
-
- impl::HWComposer hwc{std::unique_ptr<Hwc2::Composer>(mHal)};
- hwc.setConfiguration(&mCallback, 123);
-
- setDisplayConfigs({15});
- setActiveConfig(15);
-
- const auto physicalId = PhysicalDisplayId::fromPort(0);
- const hal::HWDisplayId hwcId = 0;
- hwc.allocatePhysicalDisplay(hwcId, physicalId);
-
- hal::VsyncPeriodChangeConstraints constraints;
- constraints.desiredTimeNanos = systemTime();
- constraints.seamlessRequired = false;
-
- hal::VsyncPeriodChangeTimeline timeline = {0, 0, 0};
- constexpr Config kConfigIndex = 0;
- const auto status =
- hwc.setActiveModeWithConstraints(physicalId, kConfigIndex, constraints, &timeline);
- EXPECT_EQ(NO_ERROR, status);
-
- const std::vector<Config> kConfigs{7, 8, 9, 10, 11};
- // Change the set of supported modes.
- setDisplayConfigs(kConfigs);
- setActiveConfig(11);
- hwc.onHotplug(hwcId, hal::Connection::CONNECTED);
- hwc.allocatePhysicalDisplay(hwcId, physicalId);
-
- for (size_t configIndex = 0; configIndex < kConfigs.size(); configIndex++) {
- const auto status =
- hwc.setActiveModeWithConstraints(physicalId,
- static_cast<hal::HWConfigId>(configIndex),
- constraints, &timeline);
- EXPECT_EQ(NO_ERROR, status) << "Error when switching to config " << configIndex;
- }
-}
-
-TEST_F(HWComposerConfigsTest, setActiveModeWithConstraintsWithVsyncSwitchingSupported) {
- testSetActiveModeWithConstraintsCommon(/*supported=*/true);
-}
-
-TEST_F(HWComposerConfigsTest, setActiveModeWithConstraintsWithVsyncSwitchingNotSupported) {
- testSetActiveModeWithConstraintsCommon(/*supported=*/false);
-}
-
} // namespace
} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
index c5deb7c..abecd4b 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp
@@ -144,7 +144,7 @@
EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
EXPECT_CALL(*vsyncTracker, currentPeriod())
- .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+ .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker),
std::move(eventThread), std::move(sfEventThread));
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index e060df2..a6d07d0 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -185,7 +185,7 @@
EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
EXPECT_CALL(*vsyncTracker, currentPeriod())
- .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+ .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
EXPECT_CALL(*vsyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
mFlinger.setupScheduler(std::move(vsyncController), std::move(vsyncTracker),
std::move(eventThread), std::move(sfEventThread));
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp
index 8552e15..b713334 100644
--- a/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_HandleTransactionLockedTest.cpp
@@ -669,7 +669,7 @@
// --------------------------------------------------------------------
// Call Expectations
- EXPECT_CALL(*displaySurface, resizeBuffers(newWidth, oldHeight)).Times(1);
+ EXPECT_CALL(*displaySurface, resizeBuffers(ui::Size(newWidth, oldHeight))).Times(1);
// --------------------------------------------------------------------
// Invocation
@@ -714,7 +714,7 @@
// --------------------------------------------------------------------
// Call Expectations
- EXPECT_CALL(*displaySurface, resizeBuffers(oldWidth, newHeight)).Times(1);
+ EXPECT_CALL(*displaySurface, resizeBuffers(ui::Size(oldWidth, newHeight))).Times(1);
// --------------------------------------------------------------------
// Invocation
@@ -764,7 +764,7 @@
// --------------------------------------------------------------------
// Call Expectations
- EXPECT_CALL(*displaySurface, resizeBuffers(kNewWidth, kNewHeight)).Times(1);
+ EXPECT_CALL(*displaySurface, resizeBuffers(kNewSize.getSize())).Times(1);
// --------------------------------------------------------------------
// Invocation
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 3be45e2..3787c43 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -41,6 +41,7 @@
#include "SurfaceFlingerDefaultFactory.h"
#include "SurfaceInterceptor.h"
#include "TestableScheduler.h"
+#include "mock/DisplayHardware/MockComposer.h"
#include "mock/MockDisplayIdGenerator.h"
#include "mock/MockFrameTimeline.h"
#include "mock/MockFrameTracer.h"
@@ -367,7 +368,8 @@
return mFlinger->SurfaceFlinger::getDisplayNativePrimaries(displayToken, primaries);
}
- auto& getTransactionQueue() { return mFlinger->mTransactionQueues; }
+ auto& getTransactionQueue() { return mFlinger->mTransactionQueue; }
+ auto& getPendingTransactionQueue() { return mFlinger->mPendingTransactionQueues; }
auto setTransactionState(
const FrameTimelineInfo& frameTimelineInfo, const Vector<ComposerState>& states,
@@ -477,7 +479,7 @@
static constexpr hal::HWDisplayId DEFAULT_HWC_DISPLAY_ID = 1000;
static constexpr int32_t DEFAULT_WIDTH = 1920;
static constexpr int32_t DEFAULT_HEIGHT = 1280;
- static constexpr int32_t DEFAULT_REFRESH_RATE = 16'666'666;
+ static constexpr int32_t DEFAULT_VSYNC_PERIOD = 16'666'666;
static constexpr int32_t DEFAULT_CONFIG_GROUP = 7;
static constexpr int32_t DEFAULT_DPI = 320;
static constexpr hal::HWConfigId DEFAULT_ACTIVE_CONFIG = 0;
@@ -502,8 +504,8 @@
return *this;
}
- auto& setRefreshRate(int32_t refreshRate) {
- mRefreshRate = refreshRate;
+ auto& setVsyncPeriod(int32_t vsyncPeriod) {
+ mVsyncPeriod = vsyncPeriod;
return *this;
}
@@ -532,7 +534,12 @@
return *this;
}
- void inject(TestableSurfaceFlinger* flinger, Hwc2::Composer* composer) {
+ void inject(TestableSurfaceFlinger* flinger, Hwc2::mock::Composer* composer) {
+ using ::testing::_;
+ using ::testing::DoAll;
+ using ::testing::Return;
+ using ::testing::SetArgPointee;
+
static const std::unordered_set<hal::Capability> defaultCapabilities;
if (mCapabilities == nullptr) mCapabilities = &defaultCapabilities;
@@ -547,15 +554,39 @@
display->setPowerMode(mPowerMode);
flinger->mutableHwcDisplayData()[mDisplayId].hwcDisplay = std::move(display);
- auto config = DisplayMode::Builder(mActiveConfig)
- .setWidth(mWidth)
- .setHeight(mHeight)
- .setVsyncPeriod(mRefreshRate)
- .setDpiX(mDpiX)
- .setDpiY(mDpiY)
- .setConfigGroup(mConfigGroup)
- .build();
- flinger->mutableHwcDisplayData()[mDisplayId].modes.push_back(config);
+ EXPECT_CALL(*composer, getDisplayConfigs(mHwcDisplayId, _))
+ .WillRepeatedly(
+ DoAll(SetArgPointee<1>(std::vector<hal::HWConfigId>{mActiveConfig}),
+ Return(hal::Error::NONE)));
+
+ EXPECT_CALL(*composer,
+ getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::WIDTH, _))
+ .WillRepeatedly(DoAll(SetArgPointee<3>(mWidth), Return(hal::Error::NONE)));
+
+ EXPECT_CALL(*composer,
+ getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::HEIGHT,
+ _))
+ .WillRepeatedly(DoAll(SetArgPointee<3>(mHeight), Return(hal::Error::NONE)));
+
+ EXPECT_CALL(*composer,
+ getDisplayAttribute(mHwcDisplayId, mActiveConfig,
+ hal::Attribute::VSYNC_PERIOD, _))
+ .WillRepeatedly(
+ DoAll(SetArgPointee<3>(mVsyncPeriod), Return(hal::Error::NONE)));
+
+ EXPECT_CALL(*composer,
+ getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::DPI_X, _))
+ .WillRepeatedly(DoAll(SetArgPointee<3>(mDpiX), Return(hal::Error::NONE)));
+
+ EXPECT_CALL(*composer,
+ getDisplayAttribute(mHwcDisplayId, mActiveConfig, hal::Attribute::DPI_Y, _))
+ .WillRepeatedly(DoAll(SetArgPointee<3>(mDpiY), Return(hal::Error::NONE)));
+
+ EXPECT_CALL(*composer,
+ getDisplayAttribute(mHwcDisplayId, mActiveConfig,
+ hal::Attribute::CONFIG_GROUP, _))
+ .WillRepeatedly(
+ DoAll(SetArgPointee<3>(mConfigGroup), Return(hal::Error::NONE)));
if (mHwcDisplayType == hal::DisplayType::PHYSICAL) {
const auto physicalId = PhysicalDisplayId::tryCast(mDisplayId);
@@ -581,10 +612,10 @@
hal::HWDisplayId mHwcDisplayId = DEFAULT_HWC_DISPLAY_ID;
int32_t mWidth = DEFAULT_WIDTH;
int32_t mHeight = DEFAULT_HEIGHT;
- int32_t mRefreshRate = DEFAULT_REFRESH_RATE;
+ int32_t mVsyncPeriod = DEFAULT_VSYNC_PERIOD;
int32_t mDpiX = DEFAULT_DPI;
- int32_t mConfigGroup = DEFAULT_CONFIG_GROUP;
int32_t mDpiY = DEFAULT_DPI;
+ int32_t mConfigGroup = DEFAULT_CONFIG_GROUP;
hal::HWConfigId mActiveConfig = DEFAULT_ACTIVE_CONFIG;
hal::PowerMode mPowerMode = DEFAULT_POWER_MODE;
const std::unordered_set<hal::Capability>* mCapabilities = nullptr;
@@ -602,6 +633,21 @@
mHwcDisplayId(hwcDisplayId) {
mCreationArgs.connectionType = connectionType;
mCreationArgs.isPrimary = isPrimary;
+
+ mActiveModeId = DisplayModeId(0);
+ DisplayModePtr activeMode =
+ DisplayMode::Builder(FakeHwcDisplayInjector::DEFAULT_ACTIVE_CONFIG)
+ .setId(mActiveModeId)
+ .setWidth(FakeHwcDisplayInjector::DEFAULT_WIDTH)
+ .setHeight(FakeHwcDisplayInjector::DEFAULT_HEIGHT)
+ .setVsyncPeriod(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD)
+ .setDpiX(FakeHwcDisplayInjector::DEFAULT_DPI)
+ .setDpiY(FakeHwcDisplayInjector::DEFAULT_DPI)
+ .setConfigGroup(0)
+ .build();
+
+ DisplayModes modes{activeMode};
+ mCreationArgs.supportedModes = modes;
}
sp<IBinder> token() const { return mDisplayToken; }
@@ -624,6 +670,16 @@
auto& mutableDisplayDevice() { return mFlinger.mutableDisplays()[mDisplayToken]; }
+ auto& setActiveMode(DisplayModeId mode) {
+ mActiveModeId = mode;
+ return *this;
+ }
+
+ auto& setSupportedModes(DisplayModes mode) {
+ mCreationArgs.supportedModes = mode;
+ return *this;
+ }
+
auto& setNativeWindow(const sp<ANativeWindow>& nativeWindow) {
mCreationArgs.nativeWindow = nativeWindow;
return *this;
@@ -676,6 +732,9 @@
state.isSecure = mCreationArgs.isSecure;
sp<DisplayDevice> device = new DisplayDevice(mCreationArgs);
+ if (!device->isVirtual()) {
+ device->setActiveMode(mActiveModeId);
+ }
mFlinger.mutableDisplays().emplace(mDisplayToken, device);
mFlinger.mutableCurrentState().displays.add(mDisplayToken, state);
mFlinger.mutableDrawingState().displays.add(mDisplayToken, state);
@@ -692,6 +751,7 @@
sp<BBinder> mDisplayToken = new BBinder();
DisplayDeviceCreationArgs mCreationArgs;
const std::optional<hal::HWDisplayId> mHwcDisplayId;
+ DisplayModeId mActiveModeId;
};
private:
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index 6d2f672..eb2c1ba 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -72,7 +72,7 @@
EXPECT_CALL(*mVSyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillRepeatedly(Return(0));
EXPECT_CALL(*mVSyncTracker, currentPeriod())
- .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE));
+ .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_VSYNC_PERIOD));
mFlinger.setupScheduler(std::unique_ptr<mock::VsyncController>(mVsyncController),
std::unique_ptr<mock::VSyncTracker>(mVSyncTracker),
@@ -140,7 +140,6 @@
transaction.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
transaction.id);
- // This transaction should not have been placed on the transaction queue.
// If transaction is synchronous or syncs input windows, SF
// applyTransactionState should time out (5s) wating for SF to commit
// the transaction or to receive a signal that syncInputWindows has
@@ -151,8 +150,9 @@
} else {
EXPECT_LE(returnedTime, applicationTime + s2ns(5));
}
+ // Each transaction should have been placed on the transaction queue
auto transactionQueue = mFlinger.getTransactionQueue();
- EXPECT_EQ(0u, transactionQueue.size());
+ EXPECT_EQ(1u, transactionQueue.size());
}
void PlaceOnTransactionQueue(uint32_t flags, bool syncInputWindows) {
@@ -214,6 +214,8 @@
// (5s is the timeout period that applyTransactionState waits for SF to
// commit the transaction)
EXPECT_LE(systemTime(), applicationSentTime + s2ns(5));
+ // transaction that would goes to pending transaciton queue.
+ mFlinger.flushTransactionQueues();
applicationSentTime = systemTime();
mFlinger.setTransactionState(transactionB.frameTimelineInfo, transactionB.states,
@@ -233,8 +235,11 @@
EXPECT_LE(systemTime(), applicationSentTime + s2ns(5));
}
+ // transaction that would goes to pending transaciton queue.
+ mFlinger.flushTransactionQueues();
+
// check that there is one binder on the pending queue.
- auto transactionQueue = mFlinger.getTransactionQueue();
+ auto transactionQueue = mFlinger.getPendingTransactionQueue();
EXPECT_EQ(1u, transactionQueue.size());
auto& [applyToken, transactionStates] = *(transactionQueue.begin());
@@ -273,10 +278,7 @@
auto& transactionQueue = mFlinger.getTransactionQueue();
ASSERT_EQ(1u, transactionQueue.size());
- auto& [applyToken, transactionStates] = *(transactionQueue.begin());
- ASSERT_EQ(1u, transactionStates.size());
-
- auto& transactionState = transactionStates.front();
+ auto& transactionState = transactionQueue.front();
checkEqual(transactionA, transactionState);
// because flushing uses the cached expected present time, we send an empty
diff --git a/services/surfaceflinger/tests/utils/ScreenshotUtils.h b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
index a13f93b..2fefa45 100644
--- a/services/surfaceflinger/tests/utils/ScreenshotUtils.h
+++ b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
@@ -84,11 +84,13 @@
}
void expectColor(const Rect& rect, const Color& color, uint8_t tolerance = 0) {
+ ASSERT_NE(nullptr, mOutBuffer);
ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat());
TransactionUtils::expectBufferColor(mOutBuffer, mPixels, rect, color, tolerance);
}
void expectBorder(const Rect& rect, const Color& color, uint8_t tolerance = 0) {
+ ASSERT_NE(nullptr, mOutBuffer);
ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat());
const bool leftBorder = rect.left > 0;
const bool topBorder = rect.top > 0;
@@ -146,6 +148,7 @@
}
void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) {
+ ASSERT_NE(nullptr, mOutBuffer);
ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat());
const uint8_t* pixel = mPixels + (4 * (y * mOutBuffer->getStride() + x));
if (r != pixel[0] || g != pixel[1] || b != pixel[2]) {
@@ -163,10 +166,14 @@
void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); }
explicit ScreenCapture(const sp<GraphicBuffer>& outBuffer) : mOutBuffer(outBuffer) {
- mOutBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&mPixels));
+ if (mOutBuffer) {
+ mOutBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&mPixels));
+ }
}
- ~ScreenCapture() { mOutBuffer->unlock(); }
+ ~ScreenCapture() {
+ if (mOutBuffer) mOutBuffer->unlock();
+ }
private:
sp<GraphicBuffer> mOutBuffer;