diff options
| author | 2020-09-10 17:22:18 +0000 | |
|---|---|---|
| committer | 2020-09-10 17:22:18 +0000 | |
| commit | cdb6b16dec3a541b455be99d075004cb2f0a0cd7 (patch) | |
| tree | f7110d50445c67a337105034b1f2db3946a88fef /include | |
| parent | 171cac1b603e4bb83412eb596d05a500af5d7a76 (diff) | |
| parent | ac07d0f5ab16bb9e8bbbabb589d1c7d36817baa9 (diff) | |
Merge "Merge Android R"
Diffstat (limited to 'include')
30 files changed, 1593 insertions, 609 deletions
diff --git a/include/android/bitmap.h b/include/android/bitmap.h index 2def64dc90..f19539913e 100644 --- a/include/android/bitmap.h +++ b/include/android/bitmap.h @@ -26,6 +26,7 @@ #ifndef ANDROID_BITMAP_H #define ANDROID_BITMAP_H +#include <stdbool.h> #include <stdint.h> #include <jni.h> @@ -60,6 +61,30 @@ enum AndroidBitmapFormat { ANDROID_BITMAP_FORMAT_RGBA_4444 = 7, /** Alpha: 8 bits. */ ANDROID_BITMAP_FORMAT_A_8 = 8, + /** Each component is stored as a half float. **/ + ANDROID_BITMAP_FORMAT_RGBA_F16 = 9, +}; + +/** Bitmap alpha format */ +enum { + /** Pixel components are premultiplied by alpha. */ + ANDROID_BITMAP_FLAGS_ALPHA_PREMUL = 0, + /** Pixels are opaque. */ + ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE = 1, + /** Pixel components are independent of alpha. */ + ANDROID_BITMAP_FLAGS_ALPHA_UNPREMUL = 2, + /** Bit mask for AndroidBitmapFormat.flags to isolate the alpha. */ + ANDROID_BITMAP_FLAGS_ALPHA_MASK = 0x3, + /** Shift for AndroidBitmapFormat.flags to isolate the alpha. */ + ANDROID_BITMAP_FLAGS_ALPHA_SHIFT = 0, +}; + +enum { + /** If this bit is set in AndroidBitmapInfo.flags, the Bitmap uses the + * HARDWARE Config, and its {@link AHardwareBuffer} can be retrieved via + * {@link AndroidBitmap_getHardwareBuffer}. + */ + ANDROID_BITMAP_FLAGS_IS_HARDWARE = 1 << 31, }; /** Bitmap info, see AndroidBitmap_getInfo(). */ @@ -72,17 +97,41 @@ typedef struct { uint32_t stride; /** The bitmap pixel format. See {@link AndroidBitmapFormat} */ int32_t format; - /** Unused. */ - uint32_t flags; // 0 for now + /** Bitfield containing information about the bitmap. + * + * <p>Two bits are used to encode alpha. Use {@link ANDROID_BITMAP_FLAGS_ALPHA_MASK} + * and {@link ANDROID_BITMAP_FLAGS_ALPHA_SHIFT} to retrieve them.</p> + * + * <p>One bit is used to encode whether the Bitmap uses the HARDWARE Config. Use + * {@link ANDROID_BITMAP_FLAGS_IS_HARDWARE} to know.</p> + * + * <p>These flags were introduced in API level 30.</p> + */ + uint32_t flags; } AndroidBitmapInfo; /** - * Given a java bitmap object, fill out the AndroidBitmapInfo struct for it. + * Given a java bitmap object, fill out the {@link AndroidBitmapInfo} struct for it. * If the call fails, the info parameter will be ignored. */ int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap, AndroidBitmapInfo* info); +#if __ANDROID_API__ >= 30 + +/** + * Given a java bitmap object, return its {@link ADataSpace}. + * + * Note that {@link ADataSpace} only exposes a few values. This may return + * {@link ADATASPACE_UNKNOWN}, even for Named ColorSpaces, if they have no + * corresponding ADataSpace. + * + * Available since API level 30. + */ +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 @@ -103,6 +152,110 @@ int AndroidBitmap_lockPixels(JNIEnv* env, jobject jbitmap, void** addrPtr); */ int AndroidBitmap_unlockPixels(JNIEnv* env, jobject jbitmap); +#if __ANDROID_API__ >= 30 + +// Note: these values match android.graphics.Bitmap#compressFormat. + +/** + * Specifies the formats that can be compressed to with + * {@link AndroidBitmap_compress}. + */ +enum AndroidBitmapCompressFormat { + /** + * Compress to the JPEG format. quality of 0 means + * compress for the smallest size. 100 means compress for max + * visual quality. + */ + ANDROID_BITMAP_COMPRESS_FORMAT_JPEG = 0, + /** + * Compress to the PNG format. PNG is lossless, so quality is + * ignored. + */ + ANDROID_BITMAP_COMPRESS_FORMAT_PNG = 1, + /** + * Compress to the WEBP lossy format. quality of 0 means + * compress for the smallest size. 100 means compress for max + * visual quality. + */ + ANDROID_BITMAP_COMPRESS_FORMAT_WEBP_LOSSY = 3, + /** + * Compress to the WEBP lossless format. quality refers to how + * much effort to put into compression. A value of 0 means to + * compress quickly, resulting in a relatively large file size. + * 100 means to spend more time compressing, resulting in a + * smaller file. + */ + ANDROID_BITMAP_COMPRESS_FORMAT_WEBP_LOSSLESS = 4, +}; + +/** + * User-defined function for writing the output of compression. + * + * Available since API level 30. + * + * @param userContext Pointer to user-defined data passed to + * {@link AndroidBitmap_compress}. + * @param data Compressed data of |size| bytes to write. + * @param size Length in bytes of data to write. + * @return Whether the operation succeeded. + */ +typedef bool (*AndroidBitmap_CompressWriteFunc)(void* userContext, + const void* data, + size_t size) __INTRODUCED_IN(30); + +/** + * Compress |pixels| as described by |info|. + * + * Available since API level 30. + * + * @param info Description of the pixels to compress. + * @param dataspace {@link ADataSpace} describing the color space of the + * pixels. + * @param pixels Pointer to pixels to compress. + * @param format {@link AndroidBitmapCompressFormat} to compress to. + * @param quality Hint to the compressor, 0-100. The value is interpreted + * differently depending on the + * {@link AndroidBitmapCompressFormat}. + * @param userContext User-defined data which will be passed to the supplied + * {@link AndroidBitmap_CompressWriteFunc} each time it is + * called. May be null. + * @param fn Function that writes the compressed data. Will be called each time + * the compressor has compressed more data that is ready to be + * written. May be called more than once for each call to this method. + * May not be null. + * @return AndroidBitmap functions result code. + */ +int AndroidBitmap_compress(const AndroidBitmapInfo* info, + int32_t dataspace, + const void* pixels, + int32_t format, int32_t quality, + void* userContext, + AndroidBitmap_CompressWriteFunc fn) __INTRODUCED_IN(30); + +struct AHardwareBuffer; +typedef struct AHardwareBuffer AHardwareBuffer; + +/** + * Retrieve the native object associated with a HARDWARE Bitmap. + * + * Client must not modify it while a Bitmap is wrapping it. + * + * Available since API level 30. + * + * @param bitmap Handle to an android.graphics.Bitmap. + * @param outBuffer On success, is set to a pointer to the + * {@link AHardwareBuffer} associated with bitmap. This acquires + * a reference on the buffer, and the client must call + * {@link AHardwareBuffer_release} when finished with it. + * @return AndroidBitmap functions result code. + * {@link ANDROID_BITMAP_RESULT_BAD_PARAMETER} if bitmap is not a + * HARDWARE Bitmap. + */ +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 346861f0a8..e9f559cd8e 100644 --- a/include/android/choreographer.h +++ b/include/android/choreographer.h @@ -54,6 +54,13 @@ typedef void (*AChoreographer_frameCallback)(long frameTimeNanos, void* data); */ typedef void (*AChoreographer_frameCallback64)(int64_t frameTimeNanos, void* data); +/** + * Prototype of the function that is called when the display refresh rate + * changes. It's passed the new vsync period in nanoseconds, as well as the data + * pointer provided by the application that registered a callback. + */ +typedef void (*AChoreographer_refreshRateCallback)(int64_t vsyncPeriodNanos, void* data); + #if __ANDROID_API__ >= 24 /** @@ -68,14 +75,16 @@ AChoreographer* AChoreographer_getInstance() __INTRODUCED_IN(24); * Deprecated: Use AChoreographer_postFrameCallback64 instead. */ void AChoreographer_postFrameCallback(AChoreographer* choreographer, - AChoreographer_frameCallback callback, void* data) __INTRODUCED_IN(24) __DEPRECATED_IN(29); + AChoreographer_frameCallback callback, void* data) + __INTRODUCED_IN(24) __DEPRECATED_IN(29); /** * Deprecated: Use AChoreographer_postFrameCallbackDelayed64 instead. */ void AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer, - AChoreographer_frameCallback callback, void* data, - long delayMillis) __INTRODUCED_IN(24) __DEPRECATED_IN(29); + AChoreographer_frameCallback callback, void* data, + long delayMillis) __INTRODUCED_IN(24) + __DEPRECATED_IN(29); #endif /* __ANDROID_API__ >= 24 */ @@ -87,8 +96,9 @@ void AChoreographer_postFrameCallbackDelayed(AChoreographer* choreographer, * * Available since API level 29. */ -void AChoreographer_postFrameCallback64(AChoreographer* chroreographer, - AChoreographer_frameCallback64 callback, void* data) __INTRODUCED_IN(29); +void AChoreographer_postFrameCallback64(AChoreographer* choreographer, + AChoreographer_frameCallback64 callback, void* data) + __INTRODUCED_IN(29); /** * Post a callback to be run on the frame following the specified delay. The @@ -98,10 +108,60 @@ void AChoreographer_postFrameCallback64(AChoreographer* chroreographer, * Available since API level 29. */ void AChoreographer_postFrameCallbackDelayed64(AChoreographer* choreographer, - AChoreographer_frameCallback64 callback, void* data, uint32_t delayMillis) __INTRODUCED_IN(29); + 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 + * called. The same callback may be registered multiple times, provided that a + * different data pointer is provided each time. + * + * If an application registers a callback for this choreographer instance when + * no new callbacks were previously registered, that callback is guaranteed to + * be dispatched. However, if the callback and associated data pointer are + * unregistered prior to running the callback, then the callback may be silently + * dropped. + * + * This api is thread-safe. Any thread is allowed to register a new refresh + * rate callback for the choreographer instance. + * + * Note that in API level 30, this api is not guaranteed to be atomic with + * DisplayManager. That is, calling Display#getRefreshRate very soon after + * a refresh rate callback is invoked may return a stale refresh rate. If any + * Display properties would be required by this callback, then it is recommended + * to listen directly to DisplayManager.DisplayListener#onDisplayChanged events + * instead. + * + * Available since API level 30. + */ +void AChoreographer_registerRefreshRateCallback(AChoreographer* choreographer, + AChoreographer_refreshRateCallback, void* data) + __INTRODUCED_IN(30); + +/** + * Unregisters a callback to be run when the display refresh rate changes, along + * with the data pointer previously provided when registering the callback. The + * callback is only unregistered when the data pointer matches one that was + * previously registered. + * + * This api is thread-safe. Any thread is allowed to unregister an existing + * refresh rate callback for the choreographer instance. When a refresh rate + * callback and associated data pointer are unregistered, then there is a + * guarantee that when the unregistration completes that that callback will not + * be run with the data pointer passed. + * + * Available since API level 30. + */ +void AChoreographer_unregisterRefreshRateCallback(AChoreographer* choreographer, + AChoreographer_refreshRateCallback, void* data) + __INTRODUCED_IN(30); +#endif /* __ANDROID_API__ >= 30 */ + __END_DECLS #endif // ANDROID_CHOREOGRAPHER_H diff --git a/include/android/configuration.h b/include/android/configuration.h index 05f43407fb..ccf3e59066 100644 --- a/include/android/configuration.h +++ b/include/android/configuration.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2010 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. @@ -58,13 +58,13 @@ enum { ACONFIGURATION_ORIENTATION_ANY = 0x0000, /** * Orientation: value corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#OrientationQualifier">port</a> + * <a href="/guide/topics/resources/providing-resources.html#OrientationQualifier">port</a> * resource qualifier. */ ACONFIGURATION_ORIENTATION_PORT = 0x0001, /** * Orientation: value corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#OrientationQualifier">land</a> + * <a href="/guide/topics/resources/providing-resources.html#OrientationQualifier">land</a> * resource qualifier. */ ACONFIGURATION_ORIENTATION_LAND = 0x0002, @@ -75,7 +75,7 @@ enum { ACONFIGURATION_TOUCHSCREEN_ANY = 0x0000, /** * Touchscreen: value corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#TouchscreenQualifier">notouch</a> + * <a href="/guide/topics/resources/providing-resources.html#TouchscreenQualifier">notouch</a> * resource qualifier. */ ACONFIGURATION_TOUCHSCREEN_NOTOUCH = 0x0001, @@ -83,7 +83,7 @@ enum { ACONFIGURATION_TOUCHSCREEN_STYLUS = 0x0002, /** * Touchscreen: value corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#TouchscreenQualifier">finger</a> + * <a href="/guide/topics/resources/providing-resources.html#TouchscreenQualifier">finger</a> * resource qualifier. */ ACONFIGURATION_TOUCHSCREEN_FINGER = 0x0003, @@ -92,43 +92,43 @@ enum { ACONFIGURATION_DENSITY_DEFAULT = 0, /** * Density: value corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#DensityQualifier">ldpi</a> + * <a href="/guide/topics/resources/providing-resources.html#DensityQualifier">ldpi</a> * resource qualifier. */ ACONFIGURATION_DENSITY_LOW = 120, /** * Density: value corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#DensityQualifier">mdpi</a> + * <a href="/guide/topics/resources/providing-resources.html#DensityQualifier">mdpi</a> * resource qualifier. */ ACONFIGURATION_DENSITY_MEDIUM = 160, /** * Density: value corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#DensityQualifier">tvdpi</a> + * <a href="/guide/topics/resources/providing-resources.html#DensityQualifier">tvdpi</a> * resource qualifier. */ ACONFIGURATION_DENSITY_TV = 213, /** * Density: value corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#DensityQualifier">hdpi</a> + * <a href="/guide/topics/resources/providing-resources.html#DensityQualifier">hdpi</a> * resource qualifier. */ ACONFIGURATION_DENSITY_HIGH = 240, /** * Density: value corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#DensityQualifier">xhdpi</a> + * <a href="/guide/topics/resources/providing-resources.html#DensityQualifier">xhdpi</a> * resource qualifier. */ ACONFIGURATION_DENSITY_XHIGH = 320, /** * Density: value corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#DensityQualifier">xxhdpi</a> + * <a href="/guide/topics/resources/providing-resources.html#DensityQualifier">xxhdpi</a> * resource qualifier. */ ACONFIGURATION_DENSITY_XXHIGH = 480, /** * Density: value corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#DensityQualifier">xxxhdpi</a> + * <a href="/guide/topics/resources/providing-resources.html#DensityQualifier">xxxhdpi</a> * resource qualifier. */ ACONFIGURATION_DENSITY_XXXHIGH = 640, @@ -141,19 +141,19 @@ enum { ACONFIGURATION_KEYBOARD_ANY = 0x0000, /** * Keyboard: value corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#ImeQualifier">nokeys</a> + * <a href="/guide/topics/resources/providing-resources.html#ImeQualifier">nokeys</a> * resource qualifier. */ ACONFIGURATION_KEYBOARD_NOKEYS = 0x0001, /** * Keyboard: value corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#ImeQualifier">qwerty</a> + * <a href="/guide/topics/resources/providing-resources.html#ImeQualifier">qwerty</a> * resource qualifier. */ ACONFIGURATION_KEYBOARD_QWERTY = 0x0002, /** * Keyboard: value corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#ImeQualifier">12key</a> + * <a href="/guide/topics/resources/providing-resources.html#ImeQualifier">12key</a> * resource qualifier. */ ACONFIGURATION_KEYBOARD_12KEY = 0x0003, @@ -162,25 +162,25 @@ enum { ACONFIGURATION_NAVIGATION_ANY = 0x0000, /** * Navigation: value corresponding to the - * <a href="@@dacRoot/guide/topics/resources/providing-resources.html#NavigationQualifier">nonav</a> + * <a href="@/guide/topics/resources/providing-resources.html#NavigationQualifier">nonav</a> * resource qualifier. */ ACONFIGURATION_NAVIGATION_NONAV = 0x0001, /** * Navigation: value corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#NavigationQualifier">dpad</a> + * <a href="/guide/topics/resources/providing-resources.html#NavigationQualifier">dpad</a> * resource qualifier. */ ACONFIGURATION_NAVIGATION_DPAD = 0x0002, /** * Navigation: value corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#NavigationQualifier">trackball</a> + * <a href="/guide/topics/resources/providing-resources.html#NavigationQualifier">trackball</a> * resource qualifier. */ ACONFIGURATION_NAVIGATION_TRACKBALL = 0x0003, /** * Navigation: value corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#NavigationQualifier">wheel</a> + * <a href="/guide/topics/resources/providing-resources.html#NavigationQualifier">wheel</a> * resource qualifier. */ ACONFIGURATION_NAVIGATION_WHEEL = 0x0004, @@ -189,19 +189,19 @@ enum { ACONFIGURATION_KEYSHIDDEN_ANY = 0x0000, /** * Keyboard availability: value corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keysexposed</a> + * <a href="/guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keysexposed</a> * resource qualifier. */ ACONFIGURATION_KEYSHIDDEN_NO = 0x0001, /** * Keyboard availability: value corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keyshidden</a> + * <a href="/guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keyshidden</a> * resource qualifier. */ ACONFIGURATION_KEYSHIDDEN_YES = 0x0002, /** * Keyboard availability: value corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keyssoft</a> + * <a href="/guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keyssoft</a> * resource qualifier. */ ACONFIGURATION_KEYSHIDDEN_SOFT = 0x0003, @@ -210,13 +210,13 @@ enum { ACONFIGURATION_NAVHIDDEN_ANY = 0x0000, /** * Navigation availability: value corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#NavAvailQualifier">navexposed</a> + * <a href="/guide/topics/resources/providing-resources.html#NavAvailQualifier">navexposed</a> * resource qualifier. */ ACONFIGURATION_NAVHIDDEN_NO = 0x0001, /** * Navigation availability: value corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#NavAvailQualifier">navhidden</a> + * <a href="/guide/topics/resources/providing-resources.html#NavAvailQualifier">navhidden</a> * resource qualifier. */ ACONFIGURATION_NAVHIDDEN_YES = 0x0002, @@ -226,28 +226,28 @@ enum { /** * Screen size: value indicating the screen is at least * approximately 320x426 dp units, corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#ScreenSizeQualifier">small</a> + * <a href="/guide/topics/resources/providing-resources.html#ScreenSizeQualifier">small</a> * resource qualifier. */ ACONFIGURATION_SCREENSIZE_SMALL = 0x01, /** * Screen size: value indicating the screen is at least * approximately 320x470 dp units, corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#ScreenSizeQualifier">normal</a> + * <a href="/guide/topics/resources/providing-resources.html#ScreenSizeQualifier">normal</a> * resource qualifier. */ ACONFIGURATION_SCREENSIZE_NORMAL = 0x02, /** * Screen size: value indicating the screen is at least * approximately 480x640 dp units, corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#ScreenSizeQualifier">large</a> + * <a href="/guide/topics/resources/providing-resources.html#ScreenSizeQualifier">large</a> * resource qualifier. */ ACONFIGURATION_SCREENSIZE_LARGE = 0x03, /** * Screen size: value indicating the screen is at least * approximately 720x960 dp units, corresponding to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#ScreenSizeQualifier">xlarge</a> + * <a href="/guide/topics/resources/providing-resources.html#ScreenSizeQualifier">xlarge</a> * resource qualifier. */ ACONFIGURATION_SCREENSIZE_XLARGE = 0x04, @@ -256,13 +256,13 @@ enum { ACONFIGURATION_SCREENLONG_ANY = 0x00, /** * Screen layout: value that corresponds to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#ScreenAspectQualifier">notlong</a> + * <a href="/guide/topics/resources/providing-resources.html#ScreenAspectQualifier">notlong</a> * resource qualifier. */ ACONFIGURATION_SCREENLONG_NO = 0x1, /** * Screen layout: value that corresponds to the - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#ScreenAspectQualifier">long</a> + * <a href="/guide/topics/resources/providing-resources.html#ScreenAspectQualifier">long</a> * resource qualifier. */ ACONFIGURATION_SCREENLONG_YES = 0x2, @@ -275,13 +275,13 @@ enum { ACONFIGURATION_WIDE_COLOR_GAMUT_ANY = 0x00, /** * Wide color gamut: value that corresponds to - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#WideColorGamutQualifier">no + * <a href="/guide/topics/resources/providing-resources.html#WideColorGamutQualifier">no * nowidecg</a> resource qualifier specified. */ ACONFIGURATION_WIDE_COLOR_GAMUT_NO = 0x1, /** * Wide color gamut: value that corresponds to - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#WideColorGamutQualifier"> + * <a href="/guide/topics/resources/providing-resources.html#WideColorGamutQualifier"> * widecg</a> resource qualifier specified. */ ACONFIGURATION_WIDE_COLOR_GAMUT_YES = 0x2, @@ -290,13 +290,13 @@ enum { ACONFIGURATION_HDR_ANY = 0x00, /** * HDR: value that corresponds to - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#HDRQualifier"> + * <a href="/guide/topics/resources/providing-resources.html#HDRQualifier"> * lowdr</a> resource qualifier specified. */ ACONFIGURATION_HDR_NO = 0x1, /** * HDR: value that corresponds to - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#HDRQualifier"> + * <a href="/guide/topics/resources/providing-resources.html#HDRQualifier"> * highdr</a> resource qualifier specified. */ ACONFIGURATION_HDR_YES = 0x2, @@ -305,38 +305,38 @@ enum { ACONFIGURATION_UI_MODE_TYPE_ANY = 0x00, /** * UI mode: value that corresponds to - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#UiModeQualifier">no + * <a href="/guide/topics/resources/providing-resources.html#UiModeQualifier">no * UI mode type</a> resource qualifier specified. */ ACONFIGURATION_UI_MODE_TYPE_NORMAL = 0x01, /** * UI mode: value that corresponds to - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#UiModeQualifier">desk</a> resource qualifier specified. + * <a href="/guide/topics/resources/providing-resources.html#UiModeQualifier">desk</a> resource qualifier specified. */ ACONFIGURATION_UI_MODE_TYPE_DESK = 0x02, /** * UI mode: value that corresponds to - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#UiModeQualifier">car</a> resource qualifier specified. + * <a href="/guide/topics/resources/providing-resources.html#UiModeQualifier">car</a> resource qualifier specified. */ ACONFIGURATION_UI_MODE_TYPE_CAR = 0x03, /** * UI mode: value that corresponds to - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#UiModeQualifier">television</a> resource qualifier specified. + * <a href="/guide/topics/resources/providing-resources.html#UiModeQualifier">television</a> resource qualifier specified. */ ACONFIGURATION_UI_MODE_TYPE_TELEVISION = 0x04, /** * UI mode: value that corresponds to - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#UiModeQualifier">appliance</a> resource qualifier specified. + * <a href="/guide/topics/resources/providing-resources.html#UiModeQualifier">appliance</a> resource qualifier specified. */ ACONFIGURATION_UI_MODE_TYPE_APPLIANCE = 0x05, /** * UI mode: value that corresponds to - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#UiModeQualifier">watch</a> resource qualifier specified. + * <a href="/guide/topics/resources/providing-resources.html#UiModeQualifier">watch</a> resource qualifier specified. */ ACONFIGURATION_UI_MODE_TYPE_WATCH = 0x06, /** * UI mode: value that corresponds to - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#UiModeQualifier">vr</a> resource qualifier specified. + * <a href="/guide/topics/resources/providing-resources.html#UiModeQualifier">vr</a> resource qualifier specified. */ ACONFIGURATION_UI_MODE_TYPE_VR_HEADSET = 0x07, @@ -344,12 +344,12 @@ enum { ACONFIGURATION_UI_MODE_NIGHT_ANY = 0x00, /** * UI night mode: value that corresponds to - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#NightQualifier">notnight</a> resource qualifier specified. + * <a href="/guide/topics/resources/providing-resources.html#NightQualifier">notnight</a> resource qualifier specified. */ ACONFIGURATION_UI_MODE_NIGHT_NO = 0x1, /** * UI night mode: value that corresponds to - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#NightQualifier">night</a> resource qualifier specified. + * <a href="/guide/topics/resources/providing-resources.html#NightQualifier">night</a> resource qualifier specified. */ ACONFIGURATION_UI_MODE_NIGHT_YES = 0x2, @@ -366,78 +366,78 @@ enum { ACONFIGURATION_LAYOUTDIR_ANY = 0x00, /** * Layout direction: value that corresponds to - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#LayoutDirectionQualifier">ldltr</a> resource qualifier specified. + * <a href="/guide/topics/resources/providing-resources.html#LayoutDirectionQualifier">ldltr</a> resource qualifier specified. */ ACONFIGURATION_LAYOUTDIR_LTR = 0x01, /** * Layout direction: value that corresponds to - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#LayoutDirectionQualifier">ldrtl</a> resource qualifier specified. + * <a href="/guide/topics/resources/providing-resources.html#LayoutDirectionQualifier">ldrtl</a> resource qualifier specified. */ ACONFIGURATION_LAYOUTDIR_RTL = 0x02, /** * Bit mask for - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#MccQualifier">mcc</a> + * <a href="/guide/topics/resources/providing-resources.html#MccQualifier">mcc</a> * configuration. */ ACONFIGURATION_MCC = 0x0001, /** * Bit mask for - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#MccQualifier">mnc</a> + * <a href="/guide/topics/resources/providing-resources.html#MccQualifier">mnc</a> * configuration. */ ACONFIGURATION_MNC = 0x0002, /** * Bit mask for - * <a href="{@docRoot}guide/topics/resources/providing-resources.html#LocaleQualifier">locale</a> + * <a href="/guide/topics/resources/providing-resources.html#LocaleQualifier">locale</a> * configuration. */ ACONFIGURATION_LOCALE = 0x0004, /** * Bit mask for - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#TouchscreenQualifier">touchscreen</a> + * <a href="/guide/topics/resources/providing-resources.html#TouchscreenQualifier">touchscreen</a> * configuration. */ ACONFIGURATION_TOUCHSCREEN = 0x0008, /** * Bit mask for - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#ImeQualifier">keyboard</a> + * <a href="/guide/topics/resources/providing-resources.html#ImeQualifier">keyboard</a> * configuration. */ ACONFIGURATION_KEYBOARD = 0x0010, /** * Bit mask for - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keyboardHidden</a> + * <a href="/guide/topics/resources/providing-resources.html#KeyboardAvailQualifier">keyboardHidden</a> * configuration. */ ACONFIGURATION_KEYBOARD_HIDDEN = 0x0020, /** * Bit mask for - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#NavigationQualifier">navigation</a> + * <a href="/guide/topics/resources/providing-resources.html#NavigationQualifier">navigation</a> * configuration. */ ACONFIGURATION_NAVIGATION = 0x0040, /** * Bit mask for - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#OrientationQualifier">orientation</a> + * <a href="/guide/topics/resources/providing-resources.html#OrientationQualifier">orientation</a> * configuration. */ ACONFIGURATION_ORIENTATION = 0x0080, /** * Bit mask for - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#DensityQualifier">density</a> + * <a href="/guide/topics/resources/providing-resources.html#DensityQualifier">density</a> * configuration. */ ACONFIGURATION_DENSITY = 0x0100, /** * Bit mask for - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#ScreenSizeQualifier">screen size</a> + * <a href="/guide/topics/resources/providing-resources.html#ScreenSizeQualifier">screen size</a> * configuration. */ ACONFIGURATION_SCREEN_SIZE = 0x0200, /** * Bit mask for - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#VersionQualifier">platform version</a> + * <a href="/guide/topics/resources/providing-resources.html#VersionQualifier">platform version</a> * configuration. */ ACONFIGURATION_VERSION = 0x0400, @@ -447,27 +447,27 @@ enum { ACONFIGURATION_SCREEN_LAYOUT = 0x0800, /** * Bit mask for - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#UiModeQualifier">ui mode</a> + * <a href="/guide/topics/resources/providing-resources.html#UiModeQualifier">ui mode</a> * configuration. */ ACONFIGURATION_UI_MODE = 0x1000, /** * Bit mask for - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#SmallestScreenWidthQualifier">smallest screen width</a> + * <a href="/guide/topics/resources/providing-resources.html#SmallestScreenWidthQualifier">smallest screen width</a> * configuration. */ ACONFIGURATION_SMALLEST_SCREEN_SIZE = 0x2000, /** * Bit mask for - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#LayoutDirectionQualifier">layout direction</a> + * <a href="/guide/topics/resources/providing-resources.html#LayoutDirectionQualifier">layout direction</a> * configuration. */ ACONFIGURATION_LAYOUTDIR = 0x4000, ACONFIGURATION_SCREEN_ROUND = 0x8000, /** * Bit mask for - * <a href="@dacRoot/guide/topics/resources/providing-resources.html#WideColorGamutQualifier">wide color gamut</a> - * and <a href="@dacRoot/guide/topics/resources/providing-resources.html#HDRQualifier">HDR</a> configurations. + * <a href="/guide/topics/resources/providing-resources.html#WideColorGamutQualifier">wide color gamut</a> + * and <a href="/guide/topics/resources/providing-resources.html#HDRQualifier">HDR</a> configurations. */ ACONFIGURATION_COLOR_MODE = 0x10000, /** diff --git a/include/android/hardware_buffer_jni.h b/include/android/hardware_buffer_jni.h index 293e5ac469..ae208a6e75 100644 --- a/include/android/hardware_buffer_jni.h +++ b/include/android/hardware_buffer_jni.h @@ -39,9 +39,9 @@ __BEGIN_DECLS * Return the AHardwareBuffer wrapped by a Java HardwareBuffer object. * * This method does not acquire any additional reference to the AHardwareBuffer - * that is returned. To keep the AHardwareBuffer live after the Java - * HardwareBuffer object got garbage collected, be sure to use AHardwareBuffer_acquire() - * to acquire an additional reference. + * that is returned. To keep the AHardwareBuffer alive after the Java + * HardwareBuffer object is closed, explicitly or by the garbage collector, be + * sure to use AHardwareBuffer_acquire() to acquire an additional reference. * * Available since API level 26. */ @@ -50,7 +50,18 @@ AHardwareBuffer* AHardwareBuffer_fromHardwareBuffer(JNIEnv* env, /** * Return a new Java HardwareBuffer object that wraps the passed native - * AHardwareBuffer object. + * AHardwareBuffer object. The Java HardwareBuffer will acquire a reference to + * the internal buffer and manage its lifetime. For example: + * + * <pre><code> + * AHardwareBuffer* buffer; + * AHardwareBuffer_allocate(..., &buffer); // `buffer` has reference count 1 + * jobject java_result = AHardwareBuffer_toHardwareBuffer(buffer); // `buffer` has reference count 2. + * AHardwareBuffer_release(buffer); // `buffer` has reference count 1 + * return result; // The underlying buffer is kept alive by `java_result` and + * // will be set to 0 when it is closed on the Java side with + * // HardwareBuffer::close(). + * </code></pre> * * Available since API level 26. */ diff --git a/include/android/imagedecoder.h b/include/android/imagedecoder.h new file mode 100644 index 0000000000..d7e6e4118f --- /dev/null +++ b/include/android/imagedecoder.h @@ -0,0 +1,538 @@ +/* + * Copyright (C) 2019 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. + */ + +/** + * @defgroup ImageDecoder + * + * Functions for converting encoded images into RGBA pixels. + * + * Similar to the Java counterpart android.graphics.ImageDecoder, it can be used + * to decode images in the following formats: + * - JPEG + * - PNG + * - GIF + * - WebP + * - BMP + * - ICO + * - WBMP + * - HEIF + * - Digital negatives (via the DNG SDK) + * <p>It has similar options for scaling, cropping, and choosing the output format. + * Unlike the Java API, which can create an android.graphics.Bitmap or + * android.graphics.drawable.Drawable object, AImageDecoder decodes directly + * into memory provided by the client. For more information, see the + * <a href="https://developer.android.com/ndk/guides/image-decoder">Image decoder</a> + * developer guide. + * @{ + */ + +/** + * @file imagedecoder.h + * @brief API for decoding images. + */ + +#ifndef ANDROID_IMAGE_DECODER_H +#define ANDROID_IMAGE_DECODER_H + +#include "bitmap.h" +#include <android/rect.h> +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +struct AAsset; + +#if __ANDROID_API__ >= 30 + +/** + * {@link AImageDecoder} functions result code. Many functions will return one of these + * to indicate success ({@link ANDROID_IMAGE_DECODER_SUCCESS}) or the reason + * for the failure. On failure, any out-parameters should be considered + * uninitialized, except where specified. + */ +enum { + /** + * Decoding was successful and complete. + */ + ANDROID_IMAGE_DECODER_SUCCESS = 0, + /** + * The input is incomplete. + */ + ANDROID_IMAGE_DECODER_INCOMPLETE = -1, + /** + * The input contained an error after decoding some lines. + */ + ANDROID_IMAGE_DECODER_ERROR = -2, + /** + * Could not convert. For example, attempting to decode an image with + * alpha to an opaque format. + */ + ANDROID_IMAGE_DECODER_INVALID_CONVERSION = -3, + /** + * The scale is invalid. It may have overflowed, or it may be incompatible + * with the current alpha setting. + */ + ANDROID_IMAGE_DECODER_INVALID_SCALE = -4, + /** + * Some other parameter is invalid. + */ + ANDROID_IMAGE_DECODER_BAD_PARAMETER = -5, + /** + * Input was invalid before decoding any pixels. + */ + ANDROID_IMAGE_DECODER_INVALID_INPUT = -6, + /** + * A seek was required and it failed. + */ + ANDROID_IMAGE_DECODER_SEEK_ERROR = -7, + /** + * Some other error. For example, an internal allocation failed. + */ + ANDROID_IMAGE_DECODER_INTERNAL_ERROR = -8, + /** + * AImageDecoder did not recognize the format. + */ + ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT = -9 +}; + +struct AImageDecoder; + +/** + * Opaque handle for decoding images. + * + * Create using one of the following: + * - {@link AImageDecoder_createFromAAsset} + * - {@link AImageDecoder_createFromFd} + * - {@link AImageDecoder_createFromBuffer} + * + * After creation, {@link AImageDecoder_getHeaderInfo} can be used to retrieve + * information about the encoded image. Other functions, like + * {@link AImageDecoder_setTargetSize}, can be used to specify how to decode, and + * {@link AImageDecoder_decode} will decode into client provided memory. + * + * {@link AImageDecoder} objects are NOT thread-safe, and should not be shared across + * threads. + */ +typedef struct AImageDecoder AImageDecoder; + +/** + * Create a new {@link AImageDecoder} from an {@link AAsset}. + * + * Available since API level 30. + * + * @param asset {@link AAsset} containing encoded image data. Client is still + * responsible for calling {@link AAsset_close} on it, which may be + * done after deleting the returned {@link AImageDecoder}. + * @param outDecoder On success (i.e. return value is + * {@link ANDROID_IMAGE_DECODER_SUCCESS}), this will be set to + * a newly created {@link AImageDecoder}. Caller is + * responsible for calling {@link AImageDecoder_delete} on it. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value + * indicating the reason for the failure. + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_INCOMPLETE}: The asset was truncated before + * reading the image header. + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: One of the parameters is + * null. + * - {@link ANDROID_IMAGE_DECODER_INVALID_INPUT}: There is an error in the + * header. + * - {@link ANDROID_IMAGE_DECODER_SEEK_ERROR}: The asset failed to seek. + * - {@link ANDROID_IMAGE_DECODER_INTERNAL_ERROR}: Some other error, like a + * failure to allocate memory. + * - {@link ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT}: The format is not + * supported. + */ +int AImageDecoder_createFromAAsset(struct AAsset* asset, AImageDecoder** outDecoder) + __INTRODUCED_IN(30); + +/** + * Create a new {@link AImageDecoder} from a file descriptor. + * + * Available since API level 30. + * + * @param fd Seekable, readable, open file descriptor for encoded data. + * Client is still responsible for closing it, which may be done + * after deleting the returned {@link AImageDecoder}. + * @param outDecoder On success (i.e. return value is + * {@link ANDROID_IMAGE_DECODER_SUCCESS}), this will be set to + * a newly created {@link AImageDecoder}. Caller is + * responsible for calling {@link AImageDecoder_delete} on it. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value + * indicating the reason for the failure. + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_INCOMPLETE}: The file was truncated before + * reading the image header. + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The {@link AImageDecoder} is + * null, or |fd| does not represent a valid, seekable file descriptor. + * - {@link ANDROID_IMAGE_DECODER_INVALID_INPUT}: There is an error in the + * header. + * - {@link ANDROID_IMAGE_DECODER_SEEK_ERROR}: The descriptor failed to seek. + * - {@link ANDROID_IMAGE_DECODER_INTERNAL_ERROR}: Some other error, like a + * failure to allocate memory. + * - {@link ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT}: The format is not + * supported. + */ +int AImageDecoder_createFromFd(int fd, AImageDecoder** outDecoder) __INTRODUCED_IN(30); + +/** + * Create a new AImageDecoder from a buffer. + * + * Available since API level 30. + * + * @param buffer Pointer to encoded data. Must be valid for the entire time + * the {@link AImageDecoder} is used. + * @param length Byte length of buffer. + * @param outDecoder On success (i.e. return value is + * {@link ANDROID_IMAGE_DECODER_SUCCESS}), this will be set to + * a newly created {@link AImageDecoder}. Caller is + * responsible for calling {@link AImageDecoder_delete} on it. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value + * indicating the reason for the failure. + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_INCOMPLETE}: The encoded image was truncated before + * reading the image header. + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: One of the parameters is + * invalid. + * - {@link ANDROID_IMAGE_DECODER_INVALID_INPUT}: There is an error in the + * header. + * - {@link ANDROID_IMAGE_DECODER_INTERNAL_ERROR}: Some other error, like a + * failure to allocate memory. + * - {@link ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT}: The format is not + * supported. + */ +int AImageDecoder_createFromBuffer(const void* buffer, size_t length, + AImageDecoder** outDecoder) __INTRODUCED_IN(30); + +/** + * Delete the AImageDecoder. + * + * Available since API level 30. + */ +void AImageDecoder_delete(AImageDecoder* decoder) __INTRODUCED_IN(30); + +/** + * Choose the desired output format. + * + * Available since API level 30. + * + * @param format {@link AndroidBitmapFormat} to use for the output. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value + * indicating the reason for the failure. On failure, the + * {@link AImageDecoder} uses the format it was already planning + * to use (either its default or a previously successful setting + * from this function). + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The + * {@link AImageDecoder} is null or |format| does not correspond to an + * {@link AndroidBitmapFormat}. + * - {@link ANDROID_IMAGE_DECODER_INVALID_CONVERSION}: The + * {@link AndroidBitmapFormat} is incompatible with the image. + */ +int AImageDecoder_setAndroidBitmapFormat(AImageDecoder*, + int32_t format) __INTRODUCED_IN(30); + +/** + * Specify whether the output's pixels should be unpremultiplied. + * + * By default, {@link AImageDecoder_decodeImage} will premultiply the pixels, if they have alpha. + * Pass true to this method to leave them unpremultiplied. This has no effect on an + * opaque image. + * + * Available since API level 30. + * + * @param unpremultipliedRequired Pass true to leave the pixels unpremultiplied. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value + * indicating the reason for the failure. + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_INVALID_CONVERSION}: Unpremultiplied is not + * possible due to an existing scale set by + * {@link AImageDecoder_setTargetSize}. + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The + * {@link AImageDecoder} is null. + */ +int AImageDecoder_setUnpremultipliedRequired(AImageDecoder*, + bool unpremultipliedRequired) __INTRODUCED_IN(30); + +/** + * Choose the dataspace for the output. + * + * Ignored by {@link ANDROID_BITMAP_FORMAT_A_8}, which does not support + * an {@link ADataSpace}. + * + * Available since API level 30. + * + * @param dataspace The {@link ADataSpace} to decode into. An ADataSpace + * specifies how to interpret the colors. By default, + * AImageDecoder will decode into the ADataSpace specified by + * {@link AImageDecoderHeaderInfo_getDataSpace}. If this + * parameter is set to a different ADataSpace, AImageDecoder + * will transform the output into the specified ADataSpace. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value + * indicating the reason for the failure. + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The + * {@link AImageDecoder} is null or |dataspace| does not correspond to an + * {@link ADataSpace} value. + */ +int AImageDecoder_setDataSpace(AImageDecoder*, int32_t dataspace) __INTRODUCED_IN(30); + +/** + * Specify the output size for a decoded image. + * + * Future calls to {@link AImageDecoder_decodeImage} will sample or scale the + * encoded image to reach the desired size. If a crop rect is set (via + * {@link AImageDecoder_setCrop}), it must be contained within the dimensions + * specified by width and height, and the output image will be the size of the + * crop rect. + * + * Available since API level 30. + * + * @param width Width of the output (prior to cropping). + * This will affect future calls to + * {@link AImageDecoder_getMinimumStride}, which will now return + * a value based on this width. + * @param height Height of the output (prior to cropping). + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value + * indicating the reason for the failure. + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The + * {@link AImageDecoder} is null. + * - {@link ANDROID_IMAGE_DECODER_INVALID_SCALE}: |width| or |height| is <= 0, + * the size is too big, any existing crop is not contained by the new image dimensions, + * or the scale is incompatible with a previous call to + * {@link AImageDecoder_setUnpremultipliedRequired}(true). + */ +int AImageDecoder_setTargetSize(AImageDecoder*, int32_t width, int32_t height) __INTRODUCED_IN(30); + + +/** + * Compute the dimensions to use for a given sampleSize. + * + * Although AImageDecoder can scale to an arbitrary target size (see + * {@link AImageDecoder_setTargetSize}), some sizes may be more efficient than + * others. This computes the most efficient target size to use to reach a + * particular sampleSize. + * + * Available since API level 30. + * + * @param sampleSize A subsampling rate of the original image. Must be greater + * than or equal to 1. A sampleSize of 2 means to skip every + * other pixel/line, resulting in a width and height that are + * 1/2 of the original dimensions, with 1/4 the number of + * pixels. + * @param width Out parameter for the width sampled by sampleSize, and rounded + * in the direction that the decoder can do most efficiently. + * @param height Out parameter for the height sampled by sampleSize, and rounded + * in the direction that the decoder can do most efficiently. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value + * indicating the reason for the failure. + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The + * {@link AImageDecoder}, |width| or |height| is null or |sampleSize| is < 1. + */ +int AImageDecoder_computeSampledSize(const AImageDecoder*, int sampleSize, + int32_t* width, int32_t* height) __INTRODUCED_IN(30); +/** + * Specify how to crop the output after scaling (if any). + * + * Future calls to {@link AImageDecoder_decodeImage} will crop their output to + * the specified {@link ARect}. Clients will only need to allocate enough memory + * for the cropped ARect. + * + * Available since API level 30. + * + * @param crop Rectangle describing a crop of the decode. It must be contained inside of + * the (possibly scaled, by {@link AImageDecoder_setTargetSize}) + * image dimensions. This will affect future calls to + * {@link AImageDecoder_getMinimumStride}, which will now return a + * value based on the width of the crop. An empty ARect - + * specifically { 0, 0, 0, 0 } - may be used to remove the cropping + * behavior. Any other empty or unsorted ARects will result in + * returning {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value + * indicating the reason for the failure. + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The + * {@link AImageDecoder} is null or the crop is not contained by the + * (possibly scaled) image dimensions. + */ +int AImageDecoder_setCrop(AImageDecoder*, ARect crop) __INTRODUCED_IN(30); + +struct AImageDecoderHeaderInfo; +/** + * Opaque handle for representing information about the encoded image. Retrieved + * using {@link AImageDecoder_getHeaderInfo} and passed to methods like + * {@link AImageDecoderHeaderInfo_getWidth} and + * {@link AImageDecoderHeaderInfo_getHeight}. + */ +typedef struct AImageDecoderHeaderInfo AImageDecoderHeaderInfo; + +/** + * Return an opaque handle for reading header info. + * + * This is owned by the {@link AImageDecoder} and will be destroyed when the + * AImageDecoder is destroyed via {@link AImageDecoder_delete}. + * + * Available since API level 30. + */ +const AImageDecoderHeaderInfo* AImageDecoder_getHeaderInfo( + const AImageDecoder*) __INTRODUCED_IN(30); + +/** + * Report the native width of the encoded image. This is also the logical + * pixel width of the output, unless {@link AImageDecoder_setTargetSize} is + * used to choose a different size or {@link AImageDecoder_setCrop} is used to + * set a crop rect. + * + * Available since API level 30. + */ +int32_t AImageDecoderHeaderInfo_getWidth(const AImageDecoderHeaderInfo*) __INTRODUCED_IN(30); + +/** + * Report the native height of the encoded image. This is also the logical + * pixel height of the output, unless {@link AImageDecoder_setTargetSize} is + * used to choose a different size or {@link AImageDecoder_setCrop} is used to + * set a crop rect. + * + * Available since API level 30. + */ +int32_t AImageDecoderHeaderInfo_getHeight(const AImageDecoderHeaderInfo*) __INTRODUCED_IN(30); + +/** + * Report the mimeType of the encoded image. + * + * Available since API level 30. + * + * @return a string literal describing the mime type. + */ +const char* AImageDecoderHeaderInfo_getMimeType( + const AImageDecoderHeaderInfo*) __INTRODUCED_IN(30); + +/** + * Report the {@link AndroidBitmapFormat} the AImageDecoder will decode to + * by default. {@link AImageDecoder} will try to choose one that is sensible + * for the image and the system. Note that this does not indicate the + * encoded format of the image. + * + * Available since API level 30. + */ +int32_t AImageDecoderHeaderInfo_getAndroidBitmapFormat( + const AImageDecoderHeaderInfo*) __INTRODUCED_IN(30); + +/** + * Report how the {@link AImageDecoder} will handle alpha by default. If the image + * contains no alpha (according to its header), this will return + * {@link ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE}. If the image may contain alpha, + * this returns {@link ANDROID_BITMAP_FLAGS_ALPHA_PREMUL}, because + * {@link AImageDecoder_decodeImage} will premultiply pixels by default. + * + * Available since API level 30. + */ +int AImageDecoderHeaderInfo_getAlphaFlags( + const AImageDecoderHeaderInfo*) __INTRODUCED_IN(30); + +/** + * Report the dataspace the AImageDecoder will decode to by default. + * + * By default, {@link AImageDecoder_decodeImage} will not do any color + * conversion. + * + * Available since API level 30. + * + * @return The {@link ADataSpace} representing the way the colors + * are encoded (or {@link ADATASPACE_UNKNOWN} if there is not a + * corresponding ADataSpace). This specifies how to interpret the colors + * in the decoded image, unless {@link AImageDecoder_setDataSpace} is + * called to decode to a different ADataSpace. + * + * Note that ADataSpace only exposes a few values. This may return + * {@link ADATASPACE_UNKNOWN}, even for Named ColorSpaces, if they have + * no corresponding {@link ADataSpace}. + */ +int32_t AImageDecoderHeaderInfo_getDataSpace( + const AImageDecoderHeaderInfo*) __INTRODUCED_IN(30); + +/** + * Return the minimum stride that can be used in + * {@link AImageDecoder_decodeImage). + * + * This stride provides no padding, meaning it will be exactly equal to the + * width times the number of bytes per pixel for the {@link AndroidBitmapFormat} + * being used. + * + * If the output is scaled (via {@link AImageDecoder_setTargetSize}) and/or + * cropped (via {@link AImageDecoder_setCrop}), this takes those into account. + * + * Available since API level 30. + */ +size_t AImageDecoder_getMinimumStride(AImageDecoder*) __INTRODUCED_IN(30); + +/** + * Decode the image into pixels, using the settings of the {@link AImageDecoder}. + * + * Available since API level 30. + * + * @param decoder Opaque object representing the decoder. + * @param pixels On success, will be filled with the result + * of the decode. Must be large enough to hold |size| bytes. + * @param stride Width in bytes of a single row. Must be at least + * {@link AImageDecoder_getMinimumStride} and a multiple of the + * bytes per pixel of the {@link AndroidBitmapFormat}. + * @param size Size of the pixel buffer in bytes. Must be at least + * stride * (height - 1) + + * {@link AImageDecoder_getMinimumStride}. + * @return {@link ANDROID_IMAGE_DECODER_SUCCESS} on success or a value + * indicating the reason for the failure. + * + * Errors: + * - {@link ANDROID_IMAGE_DECODER_INCOMPLETE}: The image was truncated. A + * partial image was decoded, and undecoded lines have been initialized to all + * zeroes. + * - {@link ANDROID_IMAGE_DECODER_ERROR}: The image contained an error. A + * partial image was decoded, and undecoded lines have been initialized to all + * zeroes. + * - {@link ANDROID_IMAGE_DECODER_BAD_PARAMETER}: The {@link AImageDecoder} or + * |pixels| is null, the stride is not large enough or not pixel aligned, or + * |size| is not large enough. + * - {@link ANDROID_IMAGE_DECODER_SEEK_ERROR}: The asset or file descriptor + * failed to seek. + * - {@link ANDROID_IMAGE_DECODER_INTERNAL_ERROR}: Some other error, like a + * failure to allocate memory. + */ +int AImageDecoder_decodeImage(AImageDecoder* decoder, + void* pixels, size_t stride, + size_t size) __INTRODUCED_IN(30); + +#endif // __ANDROID_API__ >= 30 + +#ifdef __cplusplus +} +#endif + +#endif // ANDROID_IMAGE_DECODER_H + +/** @} */ diff --git a/include/android/input.h b/include/android/input.h index ce439c6d75..dbfd61eb05 100644 --- a/include/android/input.h +++ b/include/android/input.h @@ -158,7 +158,10 @@ enum { AINPUT_EVENT_TYPE_KEY = 1, /** Indicates that the input event is a motion event. */ - AINPUT_EVENT_TYPE_MOTION = 2 + AINPUT_EVENT_TYPE_MOTION = 2, + + /** Focus event */ + AINPUT_EVENT_TYPE_FOCUS = 3, }; /** @@ -790,6 +793,8 @@ enum { AMOTION_EVENT_TOOL_TYPE_MOUSE = 3, /** eraser */ AMOTION_EVENT_TOOL_TYPE_ERASER = 4, + /** palm */ + AMOTION_EVENT_TOOL_TYPE_PALM = 5, }; /** diff --git a/include/android/sensor.h b/include/android/sensor.h index 3ebe79fd2e..eb407794d1 100644 --- a/include/android/sensor.h +++ b/include/android/sensor.h @@ -15,6 +15,9 @@ */ /** + * Structures and functions to receive and process sensor events in + * native code. + * * @addtogroup Sensor * @{ */ @@ -42,12 +45,6 @@ * - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES */ -/** - * Structures and functions to receive and process sensor events in - * native code. - * - */ - #include <android/looper.h> #include <stdbool.h> @@ -245,6 +242,13 @@ enum { * {@link ASENSOR_TYPE_ACCELEROMETER_UNCALIBRATED} */ ASENSOR_TYPE_ACCELEROMETER_UNCALIBRATED = 35, + /** + * {@link ASENSOR_TYPE_HINGE_ANGLE} + * reporting-mode: on-change + * + * The hinge angle sensor value is returned in degrees. + */ + ASENSOR_TYPE_HINGE_ANGLE = 36, }; /** diff --git a/include/android/surface_control.h b/include/android/surface_control.h index 90e565359e..cbcf6ec5c0 100644 --- a/include/android/surface_control.h +++ b/include/android/surface_control.h @@ -149,7 +149,7 @@ int64_t ASurfaceTransactionStats_getLatchTime(ASurfaceTransactionStats* surface_ /** * Returns a sync fence that signals when the transaction has been presented. * The recipient of the callback takes ownership of the fence and is responsible for closing - * it. + * it. If a device does not support present fences, a -1 will be returned. * * Available since API level 29. */ @@ -407,6 +407,36 @@ void ASurfaceTransaction_setHdrMetadata_cta861_3(ASurfaceTransaction* transactio #endif // __ANDROID_API__ >= 29 +#if __ANDROID_API__ >= 30 + +/** + * Sets the intended frame rate for |surface_control|. + * + * On devices that are capable of running the display at different refresh rates, the system may + * choose a display refresh rate to better match this surface's frame rate. Usage of this API won't + * directly affect the application's frame production pipeline. However, because the system may + * change the display refresh rate, calls to this function may result in changes to Choreographer + * callback timings, and changes to the time interval at which the system releases buffers back to + * the application. + * + * |frameRate| is the intended frame rate of this surface, in frames per second. 0 is a special + * value that indicates the app will accept the system's choice for the display frame rate, which is + * the default behavior if this function isn't called. The frameRate param does <em>not</em> need to + * be a valid refresh rate for this device's display - e.g., it's fine to pass 30fps to a device + * that can only run the display at 60fps. + * + * |compatibility| The frame rate compatibility of this surface. The compatibility value may + * influence the system's choice of display frame rate. To specify a compatibility use the + * ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* enum. + * + * Available since API level 30. + */ +void ASurfaceTransaction_setFrameRate(ASurfaceTransaction* transaction, + ASurfaceControl* surface_control, float frameRate, + int8_t compatibility) __INTRODUCED_IN(30); + +#endif // __ANDROID_API__ >= 30 + __END_DECLS #endif // ANDROID_SURFACE_CONTROL_H diff --git a/include/android/thermal.h b/include/android/thermal.h new file mode 100644 index 0000000000..83582d6791 --- /dev/null +++ b/include/android/thermal.h @@ -0,0 +1,190 @@ +/* + * 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. + */ + +/** + * @addtogroup Thermal + * @{ + */ + +/** + * @file thermal.h + */ + +#ifndef _ANDROID_THERMAL_H +#define _ANDROID_THERMAL_H + +#include <sys/cdefs.h> + +/****************************************************************** + * + * IMPORTANT NOTICE: + * + * This file is part of Android's set of stable system headers + * exposed by the Android NDK (Native Development Kit). + * + * Third-party source AND binary code relies on the definitions + * here to be FROZEN ON ALL UPCOMING PLATFORM RELEASES. + * + * - DO NOT MODIFY ENUMS (EXCEPT IF YOU ADD NEW 32-BIT VALUES) + * - DO NOT MODIFY CONSTANTS OR FUNCTIONAL MACROS + * - DO NOT CHANGE THE SIGNATURE OF FUNCTIONS IN ANY WAY + * - DO NOT CHANGE THE LAYOUT OR SIZE OF STRUCTURES + */ + +/* + * Structures and functions to access thermal status and register/unregister + * thermal status listener in native code. + */ + +#include <stdint.h> +#include <sys/types.h> + +#if !defined(__INTRODUCED_IN) +#define __INTRODUCED_IN(30) /* Introduced in API level 30 */ +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +enum AThermalStatus { + /** Error in thermal status. */ + ATHERMAL_STATUS_ERROR = -1, + /** Not under throttling. */ + ATHERMAL_STATUS_NONE = 0, + /** Light throttling where UX is not impacted. */ + ATHERMAL_STATUS_LIGHT = 1, + /** Moderate throttling where UX is not largely impacted. */ + ATHERMAL_STATUS_MODERATE = 2, + /** Severe throttling where UX is largely impacted. */ + ATHERMAL_STATUS_SEVERE = 3, + /** Platform has done everything to reduce power. */ + ATHERMAL_STATUS_CRITICAL = 4, + /** + * Key components in platform are shutting down due to thermal condition. + * Device functionalities will be limited. + */ + ATHERMAL_STATUS_EMERGENCY = 5, + /** Need shutdown immediately. */ + ATHERMAL_STATUS_SHUTDOWN = 6, +}; + +/** + * An opaque type representing a handle to a thermal manager. + * An instance of thermal manager must be acquired prior to + * using thermal status APIs and must be released after use. + * + * <p>To use:<ul> + * <li>Create a new thermal manager instance by calling the + * {@link AThermal_acquireManager} function.</li> + * <li>Get current thermal status with + * {@link AThermal_getCurrentThermalStatus}.</li> + * <li>Register a thermal status listener with + * {@link AThermal_registerThermalStatusListener}.</li> + * <li>Unregister a thermal status listener with + * {@link AThermal_unregisterThermalStatusListener}.</li> + * <li>Release the thermal manager instance with + * {@link AThermal_releaseManager}.</li></ul></p> + * + */ +typedef struct AThermalManager AThermalManager; + +/** + * Prototype of the function that is called when thermal status changes. + * It's passed the updated thermal status as parameter, as well as the + * pointer provided by the client that registered a callback. + */ +typedef void (*AThermal_StatusCallback)(void *data, AThermalStatus status); + +#if __ANDROID_API__ >= 30 + +/** + * Acquire an instance of the thermal manager. This must be freed using + * {@link AThermal_releaseManager}. + * + * Available since API level 30. + * + * @return manager instance on success, nullptr on failure. + */ +AThermalManager* AThermal_acquireManager() __INTRODUCED_IN(30); + +/** + * Release the thermal manager pointer acquired via + * {@link AThermal_acquireManager}. + * + * Available since API level 30. + * + * @param manager The manager to be released. + */ +void AThermal_releaseManager(AThermalManager *manager) __INTRODUCED_IN(30); + +/** + * Gets the current thermal status. + * + * Available since API level 30. + * + * @param manager The manager instance to use to query the thermal status. + * Acquired via {@link AThermal_acquireManager}. + * + * @return current thermal status, ATHERMAL_STATUS_ERROR on failure. + */ +AThermalStatus AThermal_getCurrentThermalStatus(AThermalManager *manager) __INTRODUCED_IN(30); + +/** + * Register the thermal status listener for thermal status change. + * + * Available since API level 30. + * + * @param manager The manager instance to use to register. + * Acquired via {@link AThermal_acquireManager}. + * @param callback The callback function to be called when thermal status updated. + * @param data The data pointer to be passed when callback is called. + * + * @return 0 on success + * EINVAL if the listener and data pointer were previously added and not removed. + * EPERM if the required permission is not held. + * EPIPE if communication with the system service has failed. + */ +int AThermal_registerThermalStatusListener(AThermalManager *manager, + AThermal_StatusCallback callback, void *data) __INTRODUCED_IN(30); + +/** + * Unregister the thermal status listener previously resgistered. + * + * Available since API level 30. + * + * @param manager The manager instance to use to unregister. + * Acquired via {@link AThermal_acquireManager}. + * @param callback The callback function to be called when thermal status updated. + * @param data The data pointer to be passed when callback is called. + * + * @return 0 on success + * EINVAL if the listener and data pointer were not previously added. + * EPERM if the required permission is not held. + * EPIPE if communication with the system service has failed. + */ +int AThermal_unregisterThermalStatusListener(AThermalManager *manager, + AThermal_StatusCallback callback, void *data) __INTRODUCED_IN(30); + +#endif // __ANDROID_API__ >= 30 + +#ifdef __cplusplus +} +#endif + +#endif // _ANDROID_THERMAL_H + +/** @} */ diff --git a/include/input/DisplayViewport.h b/include/input/DisplayViewport.h index fa456bb213..2427a075a1 100644 --- a/include/input/DisplayViewport.h +++ b/include/input/DisplayViewport.h @@ -17,16 +17,23 @@ #ifndef _LIBINPUT_DISPLAY_VIEWPORT_H #define _LIBINPUT_DISPLAY_VIEWPORT_H +#include <cinttypes> +#include <optional> + #include <android-base/stringprintf.h> -#include <ui/DisplayInfo.h> #include <input/Input.h> -#include <inttypes.h> -#include <optional> using android::base::StringPrintf; namespace android { +enum { + DISPLAY_ORIENTATION_0 = 0, + DISPLAY_ORIENTATION_90 = 1, + DISPLAY_ORIENTATION_180 = 2, + DISPLAY_ORIENTATION_270 = 3 +}; + /** * Describes the different type of viewports supported by input flinger. * Keep in sync with values in InputManagerService.java. @@ -67,36 +74,40 @@ struct DisplayViewport { int32_t physicalBottom; int32_t deviceWidth; int32_t deviceHeight; + bool isActive; std::string uniqueId; // The actual (hardware) port that the associated display is connected to. // Not all viewports will have this specified. std::optional<uint8_t> physicalPort; ViewportType type; - DisplayViewport() : - displayId(ADISPLAY_ID_NONE), orientation(DISPLAY_ORIENTATION_0), - logicalLeft(0), logicalTop(0), logicalRight(0), logicalBottom(0), - physicalLeft(0), physicalTop(0), physicalRight(0), physicalBottom(0), - deviceWidth(0), deviceHeight(0), uniqueId(), physicalPort(std::nullopt), - type(ViewportType::VIEWPORT_INTERNAL) { - } + DisplayViewport() + : displayId(ADISPLAY_ID_NONE), + orientation(DISPLAY_ORIENTATION_0), + logicalLeft(0), + logicalTop(0), + logicalRight(0), + logicalBottom(0), + physicalLeft(0), + physicalTop(0), + physicalRight(0), + physicalBottom(0), + deviceWidth(0), + deviceHeight(0), + isActive(false), + uniqueId(), + physicalPort(std::nullopt), + type(ViewportType::VIEWPORT_INTERNAL) {} bool operator==(const DisplayViewport& other) const { - return displayId == other.displayId - && orientation == other.orientation - && logicalLeft == other.logicalLeft - && logicalTop == other.logicalTop - && logicalRight == other.logicalRight - && logicalBottom == other.logicalBottom - && physicalLeft == other.physicalLeft - && physicalTop == other.physicalTop - && physicalRight == other.physicalRight - && physicalBottom == other.physicalBottom - && deviceWidth == other.deviceWidth - && deviceHeight == other.deviceHeight - && uniqueId == other.uniqueId - && physicalPort == other.physicalPort - && type == other.type; + return displayId == other.displayId && orientation == other.orientation && + logicalLeft == other.logicalLeft && logicalTop == other.logicalTop && + logicalRight == other.logicalRight && logicalBottom == other.logicalBottom && + physicalLeft == other.physicalLeft && physicalTop == other.physicalTop && + physicalRight == other.physicalRight && physicalBottom == other.physicalBottom && + deviceWidth == other.deviceWidth && deviceHeight == other.deviceHeight && + isActive == other.isActive && uniqueId == other.uniqueId && + physicalPort == other.physicalPort && type == other.type; } bool operator!=(const DisplayViewport& other) const { @@ -120,6 +131,7 @@ struct DisplayViewport { physicalBottom = height; deviceWidth = width; deviceHeight = height; + isActive = false; uniqueId.clear(); physicalPort = std::nullopt; type = ViewportType::VIEWPORT_INTERNAL; @@ -127,18 +139,16 @@ struct DisplayViewport { std::string toString() const { return StringPrintf("Viewport %s: displayId=%d, uniqueId=%s, port=%s, orientation=%d, " - "logicalFrame=[%d, %d, %d, %d], " - "physicalFrame=[%d, %d, %d, %d], " - "deviceSize=[%d, %d]", - viewportTypeToString(type), displayId, - uniqueId.c_str(), - physicalPort ? StringPrintf("%" PRIu8, *physicalPort).c_str() : "<none>", - orientation, - logicalLeft, logicalTop, - logicalRight, logicalBottom, - physicalLeft, physicalTop, - physicalRight, physicalBottom, - deviceWidth, deviceHeight); + "logicalFrame=[%d, %d, %d, %d], " + "physicalFrame=[%d, %d, %d, %d], " + "deviceSize=[%d, %d], " + "isActive=[%d]", + viewportTypeToString(type), displayId, uniqueId.c_str(), + physicalPort ? StringPrintf("%" PRIu8, *physicalPort).c_str() + : "<none>", + orientation, logicalLeft, logicalTop, logicalRight, logicalBottom, + physicalLeft, physicalTop, physicalRight, physicalBottom, deviceWidth, + deviceHeight, isActive); } }; diff --git a/include/input/Input.h b/include/input/Input.h index 805957a5ca..54b4e5a737 100644 --- a/include/input/Input.h +++ b/include/input/Input.h @@ -24,12 +24,16 @@ */ #include <android/input.h> +#include <math.h> +#include <stdint.h> #include <utils/BitSet.h> #include <utils/KeyedVector.h> #include <utils/RefBase.h> #include <utils/Timers.h> #include <utils/Vector.h> -#include <stdint.h> +#include <array> +#include <limits> +#include <queue> /* * Additional private constants not defined in ndk/ui/input.h. @@ -69,6 +73,19 @@ enum { AMOTION_EVENT_FLAG_TAINTED = 0x80000000, }; +/** + * Allowed VerifiedKeyEvent flags. All other flags from KeyEvent do not get verified. + * These values must be kept in sync with VerifiedKeyEvent.java + */ +constexpr int32_t VERIFIED_KEY_EVENT_FLAGS = AKEY_EVENT_FLAG_CANCELED; + +/** + * Allowed VerifiedMotionEventFlags. All other flags from MotionEvent do not get verified. + * These values must be kept in sync with VerifiedMotionEvent.java + */ +constexpr int32_t VERIFIED_MOTION_EVENT_FLAGS = + AMOTION_EVENT_FLAG_WINDOW_IS_OBSCURED | AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED; + enum { /* Used when a motion event is not associated with any display. * Typically used for non-pointer events. */ @@ -164,6 +181,8 @@ namespace android { class Parcel; #endif +const char* inputEventTypeToString(int32_t type); + /* * Flags that flow alongside events in the input dispatch system to help with certain * policy decisions such as waking from device sleep. @@ -246,6 +265,50 @@ enum class MotionClassification : uint8_t { */ const char* motionClassificationToString(MotionClassification classification); +/** + * Generator of unique numbers used to identify input events. + * + * Layout of ID: + * |--------------------------|---------------------------| + * | 2 bits for source | 30 bits for random number | + * |--------------------------|---------------------------| + */ +class IdGenerator { +private: + static constexpr uint32_t SOURCE_SHIFT = 30; + +public: + // Used to divide integer space to ensure no conflict among these sources./ + enum class Source : int32_t { + INPUT_READER = 0x0 << SOURCE_SHIFT, + INPUT_DISPATCHER = 0x1 << SOURCE_SHIFT, + OTHER = 0x3 << SOURCE_SHIFT, // E.g. app injected events + }; + IdGenerator(Source source); + + int32_t nextId() const; + + // Extract source from given id. + static inline Source getSource(int32_t id) { return static_cast<Source>(SOURCE_MASK & id); } + +private: + const Source mSource; + + static constexpr int32_t SOURCE_MASK = 0x3 << SOURCE_SHIFT; +}; + +/** + * Invalid value for cursor position. Used for non-mouse events, tests and injected events. Don't + * use it for direct comparison with any other value, because NaN isn't equal to itself according to + * IEEE 754. Use isnan() instead to check if a cursor position is valid. + */ +constexpr float AMOTION_EVENT_INVALID_CURSOR_POSITION = std::numeric_limits<float>::quiet_NaN(); + +/** + * Invalid value of HMAC - SHA256. Any events with this HMAC value will be marked as not verified. + */ +constexpr std::array<uint8_t, 32> INVALID_HMAC = {0}; + /* * Pointer coordinate data. */ @@ -334,24 +397,33 @@ public: virtual int32_t getType() const = 0; + inline int32_t getId() const { return mId; } + inline int32_t getDeviceId() const { return mDeviceId; } - inline int32_t getSource() const { return mSource; } + inline uint32_t getSource() const { return mSource; } - inline void setSource(int32_t source) { mSource = source; } + inline void setSource(uint32_t source) { mSource = source; } inline int32_t getDisplayId() const { return mDisplayId; } inline void setDisplayId(int32_t displayId) { mDisplayId = displayId; } + inline std::array<uint8_t, 32> getHmac() const { return mHmac; } + + static int32_t nextId(); protected: - void initialize(int32_t deviceId, int32_t source, int32_t displayId); + void initialize(int32_t id, int32_t deviceId, uint32_t source, int32_t displayId, + std::array<uint8_t, 32> hmac); + void initialize(const InputEvent& from); + int32_t mId; int32_t mDeviceId; - int32_t mSource; + uint32_t mSource; int32_t mDisplayId; + std::array<uint8_t, 32> mHmac; }; /* @@ -384,20 +456,14 @@ public: static const char* getLabel(int32_t keyCode); static int32_t getKeyCodeFromLabel(const char* label); - void initialize( - int32_t deviceId, - int32_t source, - int32_t displayId, - int32_t action, - int32_t flags, - int32_t keyCode, - int32_t scanCode, - int32_t metaState, - int32_t repeatCount, - nsecs_t downTime, - nsecs_t eventTime); + void initialize(int32_t id, int32_t deviceId, uint32_t source, int32_t displayId, + std::array<uint8_t, 32> hmac, int32_t action, int32_t flags, int32_t keyCode, + int32_t scanCode, int32_t metaState, int32_t repeatCount, nsecs_t downTime, + nsecs_t eventTime); void initialize(const KeyEvent& from); + static const char* actionToString(int32_t action); + protected: int32_t mAction; int32_t mFlags; @@ -451,6 +517,10 @@ public: inline void setActionButton(int32_t button) { mActionButton = button; } + inline float getXScale() const { return mXScale; } + + inline float getYScale() const { return mYScale; } + inline float getXOffset() const { return mXOffset; } inline float getYOffset() const { return mYOffset; } @@ -459,6 +529,18 @@ public: inline float getYPrecision() const { return mYPrecision; } + inline float getRawXCursorPosition() const { return mRawXCursorPosition; } + + float getXCursorPosition() const; + + inline float getRawYCursorPosition() const { return mRawYCursorPosition; } + + float getYCursorPosition() const; + + void setCursorPosition(float x, float y); + + static inline bool isValidCursorPosition(float x, float y) { return !isnan(x) && !isnan(y); } + inline nsecs_t getDownTime() const { return mDownTime; } inline void setDownTime(nsecs_t downTime) { mDownTime = downTime; } @@ -600,26 +682,14 @@ public: ssize_t findPointerIndex(int32_t pointerId) const; - void initialize( - int32_t deviceId, - int32_t source, - int32_t displayId, - int32_t action, - int32_t actionButton, - int32_t flags, - int32_t edgeFlags, - int32_t metaState, - int32_t buttonState, - MotionClassification classification, - float xOffset, - float yOffset, - float xPrecision, - float yPrecision, - nsecs_t downTime, - nsecs_t eventTime, - size_t pointerCount, - const PointerProperties* pointerProperties, - const PointerCoords* pointerCoords); + void initialize(int32_t id, int32_t deviceId, uint32_t source, int32_t displayId, + std::array<uint8_t, 32> hmac, int32_t action, int32_t actionButton, + int32_t flags, int32_t edgeFlags, int32_t metaState, int32_t buttonState, + MotionClassification classification, float xScale, float yScale, float xOffset, + float yOffset, float xPrecision, float yPrecision, float rawXCursorPosition, + float rawYCursorPosition, nsecs_t downTime, nsecs_t eventTime, + size_t pointerCount, const PointerProperties* pointerProperties, + const PointerCoords* pointerCoords); void copyFrom(const MotionEvent* other, bool keepHistory); @@ -640,7 +710,7 @@ public: status_t writeToParcel(Parcel* parcel) const; #endif - static bool isTouchEvent(int32_t source, int32_t action); + static bool isTouchEvent(uint32_t source, int32_t action); inline bool isTouchEvent() const { return isTouchEvent(mSource, mAction); } @@ -657,6 +727,8 @@ public: static const char* getLabel(int32_t axis); static int32_t getAxisFromLabel(const char* label); + static const char* actionToString(int32_t action); + protected: int32_t mAction; int32_t mActionButton; @@ -665,10 +737,14 @@ protected: int32_t mMetaState; int32_t mButtonState; MotionClassification mClassification; + float mXScale; + float mYScale; float mXOffset; float mYOffset; float mXPrecision; float mYPrecision; + float mRawXCursorPosition; + float mRawYCursorPosition; nsecs_t mDownTime; Vector<PointerProperties> mPointerProperties; Vector<nsecs_t> mSampleEventTimes; @@ -676,6 +752,77 @@ protected: }; /* + * Focus events. + */ +class FocusEvent : public InputEvent { +public: + virtual ~FocusEvent() {} + + virtual int32_t getType() const override { return AINPUT_EVENT_TYPE_FOCUS; } + + inline bool getHasFocus() const { return mHasFocus; } + + inline bool getInTouchMode() const { return mInTouchMode; } + + void initialize(int32_t id, bool hasFocus, bool inTouchMode); + + void initialize(const FocusEvent& from); + +protected: + bool mHasFocus; + bool mInTouchMode; +}; + +/** + * Base class for verified events. + * Do not create a VerifiedInputEvent explicitly. + * Use helper functions to create them from InputEvents. + */ +struct __attribute__((__packed__)) VerifiedInputEvent { + enum class Type : int32_t { + KEY = AINPUT_EVENT_TYPE_KEY, + MOTION = AINPUT_EVENT_TYPE_MOTION, + }; + + Type type; + int32_t deviceId; + nsecs_t eventTimeNanos; + uint32_t source; + int32_t displayId; +}; + +/** + * Same as KeyEvent, but only contains the data that can be verified. + * If you update this class, you must also update VerifiedKeyEvent.java + */ +struct __attribute__((__packed__)) VerifiedKeyEvent : public VerifiedInputEvent { + int32_t action; + nsecs_t downTimeNanos; + int32_t flags; + int32_t keyCode; + int32_t scanCode; + int32_t metaState; + int32_t repeatCount; +}; + +/** + * Same as MotionEvent, but only contains the data that can be verified. + * If you update this class, you must also update VerifiedMotionEvent.java + */ +struct __attribute__((__packed__)) VerifiedMotionEvent : public VerifiedInputEvent { + float rawX; + float rawY; + int32_t actionMasked; + nsecs_t downTimeNanos; + int32_t flags; + int32_t metaState; + int32_t buttonState; +}; + +VerifiedKeyEvent verifiedKeyEventFromKeyEvent(const KeyEvent& event); +VerifiedMotionEvent verifiedMotionEventFromMotionEvent(const MotionEvent& event); + +/* * Input event factory. */ class InputEventFactoryInterface { @@ -687,6 +834,7 @@ public: virtual KeyEvent* createKeyEvent() = 0; virtual MotionEvent* createMotionEvent() = 0; + virtual FocusEvent* createFocusEvent() = 0; }; /* @@ -698,12 +846,14 @@ public: PreallocatedInputEventFactory() { } virtual ~PreallocatedInputEventFactory() { } - virtual KeyEvent* createKeyEvent() { return & mKeyEvent; } - virtual MotionEvent* createMotionEvent() { return & mMotionEvent; } + virtual KeyEvent* createKeyEvent() override { return &mKeyEvent; } + virtual MotionEvent* createMotionEvent() override { return &mMotionEvent; } + virtual FocusEvent* createFocusEvent() override { return &mFocusEvent; } private: KeyEvent mKeyEvent; MotionEvent mMotionEvent; + FocusEvent mFocusEvent; }; /* @@ -714,16 +864,18 @@ public: explicit PooledInputEventFactory(size_t maxPoolSize = 20); virtual ~PooledInputEventFactory(); - virtual KeyEvent* createKeyEvent(); - virtual MotionEvent* createMotionEvent(); + virtual KeyEvent* createKeyEvent() override; + virtual MotionEvent* createMotionEvent() override; + virtual FocusEvent* createFocusEvent() override; void recycle(InputEvent* event); private: const size_t mMaxPoolSize; - Vector<KeyEvent*> mKeyEventPool; - Vector<MotionEvent*> mMotionEventPool; + std::queue<std::unique_ptr<KeyEvent>> mKeyEventPool; + std::queue<std::unique_ptr<MotionEvent>> mMotionEventPool; + std::queue<std::unique_ptr<FocusEvent>> mFocusEventPool; }; } // namespace android diff --git a/include/input/InputApplication.h b/include/input/InputApplication.h index 7f04611309..86de394a31 100644 --- a/include/input/InputApplication.h +++ b/include/input/InputApplication.h @@ -61,6 +61,11 @@ public: return mInfo.token ? mInfo.dispatchingTimeout : defaultValue; } + inline std::chrono::nanoseconds getDispatchingTimeout( + std::chrono::nanoseconds defaultValue) const { + return mInfo.token ? std::chrono::nanoseconds(mInfo.dispatchingTimeout) : defaultValue; + } + inline sp<IBinder> getApplicationToken() const { return mInfo.token; } diff --git a/include/input/InputDevice.h b/include/input/InputDevice.h index b6efc82fd4..20a17e3347 100644 --- a/include/input/InputDevice.h +++ b/include/input/InputDevice.h @@ -180,6 +180,8 @@ enum ReservedInputDeviceId : int32_t { VIRTUAL_KEYBOARD_ID = -1, // Device id of the "built-in" keyboard if there is one. BUILT_IN_KEYBOARD_ID = 0, + // First device id available for dynamic devices + END_RESERVED_ID = 1, }; } // namespace android diff --git a/include/input/InputEventLabels.h b/include/input/InputEventLabels.h index 59d16d15af..b327d76b1c 100644 --- a/include/input/InputEventLabels.h +++ b/include/input/InputEventLabels.h @@ -359,6 +359,9 @@ static const InputEventLabel AXES[] = { DEFINE_AXIS(BRAKE), DEFINE_AXIS(DISTANCE), DEFINE_AXIS(TILT), + DEFINE_AXIS(SCROLL), + DEFINE_AXIS(RELATIVE_X), + DEFINE_AXIS(RELATIVE_Y), DEFINE_AXIS(GENERIC_1), DEFINE_AXIS(GENERIC_2), DEFINE_AXIS(GENERIC_3), @@ -402,13 +405,12 @@ static const InputEventLabel LEDS[] = { { nullptr, 0 } }; -static const InputEventLabel FLAGS[] = { - DEFINE_FLAG(VIRTUAL), - DEFINE_FLAG(FUNCTION), - DEFINE_FLAG(GESTURE), +static const InputEventLabel FLAGS[] = {DEFINE_FLAG(VIRTUAL), + DEFINE_FLAG(FUNCTION), + DEFINE_FLAG(GESTURE), + DEFINE_FLAG(WAKE), - { nullptr, 0 } -}; + {nullptr, 0}}; static int lookupValueByLabel(const char* literal, const InputEventLabel *list) { while (list->literal) { diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h index 63606e5911..7ca9031f77 100644 --- a/include/input/InputTransport.h +++ b/include/input/InputTransport.h @@ -31,13 +31,17 @@ #include <string> +#include <android-base/chrono_utils.h> + #include <binder/IBinder.h> #include <input/Input.h> +#include <utils/BitSet.h> #include <utils/Errors.h> -#include <utils/Timers.h> #include <utils/RefBase.h> +#include <utils/Timers.h> #include <utils/Vector.h> -#include <utils/BitSet.h> + +#include <android-base/unique_fd.h> namespace android { class Parcel; @@ -56,14 +60,15 @@ class Parcel; * in StructLayout_test should be made. */ struct InputMessage { - enum { - TYPE_KEY = 1, - TYPE_MOTION = 2, - TYPE_FINISHED = 3, + enum class Type : uint32_t { + KEY, + MOTION, + FINISHED, + FOCUS, }; struct Header { - uint32_t type; + Type type; // 4 bytes // We don't need this field in order to align the body below but we // leave it here because InputMessage::size() and other functions // compute the size of this structure as sizeof(Header) + sizeof(Body). @@ -71,14 +76,18 @@ struct InputMessage { } header; // Body *must* be 8 byte aligned. + // For keys and motions, rely on the fact that std::array takes up exactly as much space + // as the underlying data. This is not guaranteed by C++, but it simplifies the conversions. + static_assert(sizeof(std::array<uint8_t, 32>) == 32); union Body { struct Key { uint32_t seq; - uint32_t empty1; + int32_t eventId; nsecs_t eventTime __attribute__((aligned(8))); int32_t deviceId; int32_t source; int32_t displayId; + std::array<uint8_t, 32> hmac; int32_t action; int32_t flags; int32_t keyCode; @@ -88,38 +97,46 @@ struct InputMessage { uint32_t empty2; nsecs_t downTime __attribute__((aligned(8))); - inline size_t size() const { - return sizeof(Key); - } + inline size_t size() const { return sizeof(Key); } } key; struct Motion { uint32_t seq; - uint32_t empty1; + int32_t eventId; nsecs_t eventTime __attribute__((aligned(8))); int32_t deviceId; int32_t source; int32_t displayId; + std::array<uint8_t, 32> hmac; int32_t action; int32_t actionButton; int32_t flags; int32_t metaState; int32_t buttonState; MotionClassification classification; // base type: uint8_t - uint8_t empty2[3]; + uint8_t empty2[3]; // 3 bytes to fill gap created by classification int32_t edgeFlags; nsecs_t downTime __attribute__((aligned(8))); + float xScale; + float yScale; float xOffset; float yOffset; float xPrecision; float yPrecision; + float xCursorPosition; + float yCursorPosition; uint32_t pointerCount; uint32_t empty3; - // Note that PointerCoords requires 8 byte alignment. + /** + * The "pointers" field must be the last field of the struct InputMessage. + * When we send the struct InputMessage across the socket, we are not + * writing the entire "pointers" array, but only the pointerCount portion + * of it as an optimization. Adding a field after "pointers" would break this. + */ struct Pointer { PointerProperties properties; PointerCoords coords; - } pointers[MAX_POINTERS]; + } pointers[MAX_POINTERS] __attribute__((aligned(8))); int32_t getActionId() const { uint32_t index = (action & AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) @@ -135,12 +152,21 @@ struct InputMessage { struct Finished { uint32_t seq; - bool handled; + uint32_t handled; // actually a bool, but we must maintain 8-byte alignment - inline size_t size() const { - return sizeof(Finished); - } + inline size_t size() const { return sizeof(Finished); } } finished; + + struct Focus { + uint32_t seq; + int32_t eventId; + uint32_t empty1; + // The following two fields take up 4 bytes total + uint16_t hasFocus; // actually a bool + uint16_t inTouchMode; // actually a bool, but we must maintain 8-byte alignment + + inline size_t size() const { return sizeof(Focus); } + } focus; } __attribute__((aligned(8))) body; bool isValid(size_t actualSize) const; @@ -161,60 +187,73 @@ protected: virtual ~InputChannel(); public: - InputChannel() = default; - InputChannel(const std::string& name, int fd); + static sp<InputChannel> create(const std::string& name, android::base::unique_fd fd, + sp<IBinder> token); - /* Creates a pair of input channels. + /** + * Create a pair of input channels. + * The two returned input channels are equivalent, and are labeled as "server" and "client" + * for convenience. The two input channels share the same token. * - * Returns OK on success. + * Return OK on success. */ static status_t openInputChannelPair(const std::string& name, sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel); inline std::string getName() const { return mName; } - inline int getFd() const { return mFd; } + inline int getFd() const { return mFd.get(); } - /* Sends a message to the other endpoint. + /* Send a message to the other endpoint. * * If the channel is full then the message is guaranteed not to have been sent at all. * Try again after the consumer has sent a finished signal indicating that it has * consumed some of the pending messages from the channel. * - * Returns OK on success. - * Returns WOULD_BLOCK if the channel is full. - * Returns DEAD_OBJECT if the channel's peer has been closed. + * Return OK on success. + * Return WOULD_BLOCK if the channel is full. + * Return DEAD_OBJECT if the channel's peer has been closed. * Other errors probably indicate that the channel is broken. */ status_t sendMessage(const InputMessage* msg); - /* Receives a message sent by the other endpoint. + /* Receive a message sent by the other endpoint. * * If there is no message present, try again after poll() indicates that the fd * is readable. * - * Returns OK on success. - * Returns WOULD_BLOCK if there is no message present. - * Returns DEAD_OBJECT if the channel's peer has been closed. + * Return OK on success. + * Return WOULD_BLOCK if there is no message present. + * Return DEAD_OBJECT if the channel's peer has been closed. * Other errors probably indicate that the channel is broken. */ status_t receiveMessage(InputMessage* msg); - /* Returns a new object that has a duplicate of this channel's fd. */ + /* Return a new object that has a duplicate of this channel's fd. */ sp<InputChannel> dup() const; status_t write(Parcel& out) const; - status_t read(const Parcel& from); + static sp<InputChannel> read(const Parcel& from); - sp<IBinder> getToken() const; - void setToken(const sp<IBinder>& token); + /** + * The connection token is used to identify the input connection, i.e. + * the pair of input channels that were created simultaneously. Input channels + * are always created in pairs, and the token can be used to find the server-side + * input channel from the client-side input channel, and vice versa. + * + * Do not use connection token to check equality of a specific input channel object + * to another, because two different (client and server) input channels will share the + * same connection token. + * + * Return the token that identifies this connection. + */ + sp<IBinder> getConnectionToken() const; private: - void setFd(int fd); - + InputChannel(const std::string& name, android::base::unique_fd fd, sp<IBinder> token); std::string mName; - int mFd = -1; + android::base::unique_fd mFd; - sp<IBinder> mToken = nullptr; + sp<IBinder> mToken; }; /* @@ -239,19 +278,10 @@ public: * Returns BAD_VALUE if seq is 0. * Other errors probably indicate that the channel is broken. */ - status_t publishKeyEvent( - uint32_t seq, - int32_t deviceId, - int32_t source, - int32_t displayId, - int32_t action, - int32_t flags, - int32_t keyCode, - int32_t scanCode, - int32_t metaState, - int32_t repeatCount, - nsecs_t downTime, - nsecs_t eventTime); + status_t publishKeyEvent(uint32_t seq, int32_t eventId, int32_t deviceId, int32_t source, + int32_t displayId, std::array<uint8_t, 32> hmac, int32_t action, + int32_t flags, int32_t keyCode, int32_t scanCode, int32_t metaState, + int32_t repeatCount, nsecs_t downTime, nsecs_t eventTime); /* Publishes a motion event to the input channel. * @@ -261,27 +291,25 @@ public: * Returns BAD_VALUE if seq is 0 or if pointerCount is less than 1 or greater than MAX_POINTERS. * Other errors probably indicate that the channel is broken. */ - status_t publishMotionEvent( - uint32_t seq, - int32_t deviceId, - int32_t source, - int32_t displayId, - int32_t action, - int32_t actionButton, - int32_t flags, - int32_t edgeFlags, - int32_t metaState, - int32_t buttonState, - MotionClassification classification, - float xOffset, - float yOffset, - float xPrecision, - float yPrecision, - nsecs_t downTime, - nsecs_t eventTime, - uint32_t pointerCount, - const PointerProperties* pointerProperties, - const PointerCoords* pointerCoords); + status_t publishMotionEvent(uint32_t seq, int32_t eventId, int32_t deviceId, int32_t source, + int32_t displayId, std::array<uint8_t, 32> hmac, int32_t action, + int32_t actionButton, int32_t flags, int32_t edgeFlags, + int32_t metaState, int32_t buttonState, + MotionClassification classification, float xScale, float yScale, + float xOffset, float yOffset, float xPrecision, float yPrecision, + float xCursorPosition, float yCursorPosition, nsecs_t downTime, + nsecs_t eventTime, uint32_t pointerCount, + const PointerProperties* pointerProperties, + const PointerCoords* pointerCoords); + + /* Publishes a focus event to the input channel. + * + * Returns OK on success. + * Returns WOULD_BLOCK if the channel is full. + * Returns DEAD_OBJECT if the channel's peer has been closed. + * Other errors probably indicate that the channel is broken. + */ + status_t publishFocusEvent(uint32_t seq, int32_t eventId, bool hasFocus, bool inTouchMode); /* Receives the finished signal from the consumer in reply to the original dispatch signal. * If a signal was received, returns the message sequence number, @@ -297,6 +325,7 @@ public: status_t receiveFinishedSignal(uint32_t* outSeq, bool* outHandled); private: + sp<InputChannel> mChannel; }; @@ -337,8 +366,8 @@ public: * Returns NO_MEMORY if the event could not be created. * Other errors probably indicate that the channel is broken. */ - status_t consume(InputEventFactoryInterface* factory, bool consumeBatches, - nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent); + status_t consume(InputEventFactoryInterface* factory, bool consumeBatches, nsecs_t frameTime, + uint32_t* outSeq, InputEvent** outEvent); /* Sends a finished signal to the publisher to inform it that the message * with the specified sequence number has finished being process and whether @@ -375,6 +404,13 @@ public: */ bool hasPendingBatch() const; + /* Returns the source of first pending batch if exist. + * + * Should be called after calling consume() with consumeBatches == false to determine + * whether consume() should be called again later on with consumeBatches == true. + */ + int32_t getPendingBatchSource() const; + private: // True if touch resampling is enabled. const bool mResampleTouch; @@ -509,6 +545,7 @@ private: static void rewriteMessage(TouchState& state, InputMessage& msg); static void initializeKeyEvent(KeyEvent* event, const InputMessage* msg); static void initializeMotionEvent(MotionEvent* event, const InputMessage* msg); + static void initializeFocusEvent(FocusEvent* event, const InputMessage* msg); static void addSample(MotionEvent* event, const InputMessage* msg); static bool canAddSample(const Batch& batch, const InputMessage* msg); static ssize_t findSampleNoLaterThan(const Batch& batch, nsecs_t time); diff --git a/include/input/InputWindow.h b/include/input/InputWindow.h index 916af699e0..2dac5b62a7 100644 --- a/include/input/InputWindow.h +++ b/include/input/InputWindow.h @@ -63,52 +63,53 @@ struct InputWindowInfo { FLAG_DISMISS_KEYGUARD = 0x00400000, FLAG_SPLIT_TOUCH = 0x00800000, FLAG_SLIPPERY = 0x20000000, - FLAG_NEEDS_MENU_KEY = 0x40000000, }; // Window types from WindowManager.LayoutParams enum { FIRST_APPLICATION_WINDOW = 1, - TYPE_BASE_APPLICATION = 1, - TYPE_APPLICATION = 2, + TYPE_BASE_APPLICATION = 1, + TYPE_APPLICATION = 2, TYPE_APPLICATION_STARTING = 3, LAST_APPLICATION_WINDOW = 99, - FIRST_SUB_WINDOW = 1000, - TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW, - TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW+1, - TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2, - TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3, - TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW+4, - LAST_SUB_WINDOW = 1999, - FIRST_SYSTEM_WINDOW = 2000, - TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW, - TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW+1, - TYPE_PHONE = FIRST_SYSTEM_WINDOW+2, - TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW+3, - TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW+4, - TYPE_TOAST = FIRST_SYSTEM_WINDOW+5, - TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+6, - TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW+7, - TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW+8, - TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW+9, - TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW+10, - TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW+11, - TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12, - TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW+13, - TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW+14, - TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15, - TYPE_DRAG = FIRST_SYSTEM_WINDOW+16, - TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+17, - TYPE_POINTER = FIRST_SYSTEM_WINDOW+18, - TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW+19, - TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20, - TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21, - TYPE_INPUT_CONSUMER = FIRST_SYSTEM_WINDOW+22, - TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW+24, - TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW+27, - TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW+32, - TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW+34, - LAST_SYSTEM_WINDOW = 2999, + FIRST_SUB_WINDOW = 1000, + TYPE_APPLICATION_PANEL = FIRST_SUB_WINDOW, + TYPE_APPLICATION_MEDIA = FIRST_SUB_WINDOW + 1, + TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW + 2, + TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW + 3, + TYPE_APPLICATION_MEDIA_OVERLAY = FIRST_SUB_WINDOW + 4, + LAST_SUB_WINDOW = 1999, + FIRST_SYSTEM_WINDOW = 2000, + TYPE_STATUS_BAR = FIRST_SYSTEM_WINDOW, + TYPE_SEARCH_BAR = FIRST_SYSTEM_WINDOW + 1, + TYPE_PHONE = FIRST_SYSTEM_WINDOW + 2, + TYPE_SYSTEM_ALERT = FIRST_SYSTEM_WINDOW + 3, + TYPE_KEYGUARD = FIRST_SYSTEM_WINDOW + 4, + TYPE_TOAST = FIRST_SYSTEM_WINDOW + 5, + TYPE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW + 6, + TYPE_PRIORITY_PHONE = FIRST_SYSTEM_WINDOW + 7, + TYPE_SYSTEM_DIALOG = FIRST_SYSTEM_WINDOW + 8, + TYPE_KEYGUARD_DIALOG = FIRST_SYSTEM_WINDOW + 9, + TYPE_SYSTEM_ERROR = FIRST_SYSTEM_WINDOW + 10, + TYPE_INPUT_METHOD = FIRST_SYSTEM_WINDOW + 11, + TYPE_INPUT_METHOD_DIALOG = FIRST_SYSTEM_WINDOW + 12, + TYPE_WALLPAPER = FIRST_SYSTEM_WINDOW + 13, + TYPE_STATUS_BAR_PANEL = FIRST_SYSTEM_WINDOW + 14, + TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW + 15, + TYPE_DRAG = FIRST_SYSTEM_WINDOW + 16, + TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW + 17, + TYPE_POINTER = FIRST_SYSTEM_WINDOW + 18, + TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW + 19, + TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW + 20, + TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW + 21, + TYPE_INPUT_CONSUMER = FIRST_SYSTEM_WINDOW + 22, + TYPE_NAVIGATION_BAR_PANEL = FIRST_SYSTEM_WINDOW + 24, + TYPE_MAGNIFICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 27, + TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW + 32, + TYPE_DOCK_DIVIDER = FIRST_SYSTEM_WINDOW + 34, + TYPE_NOTIFICATION_SHADE = FIRST_SYSTEM_WINDOW + 40, + TYPE_TRUSTED_APPLICATION_OVERLAY = FIRST_SYSTEM_WINDOW + 42, + LAST_SYSTEM_WINDOW = 2999, }; enum { @@ -120,17 +121,21 @@ struct InputWindowInfo { /* These values are filled in by the WM and passed through SurfaceFlinger * unless specified otherwise. */ + // This value should NOT be used to uniquely identify the window. There may be different + // input windows that have the same token. sp<IBinder> token; + // This uniquely identifies the input window. + int32_t id = -1; std::string name; - int32_t layoutParamsFlags; - int32_t layoutParamsType; - nsecs_t dispatchingTimeout; + int32_t layoutParamsFlags = 0; + int32_t layoutParamsType = 0; + nsecs_t dispatchingTimeout = -1; /* These values are filled in by SurfaceFlinger. */ - int32_t frameLeft; - int32_t frameTop; - int32_t frameRight; - int32_t frameBottom; + int32_t frameLeft = -1; + int32_t frameTop = -1; + int32_t frameRight = -1; + int32_t frameBottom = -1; /* * SurfaceFlinger consumes this value to shrink the computed frame. This is @@ -142,7 +147,7 @@ struct InputWindowInfo { // A global scaling factor for all windows. Unlike windowScaleX/Y this results // in scaling of the TOUCH_MAJOR/TOUCH_MINOR axis. - float globalScaleFactor; + float globalScaleFactor = 1.0f; // Scaling factors applied to individual windows. float windowXScale = 1.0f; @@ -153,19 +158,18 @@ struct InputWindowInfo { * to absolute coordinates by SurfaceFlinger once the frame is computed. */ Region touchableRegion; - bool visible; - bool canReceiveKeys; - bool hasFocus; - bool hasWallpaper; - bool paused; - int32_t layer; - int32_t ownerPid; - int32_t ownerUid; - int32_t inputFeatures; - int32_t displayId; + bool visible = false; + bool canReceiveKeys = false; + bool hasFocus = false; + bool hasWallpaper = false; + bool paused = false; + int32_t ownerPid = -1; + int32_t ownerUid = -1; + int32_t inputFeatures = 0; + int32_t displayId = ADISPLAY_ID_NONE; int32_t portalToDisplayId = ADISPLAY_ID_NONE; InputApplicationInfo applicationInfo; - bool replaceTouchableRegionWithCrop; + bool replaceTouchableRegionWithCrop = false; wp<IBinder> touchableRegionCropHandle; void addTouchableRegion(const Rect& region); @@ -204,18 +208,25 @@ public: sp<IBinder> getToken() const; + int32_t getId() const { return mInfo.id; } + sp<IBinder> getApplicationToken() { return mInfo.applicationInfo.token; } inline std::string getName() const { - return mInfo.token ? mInfo.name : "<invalid>"; + return !mInfo.name.empty() ? mInfo.name : "<invalid>"; } inline nsecs_t getDispatchingTimeout(nsecs_t defaultValue) const { return mInfo.token ? mInfo.dispatchingTimeout : defaultValue; } + inline std::chrono::nanoseconds getDispatchingTimeout( + std::chrono::nanoseconds defaultValue) const { + return mInfo.token ? std::chrono::nanoseconds(mInfo.dispatchingTimeout) : defaultValue; + } + /** * Requests that the state of this object be updated to reflect * the most current available information about the application. diff --git a/include/input/LatencyStatistics.h b/include/input/LatencyStatistics.h new file mode 100644 index 0000000000..bd86266901 --- /dev/null +++ b/include/input/LatencyStatistics.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2019 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_INPUT_STATISTICS_H +#define _UI_INPUT_STATISTICS_H + +#include <android-base/chrono_utils.h> + +#include <stddef.h> + +namespace android { + +class LatencyStatistics { +private: + /* Minimum sample recorded */ + float mMin; + /* Maximum sample recorded */ + float mMax; + /* Sum of all samples recorded */ + float mSum; + /* Sum of all the squares of samples recorded */ + float mSum2; + /* Count of all samples recorded */ + size_t mCount; + /* The last time statistics were reported */ + std::chrono::steady_clock::time_point mLastReportTime; + /* Statistics Report Frequency */ + const std::chrono::seconds mReportPeriod; + +public: + LatencyStatistics(std::chrono::seconds period); + + void addValue(float); + void reset(); + bool shouldReport(); + + float getMean(); + float getMin(); + float getMax(); + float getStDev(); + size_t getCount(); +}; + +} // namespace android + +#endif // _UI_INPUT_STATISTICS_H diff --git a/include/input/TouchVideoFrame.h b/include/input/TouchVideoFrame.h index b49c623204..4fa2f86dc1 100644 --- a/include/input/TouchVideoFrame.h +++ b/include/input/TouchVideoFrame.h @@ -19,7 +19,6 @@ #include <stdint.h> #include <sys/time.h> -#include <ui/DisplayInfo.h> #include <vector> namespace android { diff --git a/include/powermanager/PowerManager.h b/include/powermanager/PowerManager.h index 3268b45716..9bac242a12 100644 --- a/include/powermanager/PowerManager.h +++ b/include/powermanager/PowerManager.h @@ -33,6 +33,17 @@ enum { USER_ACTIVITY_EVENT_LAST = USER_ACTIVITY_EVENT_ACCESSIBILITY, // Last valid event code. }; +/** Keep in sync with android.os.temprature and hardware/interfaces/thermal/2.0/types.hal */ +enum class ThermalStatus : uint32_t { + THERMAL_STATUS_NONE = 0, + THERMAL_STATUS_LIGHT = 1, + THERMAL_STATUS_MODERATE = 2, + THERMAL_STATUS_SEVERE = 3, + THERMAL_STATUS_CRITICAL = 4, + THERMAL_STATUS_EMERGENCY = 5, + THERMAL_STATUS_SHUTDOWN = 6, +}; + }; // namespace android #endif // ANDROID_POWERMANAGER_H diff --git a/include/private/ui/RegionHelper.h b/include/private/ui/RegionHelper.h deleted file mode 100644 index 0ec3e9474e..0000000000 --- a/include/private/ui/RegionHelper.h +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_UI_PRIVATE_REGION_HELPER_H -#define ANDROID_UI_PRIVATE_REGION_HELPER_H - -#include <limits> -#include <stdint.h> -#include <sys/types.h> - -#include <limits> - -namespace android { -// ---------------------------------------------------------------------------- - -template<typename RECT> -class region_operator -{ -public: - typedef typename RECT::value_type TYPE; - static const TYPE max_value = std::numeric_limits<TYPE>::max(); - - /* - * Common boolean operations: - * value is computed as 0b101 op 0b110 - * other boolean operation are possible, simply compute - * their corresponding value with the above formulae and use - * it when instantiating a region_operator. - */ - static const uint32_t LHS = 0x5; // 0b101 - static const uint32_t RHS = 0x6; // 0b110 - enum { - op_nand = LHS & ~RHS, - op_and = LHS & RHS, - op_or = LHS | RHS, - op_xor = LHS ^ RHS - }; - - struct region { - RECT const* rects; - size_t count; - TYPE dx; - TYPE dy; - inline region(const region& rhs) - : rects(rhs.rects), count(rhs.count), dx(rhs.dx), dy(rhs.dy) { } - inline region(RECT const* _r, size_t _c) - : rects(_r), count(_c), dx(), dy() { } - inline region(RECT const* _r, size_t _c, TYPE _dx, TYPE _dy) - : rects(_r), count(_c), dx(_dx), dy(_dy) { } - }; - - class region_rasterizer { - friend class region_operator; - virtual void operator()(const RECT& rect) = 0; - public: - virtual ~region_rasterizer() { } - }; - - inline region_operator(uint32_t op, const region& lhs, const region& rhs) - : op_mask(op), spanner(lhs, rhs) - { - } - - void operator()(region_rasterizer& rasterizer) { - RECT current(Rect::EMPTY_RECT); - do { - SpannerInner spannerInner(spanner.lhs, spanner.rhs); - int inside = spanner.next(current.top, current.bottom); - spannerInner.prepare(inside); - do { - int inner_inside = spannerInner.next(current.left, current.right); - if ((op_mask >> inner_inside) & 1) { - if (current.left < current.right && - current.top < current.bottom) { - rasterizer(current); - } - } - } while(!spannerInner.isDone()); - } while(!spanner.isDone()); - } - -private: - uint32_t op_mask; - - class SpannerBase - { - public: - SpannerBase() - : lhs_head(max_value), lhs_tail(max_value), - rhs_head(max_value), rhs_tail(max_value) { - } - - enum { - lhs_before_rhs = 0, - lhs_after_rhs = 1, - lhs_coincide_rhs = 2 - }; - - protected: - TYPE lhs_head; - TYPE lhs_tail; - TYPE rhs_head; - TYPE rhs_tail; - - inline int next(TYPE& head, TYPE& tail, - bool& more_lhs, bool& more_rhs) - { - int inside; - more_lhs = false; - more_rhs = false; - if (lhs_head < rhs_head) { - inside = lhs_before_rhs; - head = lhs_head; - if (lhs_tail <= rhs_head) { - tail = lhs_tail; - more_lhs = true; - } else { - lhs_head = rhs_head; - tail = rhs_head; - } - } else if (rhs_head < lhs_head) { - inside = lhs_after_rhs; - head = rhs_head; - if (rhs_tail <= lhs_head) { - tail = rhs_tail; - more_rhs = true; - } else { - rhs_head = lhs_head; - tail = lhs_head; - } - } else { - inside = lhs_coincide_rhs; - head = lhs_head; - if (lhs_tail <= rhs_tail) { - tail = rhs_head = lhs_tail; - more_lhs = true; - } - if (rhs_tail <= lhs_tail) { - tail = lhs_head = rhs_tail; - more_rhs = true; - } - } - return inside; - } - }; - - class Spanner : protected SpannerBase - { - friend class region_operator; - region lhs; - region rhs; - - public: - inline Spanner(const region& _lhs, const region& _rhs) - : lhs(_lhs), rhs(_rhs) - { - if (lhs.count) { - SpannerBase::lhs_head = lhs.rects->top + lhs.dy; - SpannerBase::lhs_tail = lhs.rects->bottom + lhs.dy; - } - if (rhs.count) { - SpannerBase::rhs_head = rhs.rects->top + rhs.dy; - SpannerBase::rhs_tail = rhs.rects->bottom + rhs.dy; - } - } - - inline bool isDone() const { - return !rhs.count && !lhs.count; - } - - inline int next(TYPE& top, TYPE& bottom) - { - bool more_lhs = false; - bool more_rhs = false; - int inside = SpannerBase::next(top, bottom, more_lhs, more_rhs); - if (more_lhs) { - advance(lhs, SpannerBase::lhs_head, SpannerBase::lhs_tail); - } - if (more_rhs) { - advance(rhs, SpannerBase::rhs_head, SpannerBase::rhs_tail); - } - return inside; - } - - private: - static inline - void advance(region& reg, TYPE& aTop, TYPE& aBottom) { - // got to next span - size_t count = reg.count; - RECT const * rects = reg.rects; - RECT const * const end = rects + count; - const int top = rects->top; - while (rects != end && rects->top == top) { - rects++; - count--; - } - if (rects != end) { - aTop = rects->top + reg.dy; - aBottom = rects->bottom + reg.dy; - } else { - aTop = max_value; - aBottom = max_value; - } - reg.rects = rects; - reg.count = count; - } - }; - - class SpannerInner : protected SpannerBase - { - region lhs; - region rhs; - - public: - inline SpannerInner(const region& _lhs, const region& _rhs) - : lhs(_lhs), rhs(_rhs) - { - } - - inline void prepare(int inside) { - if (inside == SpannerBase::lhs_before_rhs) { - if (lhs.count) { - SpannerBase::lhs_head = lhs.rects->left + lhs.dx; - SpannerBase::lhs_tail = lhs.rects->right + lhs.dx; - } - SpannerBase::rhs_head = max_value; - SpannerBase::rhs_tail = max_value; - } else if (inside == SpannerBase::lhs_after_rhs) { - SpannerBase::lhs_head = max_value; - SpannerBase::lhs_tail = max_value; - if (rhs.count) { - SpannerBase::rhs_head = rhs.rects->left + rhs.dx; - SpannerBase::rhs_tail = rhs.rects->right + rhs.dx; - } - } else { - if (lhs.count) { - SpannerBase::lhs_head = lhs.rects->left + lhs.dx; - SpannerBase::lhs_tail = lhs.rects->right + lhs.dx; - } - if (rhs.count) { - SpannerBase::rhs_head = rhs.rects->left + rhs.dx; - SpannerBase::rhs_tail = rhs.rects->right + rhs.dx; - } - } - } - - inline bool isDone() const { - return SpannerBase::lhs_head == max_value && - SpannerBase::rhs_head == max_value; - } - - inline int next(TYPE& left, TYPE& right) - { - bool more_lhs = false; - bool more_rhs = false; - int inside = SpannerBase::next(left, right, more_lhs, more_rhs); - if (more_lhs) { - advance(lhs, SpannerBase::lhs_head, SpannerBase::lhs_tail); - } - if (more_rhs) { - advance(rhs, SpannerBase::rhs_head, SpannerBase::rhs_tail); - } - return inside; - } - - private: - static inline - void advance(region& reg, TYPE& left, TYPE& right) { - if (reg.rects && reg.count) { - const int cur_span_top = reg.rects->top; - reg.rects++; - reg.count--; - if (!reg.count || reg.rects->top != cur_span_top) { - left = max_value; - right = max_value; - } else { - left = reg.rects->left + reg.dx; - right = reg.rects->right + reg.dx; - } - } - } - }; - - Spanner spanner; -}; - -// ---------------------------------------------------------------------------- -}; - -#endif /* ANDROID_UI_PRIVATE_REGION_HELPER_H */ diff --git a/include/ui b/include/ui deleted file mode 120000 index 2fb3147669..0000000000 --- a/include/ui +++ /dev/null @@ -1 +0,0 @@ -../libs/ui/include/ui
\ No newline at end of file diff --git a/include/ui/DisplayInfo.h b/include/ui/DisplayInfo.h new file mode 120000 index 0000000000..9a195eaed4 --- /dev/null +++ b/include/ui/DisplayInfo.h @@ -0,0 +1 @@ +../../libs/ui/include/ui/DisplayInfo.h
\ No newline at end of file diff --git a/include/ui/FatVector.h b/include/ui/FatVector.h new file mode 120000 index 0000000000..c2047c07e1 --- /dev/null +++ b/include/ui/FatVector.h @@ -0,0 +1 @@ +../../libs/ui/include/ui/FatVector.h
\ No newline at end of file diff --git a/include/ui/FloatRect.h b/include/ui/FloatRect.h new file mode 120000 index 0000000000..d7bd737395 --- /dev/null +++ b/include/ui/FloatRect.h @@ -0,0 +1 @@ +../../libs/ui/include/ui/FloatRect.h
\ No newline at end of file diff --git a/include/ui/PixelFormat.h b/include/ui/PixelFormat.h new file mode 120000 index 0000000000..4085433af6 --- /dev/null +++ b/include/ui/PixelFormat.h @@ -0,0 +1 @@ +../../libs/ui/include/ui/PixelFormat.h
\ No newline at end of file diff --git a/include/ui/Point.h b/include/ui/Point.h new file mode 120000 index 0000000000..443938bc51 --- /dev/null +++ b/include/ui/Point.h @@ -0,0 +1 @@ +../../libs/ui/include/ui/Point.h
\ No newline at end of file diff --git a/include/ui/PublicFormat.h b/include/ui/PublicFormat.h new file mode 120000 index 0000000000..7984c0e76a --- /dev/null +++ b/include/ui/PublicFormat.h @@ -0,0 +1 @@ +../../libs/ui/include/ui/PublicFormat.h
\ No newline at end of file diff --git a/include/ui/Rect.h b/include/ui/Rect.h new file mode 120000 index 0000000000..a99c5f28c7 --- /dev/null +++ b/include/ui/Rect.h @@ -0,0 +1 @@ +../../libs/ui/include/ui/Rect.h
\ No newline at end of file diff --git a/include/ui/Region.h b/include/ui/Region.h new file mode 120000 index 0000000000..2e46e0fe30 --- /dev/null +++ b/include/ui/Region.h @@ -0,0 +1 @@ +../../libs/ui/include/ui/Region.h
\ No newline at end of file diff --git a/include/ui/Size.h b/include/ui/Size.h new file mode 120000 index 0000000000..c0da99bffc --- /dev/null +++ b/include/ui/Size.h @@ -0,0 +1 @@ +../../libs/ui/include/ui/Size.h
\ No newline at end of file |