diff -Nru libhybris-0.1.0+git20131207+e452e83/debian/changelog libhybris-0.1.0+git20151016+6d424c9/debian/changelog --- libhybris-0.1.0+git20131207+e452e83/debian/changelog 2015-04-06 23:53:56.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/debian/changelog 2016-08-10 06:28:10.000000000 +0000 @@ -1,3 +1,327 @@ +libhybris (0.1.0+git20151016+6d424c9-0ubuntu22~vivid1) vivid; urgency=medium + + * Backport to vivid stable overlay PPA + + -- Alfonso Sanchez-Beato (email Canonical) Wed, 10 Aug 2016 08:24:48 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu22~xenial1) xenial; urgency=medium + + [ You-Sheng Yang ] + * linker: disable linker probing when unavailable + * linker: remove /system/lib prefix from lib paths + * configure: use lib64 for DEFAULT_HYBRIS_LD_LIBRARY_PATH on arm64 + * compat: build arm64 flavor when available + + -- Simon Fels Fri, 05 Aug 2016 18:47:48 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu21) yakkety; urgency=medium + + [ Alfonso Sanchez-Beato ] + * compat: media: add bool macro definition + + -- Simon Fels Wed, 13 Jul 2016 08:35:49 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu20) yakkety; urgency=medium + + [ Alfonso Sanchez-Beato ] + * hybris: common: remove hooks for signal handling + + [ Simon Fels ] + * hybris: wifi: add new API method to send driver command + + -- Simon Fels Thu, 07 Jul 2016 10:40:38 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu19) yakkety; urgency=medium + + [ Bin Li ] + * hybris: common: Add hooks to support scandir + + [ Simon Fels ] + * hybris: common: remove old and unused gb and ics linkers + * hybris: common: mm: include strlcat/strlcpy to avoid linke time issues + * hybris: common: mm: drop unneeded compile time definitions + + -- Simon Fels Wed, 29 Jun 2016 17:41:10 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu18) yakkety; urgency=medium + + [ Boleslaw Tokarski ] + * [properties] An off-by-one error in prop handling + + [ Gunnar Sletta ] + * [glesv2] Wrap glGetString() and return GL_VERSION == 2.0 + + -- Simon Fels Wed, 22 Jun 2016 13:27:17 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu17) yakkety; urgency=medium + + * Revert "Fix resolving the GLEsv2 functions at link time" + * hybris: common: fine tune dynamic linker load process + * hybris: glesv2: load symbols on demand + * hybris: glesv2: drop redefined symbols + * hybris: glesv2: really drop all unneeded symbols + * hybris: glesv2: revert back to version without using GNU indirect feature + * hybris: common: more fine tuning for runtime linker loading + * hybris: common: use correct property name for device name + * hybris: common: force SDK version 19 for cooler too + * hybris: common: add env variable to override selected SDK version + * hybris: common: use debug log statement rather than plain printf + * hybris: common: rename variable containing hooks for all devices + * hybris: glesv2: don't return anything in functions with void as return type + * hybris: common: enable linker overrides only by configure option + * debian: enable ubuntu linker overrides only for armhf + + -- Simon Fels Tue, 21 Jun 2016 11:58:45 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu16) yakkety; urgency=medium + + * No change release. + + -- Simon Fels Wed, 15 Jun 2016 17:48:02 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu15) yakkety; urgency=medium + + * hybris: mm: use recursive mutex for dlopen/.. locking + * hybris: common: add support for dynamic linker loading at runtime + + -- Simon Fels Wed, 15 Jun 2016 16:55:55 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu14) yakkety; urgency=medium + + [ Ondrej Kubik ] + * Fix Android 6.x build for Android Build System. + + [ Rex Tsai (蔡志展) ] + * Fix MediaCodecSource::Create() API change for Android 6.0.0_r1. + + [ Simon Fels ] + * hybris: introduce experimental configuration feature + * hybris: note used android version in configure summary + * hybris: common: import marshmallow linker + * hybris: common: enable building marshmellow linker + * hybris: common: make marshmellow linker building + * hybris: common: mm: drop support for libs inside zip archives + * hybris: common: mm: get rid of sys/limits.h copy + * hybris: common: mm: disable tls initialization + * hybris: common: mm: disable debuggerd connection + * hybris: common: mm: export android_* dlfcn functions for use from C + * hybris: common: add hybris prefix for our hook processing method + * hybris: common: mm: add symbol hooking functionality + * hybris: common: mm: redirect all linker logs to stdout + * hybris: common: mm: use HYBRIS_LD_DEBUG to enable debug output + * hybris: common: mm: get linker building on arm platforms + * hybris: common: build with c++ support + * hybris: common: mm: further enablement work + * hybris: common: mm: don't memset class instance + * hybris: common: mm: disable linker internal memory mgmt for small objects + * hybris: common: mm: respect hybris specific library paths only + * hybris: common: mm: replace LINKER_DEBUG with TRACE_DEBUG + * hybris: mention experimental configure option in summary + * hybris: common: add missing libs we have to link to + * hybris: common: mm: switch from fprintf to DEBUG + * hybris: common: mm: disable some more code parts we don't use + * tests: add missing pthread to LDADD for test_nfc + * hybris: common: add c'tor to initialize linker logging + * hybris: common: add ability to deliver hooks from the outside + * hybris: common: mm: add missing line ending for error messages + * hybris: common: mm: fix compliation in x86 + * hybris: common: really make hooking work + * hybris: common: make hook handler availble for C++ + * hybris: common: deliver symbol requester through our hooks too + * hybris: egl: don't create surface mapping when creation failed + * hybris: hooks: hook a few more symbols for Android 6 support + * hybris: common: switch hook prefix to _hybris_hook_ + * hybris: common: add tracing support for our hooks + * utils: update load-sym-files gdb command to python3 + * hybris: common: convert addrinfo struct correctly + * hybris: common: respect unsigned nature of size_t + * hybris: common: add tracing for sysconf hook + * hybris: common: add proper copyright header for sysconf implementation + * hybris: common: add more hooks to let string.* bionic tests pass + * hybris: common: add new keys for sysconf + * hybris: common: add a few more necessary hooks + * hybris: common: improve tracing for a few hooks + * hybris: use pthread rather than lpthread to link with pthread lib + * hybris: common: mm: drop old ARCH_FLAGS we don't need + * hybris: common: add hook for strcmp to fail on nullptr + * hybris: common: fix printf format + * hybris: common: add more necessary hooks + * debian: install load_sym_files.py gdb helper script + * debian: enable mm linker by default + * hybris: detect arm64 architecture at configuration time + * hybris: common: mm: use correct names for relocation types + * debian: package libGLESv1_CM.so + + [ Giulio Camuffo ] + * Fix resolving the GLEsv2 functions at link time + + [ Simon Fels ] + * debian: update copyright file + * debian: bump standards version to 3.9.7 + + -- Simon Fels Tue, 14 Jun 2016 09:52:43 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu13) xenial; urgency=medium + + * hybris: common: stub: don't assert but return error + + -- Simon Fels Mon, 09 May 2016 16:09:26 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu12) xenial; urgency=medium + + * debian: split out arch specific configuration flags + + -- Simon Fels Fri, 06 May 2016 09:48:53 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu11) xenial; urgency=medium + + * hybris: common: add stub linker implementation + * debian: split out common parts of the default configuration + * debian: add build support for arm64 + * hybris: add README file stating which architectures are supported + * hybris: autotools want it to be README + + -- Simon Fels Tue, 03 May 2016 17:29:41 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu10) xenial; urgency=medium + + * debian: add missing hybris/common include directory + + -- Simon Fels Thu, 21 Apr 2016 11:06:48 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu9) xenial; urgency=medium + + * hybris/compat: media: wrap android media codec source implementation + * compat: media: only build media codec source support for Android 5.x + * compat: media: introduce API version number + * compat: media: don't put Android 5.x as a requirement for MediaCodecSource + + -- Simon Fels Wed, 13 Apr 2016 11:58:56 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu8) xenial; urgency=medium + + * No change rebuild to cover a new android-headers release which + floating point ABI problems. + + -- Simon Fels Mon, 11 Apr 2016 10:51:55 +0200 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu7) xenial; urgency=medium + + [ Ugo Riboni ] + * Allow setting/clearning the camera metering region + + [ Alex Tu ] + * compat: force modules to be build for 32bit only + + [ Simon Fels ] + * debian: adjust our build depends depending which distro we build for + - With this we select now gcc 4.7 for vivid builds and take what + ever else is default on all other distributions. We need to switch + soon or later away from gcc 4.7 but before we can do that we need + to overcome the still existing ABI issues we get when we build + with something else than gcc 4.7. + + -- Simon Fels Mon, 07 Mar 2016 10:41:54 +0100 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu6) xenial; urgency=medium + + [ Simon Fels ] + * Revert "debian: drop requirement of gcc 4.7" + + [ Franz-Josef ] + * hybris: add hook for freeaddrinfo and getaddrinfo + + -- Simon Fels Fri, 05 Feb 2016 15:23:26 +0100 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu5) xenial; urgency=medium + + * debian: drop requirement of gcc 4.7 + + -- Simon Fels Tue, 26 Jan 2016 12:37:21 +0100 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu4) xenial; urgency=medium + + [ You-Sheng Yang ] + * wifi: fix hardware_legacy/wifi.h not found + * tests: fix test_audio compilation on Android 5 or above + + [ Carsten Munk ] + * Hook getlogin, __sprintf_chk, __snprintf_chk + + [ Simon Fels ] + * hybris: common: dump mutex address + * hybris: common: add ugly workaround for malit-hist-dump thread + * hybris: common: also hook prctl to workaround mali-hist-dump + * hybris: common: also log name when prctl called with PR_SET_NAME + * hybris: common: add exit workaround for mali-hist-dump thread + * hybris: common: be more precise on prctl log messages + * hybris: add configuration option to enable mali related quirks + * hybris: common: hook localtime, gmtime and friends + * debian: enable mali quirks + * hybris: common: hook missing pthread functions + * hybris: common: add further debug statements for symbol hooking + * debian: update changelog + + [ You-Sheng Yang ] + * compat: media: remove wrong BOARD_HAS_MEDIA_PLAYER_PAUSE guard + * compat: media: implement android::IMediaRecorder::resume + + [ Simon Fels ] + * debian: drop files listed twice in .install files + * debian: drop -dbg package as we generate them automatically + + [ You-Sheng Yang ] + * hooks: add pthread_mutex_timedlock + + [ Thomas Voß ] + * Hook pthread_kill such that pthread_t values of 0 do not lead to segfaults. + + [ Simon Fels ] + * debian: update changelog + * debian: correct vcs reference to point to launchpad + + [ You-Sheng Yang ] + * hook: add pthread_condattr_setclock + * hook: skip only symbol names prefixed with "pthread" or "__pthread" + + [ Mikko Harju ] + * [libhybris] Add cache for socket based property lookups. + + [ Simon Fels ] + * hybris: common: add simple macro to check for existing symbols + * debian: drop stripping of not existing package + * Revert "debian: don't package NFC stuff anymore" + * utils: fix binding wrapper macro generator script + * debian: sync changelog up with what is released + * debian: enable property cache for x86 and armhf + * debian: rules: cleanup formatting for autoconf options + + -- Simon Fels Tue, 26 Jan 2016 11:05:14 +0100 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu3) vivid; urgency=medium + + * Various fixes to allow camera access to work in the web browser + * Fix compat layer compilation when API functions are missing on + certain devices in the media player implementation. + * Add initial support for Android 5.x + + -- Simon Fels Thu, 07 Jan 2016 08:07:11 +0100 + +libhybris (0.1.0+git20151016+6d424c9-0ubuntu1) vivid; urgency=medium + + [ Ricardo Salveti de Araujo ] + * New upstream snapshot: + - Rebasing patches and removing the ones that are already available in + upstream + + [ Alex Tu ] + * Fix Build error. + + [ Simon Fels ] + * Merge with upstream and rebased chagnes + + -- Simon Fels Fri, 16 Oct 2015 09:14:11 +0200 + libhybris (0.1.0+git20131207+e452e83-0ubuntu39) vivid; urgency=medium * linker: adding dl_iterate_phdr for ARM (required by Android 5 blobs) diff -Nru libhybris-0.1.0+git20131207+e452e83/debian/control libhybris-0.1.0+git20151016+6d424c9/debian/control --- libhybris-0.1.0+git20131207+e452e83/debian/control 2015-04-06 23:53:56.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/debian/control 2016-08-10 06:28:16.000000000 +0000 @@ -5,19 +5,18 @@ autotools-dev, dh-autoreconf, android-headers (>= 4.4.2), - gcc-4.7, - g++-4.7, + gcc-4.7, g++-4.7, quilt, pkg-config, libgles2-mesa-dev, libwayland-dev -Standards-Version: 3.9.5 +Standards-Version: 3.9.7 Section: libs -Vcs-Git: git://phablet.ubuntu.com/ubuntu/libhybris.git -Vcs-Browser: http://phablet.ubuntu.com/gitweb?p=ubuntu/libhybris.git;a=summary +Vcs-Git: https://git.launchpad.net/~libhybris-maintainers/libhybris/+git/libhybris +Vcs-Browser: https://git.launchpad.net/~libhybris-maintainers/libhybris/+git/libhybris/ Package: libandroid-properties1 -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: ${shlibs:Depends}, ${misc:Depends} Description: Library to provide access to get, set and list Android properties @@ -27,7 +26,7 @@ Package: libandroid-properties-dev Section: libdevel -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libandroid-properties1 (= ${binary:Version}), ${misc:Depends} Description: Development headers files for libandroid-properties @@ -35,7 +34,7 @@ set or list the Android properties. Package: libmedia1 -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: ${shlibs:Depends}, ${misc:Depends} Replaces: libhybris (<< 0.1.0+git20130606+c5d897a-0ubuntu24) @@ -50,7 +49,7 @@ Package: libmedia-dev Section: libdevel -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libmedia1 (= ${binary:Version}), android-headers (>= 4.4.2), ${misc:Depends} @@ -64,7 +63,7 @@ glibc systems. Package: libhardware2 -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: ${shlibs:Depends}, ${misc:Depends} Replaces: libhybris (<< 0.1.0+git20130606+c5d897a-0ubuntu13) @@ -79,7 +78,7 @@ Package: libhardware-dev Section: libdevel -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libhardware2 (= ${binary:Version}), android-headers (>= 4.4.2), ${misc:Depends} @@ -94,7 +93,7 @@ glibc systems. Package: libhybris-common1 -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: ${shlibs:Depends}, ${misc:Depends} Replaces: libhybris (<< 0.1.0+git20130606+c5d897a-0ubuntu13) @@ -108,7 +107,7 @@ Package: libhybris-common-dev Section: libdevel -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libhybris-common1 (= ${binary:Version}), ${misc:Depends} Replaces: libhybris-dev (<< 0.1.0+git20130606+c5d897a-0ubuntu13) @@ -122,7 +121,7 @@ glibc systems. Package: libhybris -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libandroid-properties1 (= ${binary:Version}), libhardware2, libmedia1, @@ -134,7 +133,7 @@ Package: libhybris-dev Section: libdevel -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libhybris (= ${binary:Version}), android-headers (>= 4.4.2), libandroid-properties-dev (= ${binary:Version}), @@ -152,7 +151,7 @@ Package: libhybris-utils Section: utils -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libhybris (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends} @@ -164,7 +163,7 @@ Package: libhybris-test Section: devel -Architecture: armhf i386 amd64 +Architecture: armhf arm64 i386 amd64 Depends: libhybris (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends} diff -Nru libhybris-0.1.0+git20131207+e452e83/debian/control.in libhybris-0.1.0+git20151016+6d424c9/debian/control.in --- libhybris-0.1.0+git20131207+e452e83/debian/control.in 1970-01-01 00:00:00.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/debian/control.in 2016-08-05 16:46:15.000000000 +0000 @@ -0,0 +1,175 @@ +Source: libhybris +Priority: extra +Maintainer: Ubuntu Developers +Build-Depends: debhelper (>= 9.0.0), + autotools-dev, + dh-autoreconf, + android-headers (>= 4.4.2), + @EXTRA_BUILD_DEPENDS@ + quilt, + pkg-config, + libgles2-mesa-dev, + libwayland-dev +Standards-Version: 3.9.7 +Section: libs +Vcs-Git: https://git.launchpad.net/~libhybris-maintainers/libhybris/+git/libhybris +Vcs-Browser: https://git.launchpad.net/~libhybris-maintainers/libhybris/+git/libhybris/ + +Package: libandroid-properties1 +Architecture: armhf arm64 i386 amd64 +Depends: ${shlibs:Depends}, + ${misc:Depends} +Description: Library to provide access to get, set and list Android properties + Contains a library that provides access to get, set and list Android + properties, which can be used by any Ubuntu app that needs to probe + for properties (gps, modem, device specifics). + +Package: libandroid-properties-dev +Section: libdevel +Architecture: armhf arm64 i386 amd64 +Depends: libandroid-properties1 (= ${binary:Version}), + ${misc:Depends} +Description: Development headers files for libandroid-properties + Contains the development files for use in applications that wants to get, + set or list the Android properties. + +Package: libmedia1 +Architecture: armhf arm64 i386 amd64 +Depends: ${shlibs:Depends}, + ${misc:Depends} +Replaces: libhybris (<< 0.1.0+git20130606+c5d897a-0ubuntu24) +Breaks: libhybris (<< 0.1.0+git20130606+c5d897a-0ubuntu24) +Description: Library to provide access to the Android Media HAL + Contains a library that provides access to the Android Media HAL, + which abstract the access to the Android libstagefright based + decoders. + . + Hybris is a solution that allows the use of bionic-based HW adaptations in + glibc systems. + +Package: libmedia-dev +Section: libdevel +Architecture: armhf arm64 i386 amd64 +Depends: libmedia1 (= ${binary:Version}), + android-headers (>= 4.4.2), + ${misc:Depends} +Replaces: libhybris-dev (<< 0.1.0+git20130606+c5d897a-0ubuntu24) +Breaks: libhybris-dev (<< 0.1.0+git20130606+c5d897a-0ubuntu24) +Description: Development files for libmedia + Contains the development files for the Android Media HAL, which + abstract the access to the Android libstagefright based decoders. + . + Hybris is a solution that allows the use of bionic-based HW adaptations in + glibc systems. + +Package: libhardware2 +Architecture: armhf arm64 i386 amd64 +Depends: ${shlibs:Depends}, + ${misc:Depends} +Replaces: libhybris (<< 0.1.0+git20130606+c5d897a-0ubuntu13) +Breaks: libhybris (<< 0.1.0+git20130606+c5d897a-0ubuntu13) +Description: Library to provide access to the Android libhardware HAL + Contains a library that provides access to the Android libhardware HAL, + which can be used to access a wide range of other HALs, such as audio, + power, gralloc, etc. + . + Hybris is a solution that allows the use of bionic-based HW adaptations in + glibc systems. + +Package: libhardware-dev +Section: libdevel +Architecture: armhf arm64 i386 amd64 +Depends: libhardware2 (= ${binary:Version}), + android-headers (>= 4.4.2), + ${misc:Depends} +Replaces: libhybris-dev (<< 0.1.0+git20130606+c5d897a-0ubuntu13) +Breaks: libhybris-dev (<< 0.1.0+git20130606+c5d897a-0ubuntu13) +Description: Development files for libhardware + Contains the development files for the Android libhardware HAL, which can + be used to access a wide range of other HALs, such as audio, power, + gralloc, etc. + . + Hybris is a solution that allows the use of bionic-based HW adaptations in + glibc systems. + +Package: libhybris-common1 +Architecture: armhf arm64 i386 amd64 +Depends: ${shlibs:Depends}, + ${misc:Depends} +Replaces: libhybris (<< 0.1.0+git20130606+c5d897a-0ubuntu13) +Breaks: libhybris (<< 0.1.0+git20130606+c5d897a-0ubuntu13) +Description: Common library that contains the Android linker and custom hooks + Contains a common library that contains the Android linker, used to + dynamically load and use symbols from Android based libraries. + . + Hybris is a solution that allows the use of bionic-based HW adaptations in + glibc systems. + +Package: libhybris-common-dev +Section: libdevel +Architecture: armhf arm64 i386 amd64 +Depends: libhybris-common1 (= ${binary:Version}), + ${misc:Depends} +Replaces: libhybris-dev (<< 0.1.0+git20130606+c5d897a-0ubuntu13) +Breaks: libhybris-dev (<< 0.1.0+git20130606+c5d897a-0ubuntu13) +Description: Development files for libhybris-common + Contains the development files for the common library that contains the + Android linker, used to dynamically load and use symbols from Android + based libraries. + . + Hybris is a solution that allows the use of bionic-based HW adaptations in + glibc systems. + +Package: libhybris +Architecture: armhf arm64 i386 amd64 +Depends: libandroid-properties1 (= ${binary:Version}), + libhardware2, + libmedia1, + ${shlibs:Depends}, + ${misc:Depends} +Description: Allows to run bionic-based HW adaptations in glibc systems - libs + Hybris is a solution that allows the use of bionic-based HW adaptations in + glibc systems. + +Package: libhybris-dev +Section: libdevel +Architecture: armhf arm64 i386 amd64 +Depends: libhybris (= ${binary:Version}), + android-headers (>= 4.4.2), + libandroid-properties-dev (= ${binary:Version}), + libhardware-dev (= ${binary:Version}), + libmedia-dev (= ${binary:Version}), + libhybris-common-dev (= ${binary:Version}), + ${misc:Depends}, + libgles2-mesa-dev, +Description: Development headers and libraries for libhybris + Contains the header files for use in developing applications that use + the libhybris library. + . + Hybris is a solution that allows the use of bionic-based HW adaptations in + glibc systems. + +Package: libhybris-utils +Section: utils +Architecture: armhf arm64 i386 amd64 +Depends: libhybris (= ${binary:Version}), + ${shlibs:Depends}, + ${misc:Depends} +Description: Utilities to help working with the Android HW abstraction layer + Contains utilities used to help working with Android HW abstraction layer. + . + Hybris is a solution that allows the use of bionic-based HW adaptations in + glibc systems. + +Package: libhybris-test +Section: devel +Architecture: armhf arm64 i386 amd64 +Depends: libhybris (= ${binary:Version}), + ${shlibs:Depends}, + ${misc:Depends} +Description: Allows to run bionic-based HW adaptations in glibc systems - tests + Contains the test applications used to validate libhybris (needs Android + libraries or container). + . + Hybris is a solution that allows the use of bionic-based HW adaptations in + glibc systems. diff -Nru libhybris-0.1.0+git20131207+e452e83/debian/copyright libhybris-0.1.0+git20151016+6d424c9/debian/copyright --- libhybris-0.1.0+git20131207+e452e83/debian/copyright 2015-04-06 23:53:56.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/debian/copyright 2016-08-05 16:46:15.000000000 +0000 @@ -2,106 +2,361 @@ Upstream-Name: libhybris Source: https://github.com/libhybris/libhybris -Files: compat/surface_flinger/* hybris/include/hybris/internal/surface_flinger_compatibility_layer_internal.h hybris/include/hybris/surface_flinger/surface_flinger_compatibility_layer.h hybris/sf/sf.c hybris/tests/test_sf.c -Copyright: 2013 Canonical Ltd -License: Apache 2.0 - -Files: compat/ui/* hybris/egl/eglhybris.h hybris/hardware/hardware.c hybris/include/hybris/ui/ui_compatibility_layer.h hybris/ui/ui.c hybris/tests/test_lights.c hybris/tests/test_sensors.c hybris/tests/test_ui.c -Copyright: 2012-2013 Simon Busch -License: Apache 2.0 - -Files: hybris/include/hybris/internal/binding.h -Copyright: 2013 Simon Busch - 2012 Canonical Ltd -License: Apache 2.0 +Files: * +Copyright: 2012-2014, 2016, Canonical Ltd +License: Apache-2.0 + +Files: compat/media/SimplePlayer.cpp + compat/media/SimplePlayer.h + compat/media/codec.cpp +Copyright: 2005-2008, 2010, 2012-2015, The Android Open Source Project +License: Apache-2.0 + +Files: compat/media/media_recorder.cpp + compat/media/media_recorder.h +Copyright: 2013, 2014, Canonical Ltd + 2008, The Android Open Source Project +License: Apache-2.0 + +Files: compat/ui/* +Copyright: 2012, 2013, Simon Busch +License: Apache-2.0 -Files: hybris/egl/platforms/common/native_handle.c -Copyright: 2007 The Android Open Source Project -License: Apache 2.0 +Files: hybris/common/* +Copyright: 2008-2015, The Android Open Source Project +License: BSD-2-clause + +Files: hybris/common/dlfcn.c +Copyright: 2013, Intel Corporation +License: Apache-2.0 + +Files: hybris/common/gingerbread/NOTICE + hybris/common/gingerbread/dlfcn.c +Copyright: 2005-2008, 2010, 2012-2015, The Android Open Source Project +License: Apache-2.0 Files: hybris/common/hooks.c -Copyright: 2012 Carsten Munk - 2012 Canonical Ltd -License: Apache 2.0 +Copyright: 2013, Christophe Chapuis + 2012, Carsten Munk + 2012, Canonical Ltd +License: Apache-2.0 + +Files: hybris/common/hooks_shm.c +Copyright: 2013, Christophe Chapuis + 2012, Carsten Munk +License: Apache-2.0 + +Files: hybris/common/hooks_shm.h +Copyright: 2012, Carsten Munk +License: Apache-2.0 + +Files: hybris/common/ics/dlfcn.c +Copyright: 2005-2008, 2010, 2012-2015, The Android Open Source Project +License: Apache-2.0 + +Files: hybris/common/jb/dlfcn.c +Copyright: 2005-2008, 2010, 2012-2015, The Android Open Source Project +License: Apache-2.0 + +Files: hybris/common/logging.c + hybris/common/logging.h +Copyright: 2013, Thomas Perl +License: Apache-2.0 + +Files: hybris/common/mm/* +Copyright: 2005-2008, 2010, 2012-2015, The Android Open Source Project +License: Apache-2.0 -Files: hybris/tests/test_gps.c -Copyright: 2013 Jolla Mobile -License: Apache 2.0 +Files: hybris/common/mm/bionic/* +Copyright: 2008-2015, The Android Open Source Project +License: BSD-2-clause -Files: hybris/common/logging.* -Copyright: 2013 Thomas Perl -License: Apache 2.0 - -Files: hybris/egl/platforms/fbdev/fbdev_window.* -Copyright: 2013 libhybris -License: Apache 2.0 +Files: hybris/common/mm/bionic/libc/include/android/dlext.h +Copyright: 2005-2008, 2010, 2012-2015, The Android Open Source Project +License: Apache-2.0 + +Files: hybris/common/mm/bionic/libc/private/* +Copyright: 2005-2008, 2010, 2012-2015, The Android Open Source Project +License: Apache-2.0 + +Files: hybris/common/mm/bionic/libc/private/ThreadLocalBuffer.h + hybris/common/mm/bionic/libc/private/__get_tls.h + hybris/common/mm/bionic/libc/private/bionic_asm.h + hybris/common/mm/bionic/libc/private/bionic_auxv.h + hybris/common/mm/bionic/libc/private/bionic_futex.h + hybris/common/mm/bionic/libc/private/bionic_lock.h + hybris/common/mm/bionic/libc/private/bionic_mbstate.h + hybris/common/mm/bionic/libc/private/bionic_ssp.h + hybris/common/mm/bionic/libc/private/bionic_time.h + hybris/common/mm/bionic/libc/private/bionic_time_conversions.h + hybris/common/mm/bionic/libc/private/bionic_tls.h + hybris/common/mm/bionic/libc/private/libc_events.h + hybris/common/mm/bionic/libc/private/libc_logging.h +Copyright: 2008-2015, The Android Open Source Project +License: BSD-2-clause -Files: hybris/egl/platforms/wayland/eglplatform_wayland.cpp hybris/egl/platforms/wayland/wayland_window.h hybris/egl/platforms/wayland/wayland_window.cpp -Copyright: 2013 Jolla Ltd -License: LGPL-2.1 +Files: hybris/common/mm/hybris_compat.cpp + hybris/common/mm/hybris_compat.h + hybris/common/mm/linker.cpp + hybris/common/mm/linker.h + hybris/common/mm/linker_debug.h + hybris/common/mm/linker_phdr.cpp + hybris/common/mm/linker_phdr.h + hybris/common/mm/rt.cpp +Copyright: 2008-2015, The Android Open Source Project +License: BSD-2-clause -Files: hybris/common/properties.* hybris/egl/egl.c hybris/glesv2/glesv2.c hybris/tests/test_glesv2.c hybris/tests/test_egl.c -Copyright: 2012 Carsten Munk -License: Apache 2.0 +Files: hybris/common/strlcat.c +Copyright: 1998, Todd C. Miller +License: ISC -Files: hybris/include/CL/* hybris/include/KHR/* hybris/include/EGL/* hybris/include/VG/* hybris/include/GL/glxext.h hybris/include/GL/glext.h hybris/include/GL/wglext.h -Copyright: 2007-2012 The Khronos Group Inc -License: X11/MIT +Files: hybris/common/strlcpy.c +Copyright: 1998, Todd C. Miller +License: ISC -Files: hybris/include/GL/glx.h hybris/include/GL/glx_mangle.h hybris/include/GL/osmesa.h -Copyright: 1999-2006 Brian Paul -License: X11/MIT +Files: hybris/common/stub/* +Copyright: 2012-2014, 2016, Canonical Ltd +License: Apache-2.0 + +Files: hybris/common/sysconf.c +Copyright: 2013, Adrian Negreanu +License: Apache-2.0 + +Files: hybris/egl/* +Copyright: 2012-2014, Jolla Ltd +License: Apache-2.0 + +Files: hybris/egl/egl.c +Copyright: 2012, Carsten Munk +License: Apache-2.0 + +Files: hybris/egl/eglhybris.h +Copyright: 2012, 2013, Simon Busch +License: Apache-2.0 + +Files: hybris/egl/platforms/* +Copyright: 2013, libhybris +License: Apache-2.0 + +Files: hybris/egl/platforms/common/* +Copyright: 2012, Collabora, Ltd +License: MIT2 + Permission to use, copy, modify, distribute, and sell this software and + its documentation for any purpose is hereby granted without fee, provided + that the above copyright notice appear in all copies and that both that + copyright notice and this permission notice appear in supporting + documentation, and that the name of the copyright holders not be used in + advertising or publicity pertaining to distribution of the software + without specific, written prior permission. The copyright holders make + no representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied warranty. + . + THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER + RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF + CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +Files: hybris/egl/platforms/common/hybris_nativebufferext.h +Copyright: 2013, Jolla Ltd + 2011, The Android Open Source Project +License: Apache-2.0 + +Files: hybris/egl/platforms/common/native_handle.c +Copyright: 2005-2008, 2010, 2012-2015, The Android Open Source Project +License: Apache-2.0 + +Files: hybris/egl/platforms/common/server_wlegl_handle.h + hybris/egl/platforms/common/windowbuffer.cpp + hybris/egl/platforms/common/windowbuffer.h +Copyright: 2012, Collabora, Ltd +License: BSD-2-clause + +Files: hybris/egl/platforms/wayland/* +Copyright: 2013, Jolla Ltd +License: LGPL-2.1 + +Files: hybris/egl/ws.c +Copyright: 2013, libhybris +License: Apache-2.0 + +Files: hybris/glesv1/* +Copyright: 2012-2014, Jolla Ltd +License: Apache-2.0 + +Files: hybris/glesv2/* +Copyright: 2012, Carsten Munk +License: Apache-2.0 + +Files: hybris/hardware/* +Copyright: 2012, 2013, Simon Busch +License: Apache-2.0 + +Files: hybris/include/* +Copyright: 2007-2012, The Khronos Group Inc +License: Expat + +Files: hybris/include/EGL/eglmesaext.h +Copyright: 2008, Tungsten Graphics, Inc., Cedar Park, Texas +License: Expat Files: hybris/include/GL/gl.h -Copyright: 1999-2006 Brian Paul - 2009 VMware, Inc. -License: X11/MIT +Copyright: 2009, VMware, Inc. + 1999-2006, Brian Paul +License: Expat + +Files: hybris/include/GL/glx.h + hybris/include/GL/glx_mangle.h + hybris/include/GL/osmesa.h +Copyright: 1999-2006, Brian Paul +License: Expat + +Files: hybris/include/GL/internal/* +Copyright: IBM Corporation 2004, / 2007-2008, Red Hat, Inc / 1998-1999, Precision Insight, Inc., Cedar Park, Texas +License: Expat + +Files: hybris/include/GL/internal/sarea.h +Copyright: 2000, VA Linux Systems, Inc + 1998, 1999, Precision Insight, Inc., Cedar Park, Texas +License: Expat Files: hybris/include/GL/wmesa.h -Copyright: 1995-1998 Brian Paul +Copyright: 1995-1998, Brian Paul License: LGPL-2+ -Files: hybris/include/GL/internal/sarea.h -Copyright: 1998-1999 Precision Insight, Inc., Cedar Park, Texas. - 2000 VA Linux Systems, Inc. -License: X11/MIT - -Files: hybris/include/GL/internal/dri_interface.h -Copyright: 1998-1999 Precision Insight, Inc., Cedar Park, Texas. - 2007-2008 Red Hat, Inc. - 2004 IBM Corporation -License: X11/MIT +Files: hybris/include/GLES/* +Copyright: 2010-2012 Silicon Graphics, Inc +License: SGI-2.0 -Files: hybris/include/GLES2/gl2.h hybris/include/GLES2/gl2ext.h hybris/include/GLES2/gl2platform.h hybris/include/GLES/gl.h hybris/include/GLES/glext.h hybris/include/GLES/glplatform.h +Files: hybris/include/GLES2/* Copyright: 2010-2012 Silicon Graphics, Inc License: SGI-2.0 - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation the - rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is furnished - to do so, subject to the following conditions: - . - The above copyright notice including the dates of first publication and either - this permission notice or a reference to http://oss.sgi.com/projects/FreeB/ - shall be included in all copies or substantial portions of the Software. - . - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. BE - LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR - IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - IN THE SOFTWARE. - . - Except as contained in this notice, the name of Silicon Graphics, Inc. shall - not be used in advertising or otherwise to promote the sale, use or other - dealings in this Software without prior written authorization from Silicon - Graphics, Inc. + +Files: hybris/include/VG/* +Copyright: 2008, The Khronos Group Inc +License: X11/MIT + +Files: hybris/include/hybris/* +Copyright: 2012-2014, 2016, Canonical Ltd +License: Apache-2.0 + +Files: hybris/include/hybris/common/binding.h +Copyright: 2013, Simon Busch + 2013, Jolla Ltd. + 2012, Canonical Ltd +License: Apache-2.0 + +Files: hybris/include/hybris/common/dlfcn.h +Copyright: 2013, Intel Corporation +License: Apache-2.0 + +Files: hybris/include/hybris/common/floating_point_abi.h +Copyright: 2012-2014, Jolla Ltd +License: Apache-2.0 + +Files: hybris/include/hybris/dlfcn/* +Copyright: 2013, Intel Corporation +License: Apache-2.0 + +Files: hybris/include/hybris/properties/* +Copyright: 2013, Simon Busch + 2013, Canonical Ltd + 2012, Carsten Munk + 2008, The Android Open Source Project +License: Apache-2.0 + +Files: hybris/include/hybris/ui/* +Copyright: 2012, 2013, Simon Busch +License: Apache-2.0 + +Files: hybris/libnfc_ndef_nxp/* +Copyright: 2012-2014, Jolla Ltd +License: Apache-2.0 + +Files: hybris/libnfc_nxp/* +Copyright: 2012-2014, Jolla Ltd +License: Apache-2.0 + +Files: hybris/libsync/* +Copyright: 2012, Google, Inc +License: Apache-2.0 + +Files: hybris/properties/* +Copyright: 2013, Simon Busch + 2013, Canonical Ltd + 2012, Carsten Munk + 2008, The Android Open Source Project +License: Apache-2.0 + +Files: hybris/properties/cache.c +Copyright: 2013, Simon Busch + 2013, Jolla Ltd. + 2013, Canonical Ltd + 2012, Carsten Munk + 2008, The Android Open Source Project +License: Apache-2.0 + +Files: hybris/properties/properties_p.h +Copyright: 2013, Jolla Ltd. +License: Apache-2.0 + +Files: hybris/properties/runtime_cache.c +Copyright: 2015, Jolla Ltd. + 2013, Simon Busch + 2013, Jolla Ltd. + 2013, Canonical Ltd + 2012, Carsten Munk + 2008, The Android Open Source Project +License: Apache-2.0 + +Files: hybris/tests/test_egl.c + hybris/tests/test_glesv2.c + hybris/tests/test_hwcomposer.cpp +Copyright: 2012, Carsten Munk +License: Apache-2.0 + +Files: hybris/tests/test_egl_configs.c +Copyright: 2013, Thomas Perl +License: Apache-2.0 + +Files: hybris/tests/test_gps.c + hybris/tests/test_nfc.c + hybris/tests/test_vibrator.c +Copyright: 2012-2014, Jolla Ltd +License: Apache-2.0 + +Files: hybris/tests/test_lights.c + hybris/tests/test_sensors.c + hybris/tests/test_ui.c +Copyright: 2012, 2013, Simon Busch +License: Apache-2.0 + +Files: hybris/ui/* +Copyright: 2012, 2013, Simon Busch +License: Apache-2.0 + +Files: hybris/utils/* +Copyright: 2013, 2014, Canonical Ltd + 2008, The Android Open Source Project +License: Apache-2.0 + +Files: hybris/vibrator/* +Copyright: 2012-2014, Jolla Ltd +License: Apache-2.0 + +Files: utils/* +Copyright: 2013, Jolla Ltd + 2012, Thomas Perl ; 2012-10-19 libhybris version: +License: BSD-2-clause + +Files: utils/generate_wrapper_macros.py +Copyright: 2013, Jolla Ltd +License: BSD-2-clause Files: utils/load_sym_files.py -Copyright: 2013 Adrian Negreanu +Copyright: 2013, Adrian Negreanu License: GPL-3+ This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -120,8 +375,19 @@ License version 3 can be found in the file `/usr/share/common-licenses/GPL-3'. -Files: hybris/common/gingerbread/* hybris/common/ics/* hybris/common/jb/* -Copyright: 2007-2010 The Android Open Source Project +License: Apache-2.0 + 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. + License: BSD-2-clause Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -146,30 +412,35 @@ OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Files: hybris/egl/platforms/common/wayland-android-client-protocol.h hybris/egl/platforms/common/wayland-android-protocol.c hybris/egl/platforms/common/server_wlegl_buffer.h hybris/egl/platforms/common/server_wlegl_buffer.cpp hybris/egl/platforms/common/server_wlegl.h hybris/egl/platforms/common/wayland-android.xml hybris/egl/platforms/common/server_wlegl_handle.cpp hybris/egl/platforms/common/wayland-android-server-protocol.h hybris/egl/platforms/common/server_wlegl.cpp hybris/egl/platforms/common/server_wlegl_private.h -Copyright: 2012 Collabora, Ltd. -License: MIT2 - Permission to use, copy, modify, distribute, and sell this software and - its documentation for any purpose is hereby granted without fee, provided - that the above copyright notice appear in all copies and that both that - copyright notice and this permission notice appear in supporting - documentation, and that the name of the copyright holders not be used in - advertising or publicity pertaining to distribution of the software - without specific, written prior permission. The copyright holders make - no representations about the suitability of this software for any - purpose. It is provided "as is" without express or implied warranty. +License: Expat + The MIT License . - THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER - RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF - CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN - CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated + documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to + whom the Software is furnished to do so, subject to the + following conditions: + . + The above copyright notice and this permission notice shall + be included in all copies or substantial portions of the + Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT + WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE AND NONINFRINGEMENT. IN NO EVENT + SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. -Files: hybris/common/strlcpy.c -Copyright: 1998 Todd C. Miller -License: ICS +License: ISC Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. @@ -182,24 +453,11 @@ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -License: Apache 2.0 - 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. - -License: LGPL-2.1 +License: LGPL-2+ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation, version 2.1 - of the License. + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. . This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -212,14 +470,14 @@ Boston, MA 02110-1301 USA . On Debian systems, the full text of the GNU Lesser General Public - License version 2.1 can be found in the file - `/usr/share/common-licenses/LGPL-2.1'. + License version 2 can be found in the file + `/usr/share/common-licenses/LGPL-2'. -License: LGPL-2+ +License: LGPL-2.1 This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. + License as published by the Free Software Foundation, version 2.1 + of the License. . This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -232,8 +490,8 @@ Boston, MA 02110-1301 USA . On Debian systems, the full text of the GNU Lesser General Public - License version 2 can be found in the file - `/usr/share/common-licenses/LGPL-2'. + License version 2.1 can be found in the file + `/usr/share/common-licenses/LGPL-2.1'. License: X11/MIT Permission is hereby granted, free of charge, to any person obtaining a copy @@ -253,3 +511,29 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +License: SGI-2.0 + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is furnished + to do so, subject to the following conditions: + . + The above copyright notice including the dates of first publication and either + this permission notice or a reference to http://oss.sgi.com/projects/FreeB/ + shall be included in all copies or substantial portions of the Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL SILICON GRAPHICS, INC. BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. + . + Except as contained in this notice, the name of Silicon Graphics, Inc. shall + not be used in advertising or otherwise to promote the sale, use or other + dealings in this Software without prior written authorization from Silicon + Graphics, Inc. diff -Nru libhybris-0.1.0+git20131207+e452e83/debian/libhybris-common1.install libhybris-0.1.0+git20151016+6d424c9/debian/libhybris-common1.install --- libhybris-0.1.0+git20131207+e452e83/debian/libhybris-common1.install 2015-04-06 23:53:56.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/debian/libhybris-common1.install 2016-08-05 16:46:15.000000000 +0000 @@ -1 +1,2 @@ usr/lib/*/libhybris-common.so.* +usr/lib/*/libhybris/linker/*.so diff -Nru libhybris-0.1.0+git20131207+e452e83/debian/libhybris-dev.install libhybris-0.1.0+git20151016+6d424c9/debian/libhybris-dev.install --- libhybris-0.1.0+git20131207+e452e83/debian/libhybris-dev.install 2015-04-06 23:53:56.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/debian/libhybris-dev.install 2016-08-05 16:46:15.000000000 +0000 @@ -6,11 +6,15 @@ usr/lib/*/libis.so usr/lib/*/libcamera.so usr/lib/*/libwifi.so +usr/lib/*/libnfc_nxp.so +usr/lib/*/libvibrator.so usr/lib/*/pkgconfig/hwcomposer-egl.pc usr/lib/*/pkgconfig/hybris-egl-platform.pc usr/lib/*/pkgconfig/libis.pc usr/lib/*/pkgconfig/libcamera.pc usr/lib/*/pkgconfig/libwifi.pc +usr/lib/*/pkgconfig/libvibrator.pc +usr/lib/*/pkgconfig/libnfc_nxp.pc usr/lib/*/pkgconfig/libsf.pc usr/lib/*/pkgconfig/libsync.pc usr/include/hybris/input @@ -21,3 +25,4 @@ usr/include/hybris/eglplatformcommon usr/include/hybris/hwcomposerwindow usr/include/hybris/dlfcn +usr/include/hybris/common diff -Nru libhybris-0.1.0+git20131207+e452e83/debian/libhybris.install.in libhybris-0.1.0+git20151016+6d424c9/debian/libhybris.install.in --- libhybris-0.1.0+git20131207+e452e83/debian/libhybris.install.in 2015-04-06 23:53:56.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/debian/libhybris.install.in 2016-08-05 16:46:15.000000000 +0000 @@ -6,7 +6,10 @@ usr/lib/*/libis.so.* usr/lib/*/libcamera.so.* usr/lib/*/libwifi.so.* +usr/lib/*/libnfc_nxp.so.* +usr/lib/*/libvibrator.so.* usr/lib/*/libhybris/*.so usr/lib/*/libwayland-egl.so.* #PKGLIBDIR# usr/lib/*/libEGL.so.* #PKGLIBDIR# usr/lib/*/libGLESv2.so.* #PKGLIBDIR# +usr/lib/*/libGLESv1_CM.so.* #PKGLIBDIR# diff -Nru libhybris-0.1.0+git20131207+e452e83/debian/libhybris-utils.install libhybris-0.1.0+git20151016+6d424c9/debian/libhybris-utils.install --- libhybris-0.1.0+git20131207+e452e83/debian/libhybris-utils.install 2015-04-06 23:53:56.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/debian/libhybris-utils.install 2016-08-05 16:46:15.000000000 +0000 @@ -1,2 +1,3 @@ usr/bin/getprop usr/bin/setprop +utils/load_sym_files.py usr/share/libhybris/gdb/ diff -Nru libhybris-0.1.0+git20131207+e452e83/debian/patches/debian-changes libhybris-0.1.0+git20151016+6d424c9/debian/patches/debian-changes --- libhybris-0.1.0+git20131207+e452e83/debian/patches/debian-changes 2015-04-06 23:56:31.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/debian/patches/debian-changes 2016-08-10 06:28:18.000000000 +0000 @@ -9,7 +9,7 @@ For full commit history and separated commits, see the packaging Git repository. --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/Android.common.mk ++++ libhybris-0.1.0+git20151016+6d424c9/compat/Android.common.mk @@ -0,0 +1,10 @@ +# define ANDROID_VERSION MAJOR, MINOR and PATCH + @@ -21,8 +21,8 @@ + -DANDROID_VERSION_MAJOR=$(ANDROID_VERSION_MAJOR) \ + -DANDROID_VERSION_MINOR=$(ANDROID_VERSION_MINOR) \ + -DANDROID_VERSION_PATCH=$(ANDROID_VERSION_PATCH) ---- libhybris-0.1.0+git20131207+e452e83.orig/compat/camera/Android.mk -+++ libhybris-0.1.0+git20131207+e452e83/compat/camera/Android.mk +--- libhybris-0.1.0+git20151016+6d424c9.orig/compat/camera/Android.mk ++++ libhybris-0.1.0+git20151016+6d424c9/compat/camera/Android.mk @@ -1,5 +1,6 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) @@ -30,7 +30,27 @@ HYBRIS_PATH := $(LOCAL_PATH)/../../hybris -@@ -43,6 +44,7 @@ LOCAL_SHARED_LIBRARIES := \ +@@ -7,6 +8,9 @@ LOCAL_SRC_FILES := camera_compatibility_ + + LOCAL_MODULE := libcamera_compat_layer + LOCAL_MODULE_TAGS := optional ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif + + LOCAL_C_INCLUDES := \ + $(HYBRIS_PATH)/include +@@ -30,6 +34,9 @@ LOCAL_SRC_FILES := direct_camera_test.cp + + LOCAL_MODULE := direct_camera_test + LOCAL_MODULE_TAGS := optional ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif + + LOCAL_C_INCLUDES := \ + $(HYBRIS_PATH)/include \ +@@ -43,6 +50,7 @@ LOCAL_SHARED_LIBRARIES := \ libis_compat_layer \ libsf_compat_layer \ libcamera_compat_layer \ @@ -38,8 +58,8 @@ libcutils \ libcamera_client \ libutils \ ---- libhybris-0.1.0+git20131207+e452e83.orig/compat/camera/camera_compatibility_layer.cpp -+++ libhybris-0.1.0+git20131207+e452e83/compat/camera/camera_compatibility_layer.cpp +--- libhybris-0.1.0+git20151016+6d424c9.orig/compat/camera/camera_compatibility_layer.cpp ++++ libhybris-0.1.0+git20151016+6d424c9/compat/camera/camera_compatibility_layer.cpp @@ -1,11 +1,11 @@ /* - * Copyright (C) 2013 Canonical Ltd @@ -68,7 +88,7 @@ #include #include #include -@@ -27,17 +30,29 @@ +@@ -27,18 +30,41 @@ #include #include #include @@ -77,6 +97,9 @@ +#else +#include +#endif ++#if ANDROID_VERSION_MAJOR>=5 ++#include ++#endif #include +#include @@ -84,6 +107,8 @@ + #undef LOG_TAG #define LOG_TAG "CameraCompatibilityLayer" ++#include ++#include #include #include +#include @@ -95,15 +120,100 @@ #define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__) -// From android::SurfaceTexture::FrameAvailableListener +-void CameraControl::onFrameAvailable() ++using android::CompileTimeAssert; // So COMPILE_TIME_ASSERT works ++ +// From android::GLConsumer::FrameAvailableListener - void CameraControl::onFrameAvailable() ++#if ANDROID_VERSION_MAJOR==5 && ANDROID_VERSION_MINOR>=1 || ANDROID_VERSION_MAJOR>=6 ++ void CameraControl::onFrameAvailable(const android::BufferItem& item) ++#else ++ void CameraControl::onFrameAvailable() ++#endif + { + REPORT_FUNCTION(); + if (listener) +@@ -95,6 +121,9 @@ void CameraControl::postData( + if (listener->on_data_compressed_image_cb) + listener->on_data_compressed_image_cb(data->pointer(), data->size(), listener->context); + break; ++ case CAMERA_MSG_PREVIEW_FRAME: ++ if (listener->on_preview_frame_cb) ++ listener->on_preview_frame_cb(data->pointer(), data->size(), listener->context); + default: + break; + } +@@ -137,54 +166,80 @@ sp NativeBufferAlloc::cre + } + } + +-namespace ++int android_camera_get_number_of_devices() + { +- +-android::sp camera_control_instance; +- ++ REPORT_FUNCTION(); ++ return android::Camera::getNumberOfCameras(); + } + +-int android_camera_get_number_of_devices() ++int android_camera_get_device_info(int32_t camera_id, int* facing, int* orientation) + { + REPORT_FUNCTION(); +- return android::Camera::getNumberOfCameras(); ++ ++ if (!facing || !orientation) ++ return android::BAD_VALUE; ++ ++ COMPILE_TIME_ASSERT_FUNCTION_SCOPE(CAMERA_FACING_BACK == static_cast(BACK_FACING_CAMERA_TYPE)); ++ COMPILE_TIME_ASSERT_FUNCTION_SCOPE(CAMERA_FACING_FRONT == static_cast(FRONT_FACING_CAMERA_TYPE)); ++ ++ android::CameraInfo ci; ++ ++ int rv = android::Camera::getCameraInfo(camera_id, &ci); ++ if (rv != android::OK) ++ return rv; ++ ++ *facing = ci.facing; ++ *orientation = ci.orientation; ++ ++ return android::OK; + } + + CameraControl* android_camera_connect_to(CameraType camera_type, CameraControlListener* listener) { REPORT_FUNCTION(); -@@ -170,7 +185,11 @@ CameraControl* android_camera_connect_to - CameraControl* cc = new CameraControl(); +- int32_t camera_id; +- int32_t camera_count = camera_id = android::Camera::getNumberOfCameras(); ++ const int32_t camera_count = android::Camera::getNumberOfCameras(); + +- for (camera_id = 0; camera_id < camera_count; camera_id++) { ++ for (int32_t camera_id = 0; camera_id < camera_count; camera_id++) { + android::CameraInfo ci; + android::Camera::getCameraInfo(camera_id, &ci); + +- if (ci.facing == camera_type) +- break; ++ if (ci.facing != camera_type) ++ continue; ++ ++ return android_camera_connect_by_id(camera_id, listener); + } + +- if (camera_id == camera_count) ++ return NULL; ++} ++ ++CameraControl* android_camera_connect_by_id(int32_t camera_id, struct CameraControlListener* listener) ++{ ++ if (camera_id < 0 || camera_id >= android::Camera::getNumberOfCameras()) + return NULL; + +- CameraControl* cc = new CameraControl(); ++ android::sp cc = new CameraControl(); cc->listener = listener; -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR>=3 ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR>=3 || ANDROID_VERSION_MAJOR==5 || ANDROID_VERSION_MAJOR>=6 + cc->camera = android::Camera::connect(camera_id, android::String16("hybris"), android::Camera::USE_CALLING_UID); +#else cc->camera = android::Camera::connect(camera_id); @@ -111,7 +221,36 @@ if (cc->camera == NULL) return NULL; -@@ -252,6 +271,35 @@ void android_camera_get_flash_mode(Camer + + cc->camera_parameters = android::CameraParameters(cc->camera->getParameters()); + +- camera_control_instance = cc; +- cc->camera->setListener(camera_control_instance); ++ // android::Camera holds a strong reference to the listener, keeping ++ // |cc| alive ++ cc->camera->setListener(cc); + cc->camera->lock(); + + // TODO: Move this to a more generic component + android::ProcessState::self()->startThreadPool(); + +- return cc; ++ return cc.get(); + } + + void android_camera_disconnect(CameraControl* control) +@@ -215,7 +270,9 @@ int android_camera_unlock(CameraControl* + + void android_camera_delete(CameraControl* control) + { +- delete control; ++ android::sp camera = control->camera; ++ control->camera.clear(); ++ camera.clear(); + } + + void android_camera_dump_parameters(CameraControl* control) +@@ -252,6 +309,35 @@ void android_camera_get_flash_mode(Camer *mode = FLASH_MODE_OFF; } @@ -147,7 +286,7 @@ void android_camera_set_white_balance_mode(CameraControl* control, WhiteBalanceMode mode) { REPORT_FUNCTION(); -@@ -291,6 +339,31 @@ void android_camera_set_scene_mode(Camer +@@ -291,6 +377,31 @@ void android_camera_set_scene_mode(Camer control->camera->setParameters(control->camera_parameters.flatten()); } @@ -179,7 +318,7 @@ void android_camera_get_scene_mode(CameraControl* control, SceneMode* mode) { REPORT_FUNCTION(); -@@ -445,6 +518,67 @@ void android_camera_get_picture_size(Cam +@@ -445,6 +556,67 @@ void android_camera_get_picture_size(Cam control->camera_parameters.getPictureSize(width, height); } @@ -247,7 +386,7 @@ void android_camera_set_picture_size(CameraControl* control, int width, int height) { REPORT_FUNCTION(); -@@ -511,30 +645,57 @@ void android_camera_set_preview_texture( +@@ -511,30 +683,72 @@ void android_camera_set_preview_texture( assert(control); static const bool allow_synchronous_mode = false; @@ -257,6 +396,11 @@ new android::NativeBufferAlloc() ); ++#if ANDROID_VERSION_MAJOR>=5 ++ android::sp producer; ++ android::sp consumer; ++ android::BufferQueue::createBufferQueue(&producer, &consumer); ++#else android::sp buffer_queue( +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 new android::BufferQueue(false, NULL, native_alloc) @@ -264,6 +408,7 @@ + new android::BufferQueue(NULL) +#endif ); ++#endif if (control->preview_texture == NULL) { +#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 @@ -273,7 +418,13 @@ + control->preview_texture = android::sp( + new android::GLConsumer( +#endif -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 ++#if ANDROID_VERSION_MAJOR>=5 ++ consumer, ++ texture_id, ++ GL_TEXTURE_EXTERNAL_OES, ++ true, ++ is_controlled_by_app)); ++#elif ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 texture_id, allow_synchronous_mode, GL_TEXTURE_EXTERNAL_OES, @@ -294,7 +445,10 @@ +#else + android::sp(control)); +#endif -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 ++ ++#if ANDROID_VERSION_MAJOR>=5 ++ control->camera->setPreviewTarget(producer); ++#elif ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 control->camera->setPreviewTexture(control->preview_texture->getBufferQueue()); +#else + control->camera->setPreviewTarget(buffer_queue); @@ -305,7 +459,7 @@ void android_camera_set_preview_surface(CameraControl* control, SfSurface* surface) { REPORT_FUNCTION(); -@@ -544,6 +705,7 @@ void android_camera_set_preview_surface( +@@ -544,6 +758,7 @@ void android_camera_set_preview_surface( android::Mutex::Autolock al(control->guard); control->camera->setPreviewDisplay(surface->surface); } @@ -313,7 +467,70 @@ void android_camera_start_preview(CameraControl* control) { -@@ -702,6 +864,30 @@ void android_camera_set_rotation(CameraC +@@ -630,6 +845,22 @@ void android_camera_take_snapshot(Camera + control->camera->takePicture(CAMERA_MSG_SHUTTER | CAMERA_MSG_COMPRESSED_IMAGE); + } + ++int android_camera_set_preview_callback_mode(CameraControl* control, PreviewCallbackMode mode) ++{ ++ REPORT_FUNCTION(); ++ ++ if (!control) ++ return android::BAD_VALUE; ++ ++ android::Mutex::Autolock al(control->guard); ++ ++ control->camera->setPreviewCallbackFlags( ++ mode == PREVIEW_CALLBACK_ENABLED ? ++ CAMERA_FRAME_CALLBACK_FLAG_CAMCORDER : CAMERA_FRAME_CALLBACK_FLAG_NOOP); ++ ++ return android::OK; ++} ++ + void android_camera_set_preview_format(CameraControl* control, CameraPixelFormat pf) + { + REPORT_FUNCTION(); +@@ -690,6 +921,39 @@ void android_camera_reset_focus_region(C + android_camera_set_focus_region(control, ®ion); + } + ++void android_camera_set_metering_region( ++ CameraControl* control, ++ MeteringRegion* region) ++{ ++ REPORT_FUNCTION(); ++ assert(control); ++ ++ android::Mutex::Autolock al(control->guard); ++ static const char* metering_region_pattern = "(%d,%d,%d,%d,%d)"; ++ static char metering_region[256]; ++ snprintf(metering_region, ++ sizeof(metering_region), ++ metering_region_pattern, ++ region->left, ++ region->top, ++ region->right, ++ region->bottom, ++ region->weight); ++ ++ control->camera_parameters.set( ++ android::CameraParameters::KEY_METERING_AREAS, ++ metering_region); ++ ++ control->camera->setParameters(control->camera_parameters.flatten()); ++} ++ ++void android_camera_reset_metering_region(CameraControl* control) ++{ ++ static FocusRegion region = { 0, 0, 0, 0, 0 }; ++ ++ android_camera_set_metering_region(control, ®ion); ++} ++ + void android_camera_set_rotation(CameraControl* control, int rotation) + { + REPORT_FUNCTION(); +@@ -702,6 +966,30 @@ void android_camera_set_rotation(CameraC control->camera->setParameters(control->camera_parameters.flatten()); } @@ -344,7 +561,7 @@ void android_camera_enumerate_supported_video_sizes(CameraControl* control, size_callback cb, void* ctx) { REPORT_FUNCTION(); -@@ -737,3 +923,25 @@ void android_camera_set_video_size(Camer +@@ -737,3 +1025,25 @@ void android_camera_set_video_size(Camer control->camera_parameters.setVideoSize(width, height); control->camera->setParameters(control->camera_parameters.flatten()); } @@ -370,8 +587,8 @@ + *quality = atoi(control->camera_parameters.get( + android::CameraParameters::KEY_JPEG_QUALITY)); +} ---- libhybris-0.1.0+git20131207+e452e83.orig/compat/camera/direct_camera_test.cpp -+++ libhybris-0.1.0+git20131207+e452e83/compat/camera/direct_camera_test.cpp +--- libhybris-0.1.0+git20151016+6d424c9.orig/compat/camera/direct_camera_test.cpp ++++ libhybris-0.1.0+git20151016+6d424c9/compat/camera/direct_camera_test.cpp @@ -1,11 +1,11 @@ /* - * Copyright (C) 2013 Canonical Ltd @@ -1069,25 +1286,141 @@ + android_camera_stop_preview(camera_control); + android_camera_disconnect(camera_control); } ---- libhybris-0.1.0+git20131207+e452e83.orig/compat/input/Android.mk -+++ libhybris-0.1.0+git20131207+e452e83/compat/input/Android.mk -@@ -18,6 +18,11 @@ LOCAL_SHARED_LIBRARIES := \ - libgui \ - libandroidfw +--- libhybris-0.1.0+git20151016+6d424c9.orig/compat/input/Android.mk ++++ libhybris-0.1.0+git20151016+6d424c9/compat/input/Android.mk +@@ -1,5 +1,6 @@ + LOCAL_PATH := $(call my-dir) + include $(CLEAR_VARS) ++include $(LOCAL_PATH)/../Android.common.mk + + HYBRIS_PATH := $(LOCAL_PATH)/../../hybris + +@@ -9,6 +10,9 @@ LOCAL_SRC_FILES:= input_compatibility_la + + LOCAL_MODULE:= libis_compat_layer + LOCAL_MODULE_TAGS := optional ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif + LOCAL_SHARED_LIBRARIES := \ + libinput \ +@@ -20,8 +24,24 @@ LOCAL_SHARED_LIBRARIES := \ + + LOCAL_C_INCLUDES := \ + $(HYBRIS_PATH)/include \ +- external/skia/include/core \ +- frameworks/base/services/input ++ external/skia/include/core ++ +HAS_LIBINPUTSERVICE := $(shell test $(ANDROID_VERSION_MAJOR) -eq 4 -a $(ANDROID_VERSION_MINOR) -gt 2 && echo true) +ifeq ($(HAS_LIBINPUTSERVICE),true) +LOCAL_SHARED_LIBRARIES += libinputservice ++LOCAL_C_INCLUDES += frameworks/base/services/input +endif + ++HAS_LIBINPUTFLINGER := $(shell test $(ANDROID_VERSION_MAJOR) -ge 5 && echo true) ++ifeq ($(HAS_LIBINPUTFLINGER),true) ++LOCAL_SHARED_LIBRARIES += libinputflinger libinputservice ++LOCAL_C_INCLUDES += \ ++ frameworks/base/libs/input \ ++ frameworks/native/services ++endif ++ ++ ++ + + include $(BUILD_SHARED_LIBRARY) + +@@ -36,6 +56,9 @@ LOCAL_SRC_FILES:= \ + + LOCAL_MODULE:= direct_input_test + LOCAL_MODULE_TAGS := optional ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif + LOCAL_C_INCLUDES := \ $(HYBRIS_PATH)/include \ - external/skia/include/core \ +--- libhybris-0.1.0+git20151016+6d424c9.orig/compat/input/input_compatibility_layer.cpp ++++ libhybris-0.1.0+git20151016+6d424c9/compat/input/input_compatibility_layer.cpp +@@ -19,8 +19,14 @@ + + #include + +-#include "InputListener.h" +-#include "InputReader.h" ++#if ANDROID_VERSION_MAJOR<=4 ++ #include "InputListener.h" ++ #include "InputReader.h" ++#elif ANDROID_VERSION_MAJOR>=5 ++ #include "inputflinger/InputListener.h" ++ #include "inputflinger/InputReader.h" ++#endif ++ + #include "PointerController.h" + #include "SpriteController.h" + #include +@@ -48,10 +54,28 @@ public: + + DefaultPointerControllerPolicy() + { ++#if ANDROID_VERSION_MAJOR<=4 + bitmap.setConfig( + SkBitmap::kARGB_8888_Config, + bitmap_width, + bitmap_height); ++#elif ANDROID_VERSION_MAJOR==5 ++ SkColorType ct = SkBitmapConfigToColorType(SkBitmap::kARGB_8888_Config); ++ bitmap.setInfo( ++ SkImageInfo::Make(bitmap_width, ++ bitmap_height, ++ ct, ++ SkAlphaType::kPremul_SkAlphaType), ++ 0); ++#elif ANDROID_VERSION_MAJOR==6 ++bitmap.setInfo( ++ SkImageInfo::Make(bitmap_width, ++ bitmap_height, ++ kRGBA_8888_SkColorType, ++ SkAlphaType::kPremul_SkAlphaType), ++ 0); ++ ++#endif + bitmap.allocPixels(); + + // Icon for spot touches +@@ -142,7 +166,11 @@ public: + mInputDevices = inputDevices; + } + ++#if ANDROID_VERSION_MAJOR<=4 + virtual android::sp getKeyboardLayoutOverlay(const android::String8& inputDeviceDescriptor) { ++#elif ANDROID_VERSION_MAJOR>=5 ++ virtual android::sp getKeyboardLayoutOverlay(const android::InputDeviceIdentifier& identifier) { ++#endif + return NULL; + } + +@@ -150,6 +178,12 @@ public: + return android::String8::empty(); + } + ++#if ANDROID_VERSION_MAJOR>=5 ++ virtual android::TouchAffineTransformation getTouchAffineTransformation(const android::String8& inputDeviceDescriptor, int32_t surfaceRotation) { ++ return android::TouchAffineTransformation(); ++ } ++#endif ++ + private: + android::sp looper; + int default_layer_for_touch_point_visualization; --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/Android.mk -@@ -0,0 +1,163 @@ ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/Android.mk +@@ -0,0 +1,179 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) ++include $(LOCAL_PATH)/../Android.common.mk + +LOCAL_SRC_FILES := \ + camera_service.cpp @@ -1108,8 +1441,23 @@ + frameworks/av/services/medialog \ + frameworks/av/services/camera/libcameraservice + ++IS_ANDROID_5 := $(shell test $(ANDROID_VERSION_MAJOR) -ge 5 && echo true) ++ ++ifeq ($(IS_ANDROID_5),true) ++LOCAL_C_INCLUDES += system/media/camera/include ++ ++# All devices having Android 5.x also have MediaCodecSource ++# available so we don't have to put a switch for this into ++# any BoardConfig.mk ++BOARD_HAS_MEDIA_CODEC_SOURCE := true ++endif ++ +LOCAL_MODULE := camera_service + ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif ++ +include $(BUILD_EXECUTABLE) + +# ------------------------------------------------- @@ -1121,6 +1469,13 @@ + +LOCAL_CFLAGS += -std=gnu++0x + ++ifeq ($(BOARD_HAS_MEDIA_RECORDER_PAUSE),true) ++LOCAL_CFLAGS += -DBOARD_HAS_MEDIA_RECORDER_PAUSE ++endif ++ifeq ($(BOARD_HAS_MEDIA_RECORDER_RESUME),true) ++LOCAL_CFLAGS += -DBOARD_HAS_MEDIA_RECORDER_RESUME ++endif ++ +LOCAL_SRC_FILES:= \ + media_compatibility_layer.cpp \ + media_codec_layer.cpp \ @@ -1132,10 +1487,22 @@ + media_recorder.cpp \ + media_recorder_client.cpp \ + media_recorder_factory.cpp \ -+ media_recorder_observer.cpp ++ media_recorder_observer.cpp \ ++ media_buffer_layer.cpp \ ++ media_message_layer.cpp \ ++ media_meta_data_layer.cpp ++ ++ifeq ($(BOARD_HAS_MEDIA_CODEC_SOURCE),true) ++# MediaCodecSource support is only available starting with ++# Android 5.x so we have to limit support for it. ++LOCAL_SRC_FILES += media_codec_source_layer.cpp ++endif + +LOCAL_MODULE:= libmedia_compat_layer +LOCAL_MODULE_TAGS := optional ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif + +LOCAL_SHARED_LIBRARIES := \ + libcutils \ @@ -1159,11 +1526,17 @@ + frameworks/base/include/media/stagefright \ + frameworks/base/include/media \ + frameworks/av/media \ ++ frameworks/av/media/libstagefright/include \ + frameworks/av/include \ + frameworks/native/include \ + system/media/audio_utils/include \ + frameworks/av/services/camera/libcameraservice + ++IS_ANDROID_5 := $(shell test $(ANDROID_VERSION_MAJOR) -ge 5 && echo true) ++ifeq ($(IS_ANDROID_5),true) ++LOCAL_C_INCLUDES += frameworks/native/include/media/openmax ++endif ++ +ifeq ($(strip $(MTK_CAMERA_BSP_SUPPORT)),yes) +LOCAL_C_INCLUDES += $(TOP)/mediatek/kernel/include/linux/vcodec +LOCAL_SHARED_LIBRARIES += \ @@ -1177,6 +1550,10 @@ + $(TOP)/$(MTK_PATH_SOURCE)/frameworks/av/include +endif + ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif ++ +include $(BUILD_SHARED_LIBRARY) + +# ------------------------------------------------- @@ -1189,6 +1566,9 @@ + +LOCAL_MODULE:= direct_media_test +LOCAL_MODULE_TAGS := optional ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif + +LOCAL_C_INCLUDES := \ + $(HYBRIS_PATH)/include \ @@ -1212,45 +1592,13 @@ + libEGL \ + libGLESv2 + -+include $(BUILD_EXECUTABLE) -+ -+include $(CLEAR_VARS) -+include $(LOCAL_PATH)/../Android.common.mk -+ -+LOCAL_CFLAGS += -Wno-multichar -D SIMPLE_PLAYER -std=gnu++0x -+ -+LOCAL_SRC_FILES:= \ -+ media_codec_layer.cpp \ -+ media_codec_list.cpp \ -+ media_format_layer.cpp \ -+ codec.cpp \ -+ SimplePlayer.cpp -+ -+LOCAL_SHARED_LIBRARIES := \ -+ libstagefright \ -+ libstagefright_foundation \ -+ liblog \ -+ libutils \ -+ libbinder \ -+ libmedia \ -+ libgui \ -+ libcutils \ -+ libui -+ -+LOCAL_C_INCLUDES:= \ -+ $(HYBRIS_PATH)/include \ -+ frameworks/av/media/libstagefright \ -+ frameworks/native/include/media/openmax \ -+ frameworks/base/media/libstagefright/include \ -+ frameworks/base/include/media/stagefright \ -+ frameworks/base/include/media -+ -+LOCAL_MODULE:= codec -+LOCAL_MODULE_TAGS := optional ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif + +include $(BUILD_EXECUTABLE) --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/SimplePlayer.cpp ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/SimplePlayer.cpp @@ -0,0 +1,777 @@ +/* + * Copyright (C) 2012 The Android Open Source Project @@ -2030,7 +2378,7 @@ + +} // namespace android --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/SimplePlayer.h ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/SimplePlayer.h @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2012 The Android Open Source Project @@ -2153,7 +2501,7 @@ + +} // namespace android --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/camera_service.cpp ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/camera_service.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2014 Canonical Ltd @@ -2208,7 +2556,7 @@ + IPCThreadState::self()->joinThreadPool(); +} --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/codec.cpp ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/codec.cpp @@ -0,0 +1,433 @@ +/* + * Copyright (C) 2012 The Android Open Source Project @@ -2644,8 +2992,8 @@ + return 0; +} --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/decoding_service.cpp -@@ -0,0 +1,347 @@ ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/decoding_service.cpp +@@ -0,0 +1,386 @@ +/* + * Copyright (C) 2014 Canonical Ltd + * @@ -2711,8 +3059,11 @@ + CHECK_INTERFACE(IDecodingService, data, reply); + sp gbc; + status_t res = getIGraphicBufferConsumer(&gbc); -+ ++#if ANDROID_VERSION_MAJOR>=6 ++ reply->writeStrongBinder(IInterface::asBinder(gbc)); ++#else + reply->writeStrongBinder(gbc->asBinder()); ++#endif + reply->writeInt32(res); + + return NO_ERROR; @@ -2722,7 +3073,11 @@ + sp gbp; + status_t res = getIGraphicBufferProducer(&gbp); + ++#if ANDROID_VERSION_MAJOR>=6 ++ reply->writeStrongBinder(IInterface::asBinder(gbp)); ++#else + reply->writeStrongBinder(gbp->asBinder()); ++#endif + reply->writeInt32(res); + + return NO_ERROR; @@ -2772,7 +3127,11 @@ + ALOGD("Entering %s", __PRETTY_FUNCTION__); + Parcel data, reply; + data.writeInterfaceToken(IDecodingService::getInterfaceDescriptor()); ++#if ANDROID_VERSION_MAJOR>=6 ++ data.writeStrongBinder(IInterface::asBinder(session)); ++#else + data.writeStrongBinder(session->asBinder()); ++#endif + data.writeInt32(handle); + remote()->transact(REGISTER_SESSION, data, &reply); + return NO_ERROR; @@ -2843,7 +3202,11 @@ + pid_t pid = IPCThreadState::self()->getCallingPid(); + ALOGD("Calling Pid: %d", pid); + ++#if ANDROID_VERSION_MAJOR>=5 ++ *gbc = consumer; ++#else + *gbc = buffer_queue; ++#endif + + return OK; +} @@ -2853,7 +3216,11 @@ + pid_t pid = IPCThreadState::self()->getCallingPid(); + ALOGD("Calling Pid: %d", pid); + ++#if ANDROID_VERSION_MAJOR>=5 ++ *gbp = producer; ++#else + *gbp = buffer_queue; ++#endif + ALOGD("producer(gbp): %p", (void*)gbp->get()); + return OK; +} @@ -2863,8 +3230,13 @@ + ALOGD("Entering %s", __PRETTY_FUNCTION__); + + // Add session/handle to running clients map and connect death observer ++#if ANDROID_VERSION_MAJOR>=6 ++ status_t ret = IInterface::asBinder(session)->linkToDeath(sp(this)); ++ clientCbs.add(IInterface::asBinder(session), clients.valueFor(handle)); ++#else + status_t ret = session->asBinder()->linkToDeath(sp(this)); + clientCbs.add(session->asBinder(), clients.valueFor(handle)); ++#endif + clients.removeItem(handle); + + // Create a new BufferQueue instance so that the next created client plays @@ -2879,11 +3251,20 @@ + ALOGD("Entering %s", __PRETTY_FUNCTION__); + if (session != NULL) + { ++#if ANDROID_VERSION_MAJOR>=6 ++ IInterface::asBinder(session)->unlinkToDeath(this); ++#else + session->asBinder()->unlinkToDeath(this); ++#endif + session.clear(); + // Reset the BufferQueue instance so that the next created client plays + // video correctly ++#if ANDROID_VERSION_MAJOR>=5 ++ producer.clear(); ++ consumer.clear(); ++#else + buffer_queue.clear(); ++#endif + } + + return OK; @@ -2896,14 +3277,20 @@ + sp g_buffer_alloc(new GraphicBufferAlloc()); + + // This BuferQueue is shared between the client and the service -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 ++#if ANDROID_VERSION_MAJOR>=5 ++ BufferQueue::createBufferQueue(&producer, &consumer); ++#elif ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 + sp native_alloc(new NativeBufferAlloc()); + buffer_queue = new BufferQueue(false, NULL, native_alloc); +#else + buffer_queue = new BufferQueue(NULL); -+#endif + ALOGD("buffer_queue: %p", (void*)buffer_queue.get()); ++#endif ++#if ANDROID_VERSION_MAJOR>=5 ++ producer->setBufferCount(5); ++#else + buffer_queue->setBufferCount(5); ++#endif +} + +void DecodingService::binderDied(const wp& who) @@ -2994,8 +3381,8 @@ + +}; // namespace android --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/decoding_service_priv.h -@@ -0,0 +1,203 @@ ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/decoding_service_priv.h +@@ -0,0 +1,208 @@ +/* + * Copyright (C) 2014 Canonical Ltd + * @@ -3128,7 +3515,12 @@ + +private: + static sp decoding_service; ++#if ANDROID_VERSION_MAJOR>=5 ++ sp producer; ++ sp consumer; ++#else + sp buffer_queue; ++#endif + sp session; + DecodingClientDeathCbHybris client_death_cb; + void *client_death_context; @@ -3200,7 +3592,7 @@ + +#endif --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/direct_media_test.cpp ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/direct_media_test.cpp @@ -0,0 +1,417 @@ +/* + * Copyright (C) 2013 Canonical Ltd @@ -3620,7 +4012,7 @@ + return EXIT_SUCCESS; +} --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/direct_media_test.h ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/direct_media_test.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2013 Canonical Ltd @@ -3681,10 +4073,10 @@ + +#endif --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_codec_layer.cpp -@@ -0,0 +1,879 @@ ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_buffer_layer.cpp +@@ -0,0 +1,325 @@ +/* -+ * Copyright (C) 2013 Canonical Ltd ++ * Copyright (C) 2016 Canonical Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. @@ -3698,62 +4090,453 @@ + * See the License for the specific language governing permissions and + * limitations under the License. + * -+ * Authored by: Jim Hodapp ++ * Authored by: Simon Fels + */ + -+// Uncomment to enable verbose debug output +#define LOG_NDEBUG 0 -+ +#undef LOG_TAG -+#define LOG_TAG "MediaCodecLayer" ++#define LOG_TAG "MediaCompatibilityLayer" + -+#include -+#include -+#include ++#include + -+#include "media_format_layer_priv.h" -+#include "surface_texture_client_hybris_priv.h" -+#include "decoding_service_priv.h" ++#include "media_buffer_priv.h" ++#include "media_meta_data_priv.h" ++#include "media_message_priv.h" + -+#include -+#include ++MediaBufferPrivate* MediaBufferPrivate::toPrivate(MediaBufferWrapper *buffer) ++{ ++ if (!buffer) ++ return NULL; + -+#include -+#include ++ return static_cast(buffer); ++} + -+#include ++MediaBufferPrivate::MediaBufferPrivate(android::MediaBuffer *buffer) : ++ buffer(buffer), ++ return_callback(NULL), ++ return_callback_data(NULL) ++{ ++} + -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include ++MediaBufferPrivate::MediaBufferPrivate() : ++ buffer(NULL) ++{ ++} + -+#include -+#include ++MediaBufferPrivate::~MediaBufferPrivate() ++{ ++ if (buffer) ++ buffer->release(); ++} + -+#include -+#include -+#include -+#include ++void MediaBufferPrivate::signalBufferReturned(android::MediaBuffer *buffer) ++{ ++ if (buffer != this->buffer) { ++ ALOGE("Got called for unknown buffer %p", buffer); ++ return; ++ } + -+#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__); ++ if (!return_callback) ++ return; + -+using namespace android; ++ return_callback(this, return_callback_data); ++} + -+struct _MediaCodecDelegate : public AHandler ++MediaBufferWrapper* media_buffer_create(size_t size) +{ -+public: -+ typedef sp<_MediaCodecDelegate> Ptr; ++ android::MediaBuffer *mbuf = new android::MediaBuffer(size); ++ if (!mbuf) ++ return NULL; + -+ explicit _MediaCodecDelegate(void *context); -+ virtual ~_MediaCodecDelegate(); ++ MediaBufferPrivate *d = new MediaBufferPrivate(mbuf); ++ if (!d) { ++ mbuf->release(); ++ return NULL; ++ } + -+protected: ++ return d; ++} ++ ++void media_buffer_destroy(MediaBufferWrapper *buffer) ++{ ++ MediaBufferPrivate *d = MediaBufferPrivate::toPrivate(buffer); ++ if (!d) ++ return; ++ ++ delete d; ++} ++ ++ ++void media_buffer_release(MediaBufferWrapper *buffer) ++{ ++ MediaBufferPrivate *d = MediaBufferPrivate::toPrivate(buffer); ++ if (!d || !d->buffer) ++ return; ++ ++ d->buffer->release(); ++} ++ ++void media_buffer_ref(MediaBufferWrapper *buffer) ++{ ++ MediaBufferPrivate *d = MediaBufferPrivate::toPrivate(buffer); ++ if (!d) ++ return; ++ ++ d->buffer->add_ref(); ++} ++ ++int media_buffer_get_refcount(MediaBufferWrapper *buffer) ++{ ++ MediaBufferPrivate *d = MediaBufferPrivate::toPrivate(buffer); ++ if (!d || !d->buffer) ++ return 0; ++ ++ return d->buffer->refcount(); ++} ++ ++void* media_buffer_get_data(MediaBufferWrapper *buffer) ++{ ++ MediaBufferPrivate *d = MediaBufferPrivate::toPrivate(buffer); ++ if (!d || !d->buffer) ++ return NULL; ++ ++ return d->buffer->data(); ++} ++ ++size_t media_buffer_get_size(MediaBufferWrapper *buffer) ++{ ++ MediaBufferPrivate *d = MediaBufferPrivate::toPrivate(buffer); ++ if (!d || !d->buffer) ++ return 0; ++ ++ return d->buffer->size(); ++} ++ ++size_t media_buffer_get_range_offset(MediaBufferWrapper *buffer) ++{ ++ MediaBufferPrivate *d = MediaBufferPrivate::toPrivate(buffer); ++ if (!d || !d->buffer) ++ return 0; ++ ++ return d->buffer->range_offset(); ++} ++ ++size_t media_buffer_get_range_length(MediaBufferWrapper *buffer) ++{ ++ MediaBufferPrivate *d = MediaBufferPrivate::toPrivate(buffer); ++ if (!d || !d->buffer) ++ return 0; ++ ++ return d->buffer->range_length(); ++} ++ ++MediaMetaDataWrapper* media_buffer_get_meta_data(MediaBufferWrapper *buffer) ++{ ++ MediaBufferPrivate *d = MediaBufferPrivate::toPrivate(buffer); ++ if (!d || !d->buffer) ++ return NULL; ++ ++ return new MediaMetaDataPrivate(d->buffer->meta_data()); ++} ++ ++void media_buffer_set_return_callback(MediaBufferWrapper *buffer, ++ MediaBufferReturnCallback callback, void *user_data) ++{ ++ MediaBufferPrivate *d = MediaBufferPrivate::toPrivate(buffer); ++ if (!d) ++ return; ++ ++ d->return_callback = callback; ++ d->return_callback_data = user_data; ++ ++ if (d->return_callback) ++ d->buffer->setObserver(d); ++ else ++ d->buffer->setObserver(NULL); ++} ++ ++MediaABufferPrivate* MediaABufferPrivate::toPrivate(MediaABufferWrapper *buffer) ++{ ++ if (!buffer) ++ return NULL; ++ ++ return static_cast(buffer); ++} ++ ++MediaABufferPrivate::MediaABufferPrivate() ++{ ++} ++ ++MediaABufferPrivate::MediaABufferPrivate(android::sp buffer) : ++ buffer(buffer) ++{ ++} ++ ++MediaABufferWrapper* media_abuffer_create(size_t capacity) ++{ ++ MediaABufferPrivate *d = new MediaABufferPrivate; ++ if (!d) ++ return NULL; ++ ++ d->buffer = new android::ABuffer(capacity); ++ if (!d->buffer.get()) { ++ delete d; ++ return NULL; ++ } ++ ++ return d; ++} ++ ++MediaABufferWrapper* media_abuffer_create_with_data(uint8_t *data, size_t size) ++{ ++ MediaABufferPrivate *d = new MediaABufferPrivate; ++ if (!d) ++ return NULL; ++ ++ d->buffer = new android::ABuffer(data, size); ++ if (!d->buffer.get()) { ++ delete d; ++ return NULL; ++ } ++ ++ return d; ++} ++ ++void media_abuffer_set_range(MediaABufferWrapper *buffer, size_t offset, size_t size) ++{ ++ MediaABufferPrivate *d = MediaABufferPrivate::toPrivate(buffer); ++ if (!d || !d->buffer.get()) ++ return; ++ ++ d->buffer->setRange(offset, size); ++} ++ ++void media_abuffer_set_media_buffer_base(MediaABufferWrapper *buffer, MediaBufferWrapper *mbuf) ++{ ++ MediaABufferPrivate *d = MediaABufferPrivate::toPrivate(buffer); ++ if (!d || !d->buffer.get()) ++ return; ++ ++#if ANDROID_VERSION_MAJOR>=5 ++ android::MediaBuffer *media_buffer = NULL; ++ ++ if (mbuf != NULL) ++ media_buffer = MediaBufferPrivate::toPrivate(mbuf)->buffer; ++ ++ d->buffer->setMediaBufferBase(media_buffer); ++#else ++ return; ++#endif ++} ++ ++MediaBufferWrapper* media_abuffer_get_media_buffer_base(MediaABufferWrapper *buffer) ++{ ++ MediaABufferPrivate *d = MediaABufferPrivate::toPrivate(buffer); ++ if (!d || !d->buffer.get()) ++ return NULL; ++ ++#if ANDROID_VERSION_MAJOR>= 5 ++ ++ android::MediaBufferBase *mbufb = d->buffer->getMediaBufferBase(); ++ if (mbufb == NULL) ++ return NULL; ++ ++ MediaBufferPrivate *mbuf = new MediaBufferPrivate; ++ mbuf->buffer = (android::MediaBuffer*) mbufb; ++ ++ return mbuf; ++#else ++ return NULL; ++#endif ++} ++ ++void* media_abuffer_get_data(MediaABufferWrapper *buffer) ++{ ++ MediaABufferPrivate *d = MediaABufferPrivate::toPrivate(buffer); ++ if (!d || !d->buffer.get()) ++ return NULL; ++ ++ return d->buffer->data(); ++} ++ ++size_t media_abuffer_get_size(MediaABufferWrapper *buffer) ++{ ++ MediaABufferPrivate *d = MediaABufferPrivate::toPrivate(buffer); ++ if (!d || !d->buffer.get()) ++ return 0; ++ ++ return d->buffer->size(); ++} ++ ++size_t media_abuffer_get_range_offset(MediaABufferWrapper *buffer) ++{ ++ MediaABufferPrivate *d = MediaABufferPrivate::toPrivate(buffer); ++ if (!d || !d->buffer.get()) ++ return 0; ++ ++ return d->buffer->offset(); ++} ++ ++size_t media_abuffer_get_capacity(MediaABufferWrapper *buffer) ++{ ++ MediaABufferPrivate *d = MediaABufferPrivate::toPrivate(buffer); ++ if (!d || !d->buffer.get()) ++ return 0; ++ ++ return d->buffer->capacity(); ++} ++ ++MediaMessageWrapper* media_abuffer_get_meta(MediaABufferWrapper *buffer) ++{ ++ MediaABufferPrivate *d = MediaABufferPrivate::toPrivate(buffer); ++ if (!d || !d->buffer.get()) ++ return NULL; ++ ++ MediaMessagePrivate *msg = new MediaMessagePrivate; ++ if (!msg) ++ return NULL; ++ ++ msg->msg = d->buffer->meta(); ++ ++ return msg; ++} +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_buffer_priv.h +@@ -0,0 +1,56 @@ ++/* ++ * Copyright (C) 2016 Canonical Ltd ++ * ++ * 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. ++ * ++ * Authored by: Simon Fels ++ */ ++ ++#ifndef MEDIA_BUFFER_PRIV_H_ ++#define MEDIA_BUFFER_PRIV_H_ ++ ++#include ++ ++#include ++ ++#include ++ ++struct MediaBufferPrivate : public android::MediaBufferObserver ++{ ++public: ++ static MediaBufferPrivate* toPrivate(MediaBufferWrapper *source); ++ ++ MediaBufferPrivate(android::MediaBuffer *data); ++ MediaBufferPrivate(); ++ ~MediaBufferPrivate(); ++ ++ void signalBufferReturned(android::MediaBuffer *buffer); ++ ++ android::MediaBuffer *buffer; ++ MediaBufferReturnCallback return_callback; ++ void *return_callback_data; ++}; ++ ++struct MediaABufferPrivate ++{ ++public: ++ static MediaABufferPrivate* toPrivate(MediaABufferWrapper *source); ++ ++ MediaABufferPrivate(); ++ MediaABufferPrivate(android::sp buffer); ++ ++public: ++ android::sp buffer; ++}; ++ ++#endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_codec_layer.cpp +@@ -0,0 +1,937 @@ ++/* ++ * Copyright (C) 2013 Canonical Ltd ++ * ++ * 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. ++ * ++ * Authored by: Jim Hodapp ++ */ ++ ++// Uncomment to enable verbose debug output ++#define LOG_NDEBUG 0 ++ ++#undef LOG_TAG ++#define LOG_TAG "MediaCodecLayer" ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#if ANDROID_VERSION_MAJOR<=5 ++#include ++#endif ++ ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "media_format_layer_priv.h" ++#include "surface_texture_client_hybris_priv.h" ++#include "decoding_service_priv.h" ++#include "media_message_priv.h" ++#include "media_buffer_priv.h" ++ ++#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__); ++ ++using namespace android; ++ ++struct _MediaCodecDelegate : public AHandler ++{ ++public: ++ typedef sp<_MediaCodecDelegate> Ptr; ++ ++ explicit _MediaCodecDelegate(void *context); ++ virtual ~_MediaCodecDelegate(); ++ ++protected: + virtual void onMessageReceived(const sp &msg) { } + +public: @@ -4240,17 +5023,44 @@ + return d->input_buffers.itemAt(n).get()->data(); +} + -+size_t media_codec_get_nth_input_buffer_capacity(MediaCodecDelegate delegate, size_t n) ++MediaABufferWrapper* media_codec_get_nth_input_buffer_as_abuffer(MediaCodecDelegate delegate, size_t n) +{ + REPORT_FUNCTION() + + _MediaCodecDelegate *d = get_internal_delegate(delegate); + if (d == NULL) -+ return BAD_VALUE; ++ return NULL; + -+ Vector > input_buffers; -+ status_t ret = d->media_codec->getInputBuffers(&input_buffers); -+ if (ret != OK) ++ if (d->input_buffers.size() == 0) ++ { ++ status_t ret = d->media_codec->getInputBuffers(&d->input_buffers); ++ if (ret != OK) ++ { ++ ALOGE("Failed to get input buffers"); ++ return NULL; ++ } ++ } ++ ++ if (n > d->input_buffers.size()) ++ { ++ ALOGE("Failed to get %uth input buffer, n > total buffer size", n); ++ return NULL; ++ } ++ ++ return new MediaABufferPrivate(d->input_buffers.itemAt(n).get()); ++} ++ ++size_t media_codec_get_nth_input_buffer_capacity(MediaCodecDelegate delegate, size_t n) ++{ ++ REPORT_FUNCTION() ++ ++ _MediaCodecDelegate *d = get_internal_delegate(delegate); ++ if (d == NULL) ++ return BAD_VALUE; ++ ++ Vector > input_buffers; ++ status_t ret = d->media_codec->getInputBuffers(&input_buffers); ++ if (ret != OK) + { + ALOGE("Failed to get input buffers"); + return 0; @@ -4308,6 +5118,33 @@ + return d->output_buffers.itemAt(n).get()->data(); +} + ++MediaABufferWrapper* media_codec_get_nth_output_buffer_as_abuffer(MediaCodecDelegate delegate, size_t n) ++{ ++ REPORT_FUNCTION() ++ ++ _MediaCodecDelegate *d = get_internal_delegate(delegate); ++ if (d == NULL) ++ return NULL; ++ ++ if (d->output_buffers.size() == 0) ++ { ++ status_t ret = d->media_codec->getOutputBuffers(&d->output_buffers); ++ if (ret != OK) ++ { ++ ALOGE("Failed to get output buffers"); ++ return NULL; ++ } ++ } ++ ++ if (n > d->output_buffers.size()) ++ { ++ ALOGE("Failed to get %uth output buffer, n > total buffer size", n); ++ return NULL; ++ } ++ ++ return new MediaABufferPrivate(d->output_buffers.itemAt(n).get()); ++} ++ +size_t media_codec_get_nth_output_buffer_capacity(MediaCodecDelegate delegate, size_t n) +{ + REPORT_FUNCTION() @@ -4563,8 +5400,8 @@ + return f; +} --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_codec_list.cpp -@@ -0,0 +1,228 @@ ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_codec_list.cpp +@@ -0,0 +1,281 @@ +/* + * Copyright (C) 2013 Canonical Ltd + * @@ -4627,13 +5464,21 @@ +const char *media_codec_list_get_codec_name(size_t index) +{ + REPORT_FUNCTION() ++#if ANDROID_VERSION_MAJOR>=5 ++ return MediaCodecList::getInstance()->getCodecInfo(index)->getCodecName(); ++#else + return MediaCodecList::getInstance()->getCodecName(index); ++#endif +} + +bool media_codec_list_is_encoder(size_t index) +{ + REPORT_FUNCTION() ++#if ANDROID_VERSION_MAJOR>=5 ++ return MediaCodecList::getInstance()->getCodecInfo(index)->isEncoder(); ++#else + return MediaCodecList::getInstance()->isEncoder(index); ++#endif +} + +size_t media_codec_list_get_num_supported_types(size_t index) @@ -4641,12 +5486,16 @@ + REPORT_FUNCTION() + + Vector types; ++#if ANDROID_VERSION_MAJOR>=5 ++ MediaCodecList::getInstance()->getCodecInfo(index)->getSupportedMimes(&types); ++#else + status_t err = MediaCodecList::getInstance()->getSupportedTypes(index, &types); + if (err != OK) + { + ALOGE("Failed to get the number of supported codec types (err: %d)", err); + return 0; + } ++#endif + ALOGD("Number of supported codec types: %d", types.size()); + + return types.size(); @@ -4657,7 +5506,11 @@ + REPORT_FUNCTION() + + Vector types; ++#if ANDROID_VERSION_MAJOR>=5 ++ MediaCodecList::getInstance()->getCodecInfo(index)->getSupportedMimes(&types); ++#else + status_t err = MediaCodecList::getInstance()->getSupportedTypes(index, &types); ++#endif + + return types[n].size(); +} @@ -4673,31 +5526,48 @@ + } + + Vector types; ++#if ANDROID_VERSION_MAJOR>=5 ++ MediaCodecList::getInstance()->getCodecInfo(index)->getSupportedMimes(&types); ++#else + status_t err = MediaCodecList::getInstance()->getSupportedTypes(index, &types); ++#endif + for (size_t i=0; i=5 ++ return OK; ++#else + return err; ++#endif +} + +static void media_codec_list_get_num_codec_capabilities(size_t index, const char *type, size_t *num_profile_levels, size_t *num_color_formats) +{ + REPORT_FUNCTION() + ++#if ANDROID_VERSION_MAJOR>=5 ++ Vector profile_levels; ++#else + Vector profile_levels; ++#endif + Vector color_formats; + ALOGD("index: %d, type: '%s'", index, type); -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 ++#if ANDROID_VERSION_MAJOR>=5 ++ MediaCodecList::getInstance()->getCodecInfo(index)->getCapabilitiesFor(type)->getSupportedProfileLevels(&profile_levels); ++ MediaCodecList::getInstance()->getCodecInfo(index)->getCapabilitiesFor(type)->getSupportedColorFormats(&color_formats); ++#elif ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 + status_t err = MediaCodecList::getInstance()->getCodecCapabilities(index, type, &profile_levels, &color_formats); +#else + uint32_t flags; + status_t err = MediaCodecList::getInstance()->getCodecCapabilities(index, type, &profile_levels, &color_formats, &flags); +#endif ++#if ANDROID_VERSION_MAJOR<5 + if (err != OK) + { + ALOGE("Failed to get the number of supported codec capabilities (err: %d)", err); + return; + } ++#endif + + if (num_profile_levels != NULL) + { @@ -4747,43 +5617,63 @@ + return BAD_VALUE; + } + ++#if ANDROID_VERSION_MAJOR>=5 ++ Vector profile_levels; ++#else + Vector profile_levels; ++#endif + Vector formats; -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 ++#if ANDROID_VERSION_MAJOR>=5 ++ MediaCodecList::getInstance()->getCodecInfo(index)->getCapabilitiesFor(type)->getSupportedProfileLevels(&profile_levels); ++#elif ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 + status_t err = MediaCodecList::getInstance()->getCodecCapabilities(index, type, &profile_levels, &formats); +#else + uint32_t flags; + status_t err = MediaCodecList::getInstance()->getCodecCapabilities(index, type, &profile_levels, &formats, &flags); +#endif ++#if ANDROID_VERSION_MAJOR<5 + if (err != OK) + { + ALOGE("Failed to get the nth codec profile level (err: %d)", err); + return 0; + } ++#endif + + pro_level->profile = profile_levels[n].mProfile; + pro_level->level = profile_levels[n].mLevel; + ++#if ANDROID_VERSION_MAJOR>=5 ++ return OK; ++#else + return err; ++#endif +} + +int media_codec_list_get_codec_color_formats(size_t index, const char *type, uint32_t *color_formats) +{ + REPORT_FUNCTION() + ++#if ANDROID_VERSION_MAJOR>=5 ++ Vector profile_levels; ++#else + Vector profile_levels; ++#endif + Vector formats; -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 ++#if ANDROID_VERSION_MAJOR>=5 ++ MediaCodecList::getInstance()->getCodecInfo(index)->getCapabilitiesFor(type)->getSupportedColorFormats(&formats); ++#elif ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 + status_t err = MediaCodecList::getInstance()->getCodecCapabilities(index, type, &profile_levels, &formats); +#else + uint32_t flags; + status_t err = MediaCodecList::getInstance()->getCodecCapabilities(index, type, &profile_levels, &formats, &flags); +#endif ++#if ANDROID_VERSION_MAJOR<5 + if (err != OK) + { + ALOGE("Failed to get the number of supported codec types (err: %d)", err); + return 0; + } ++#endif + + for (size_t i=0; i -+ * Ricardo Salveti de Araujo ++ * Authored by: Simon Fels + */ + -+// Uncomment to enable verbose debug output +#define LOG_NDEBUG 0 -+ +#undef LOG_TAG +#define LOG_TAG "MediaCompatibilityLayer" + -+#include ++#include + -+#include -+#include ++#include + -+#include ++#include ++#include ++#include ++#include ++#include + -+#include -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+#include -+#else -+#include -+#endif ++#include ++#include ++#include ++#include + -+#include -+#include ++#include + -+#include ++#include "media_message_priv.h" ++#include "media_buffer_priv.h" ++#include "media_meta_data_priv.h" + -+#include ++#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__); + -+#include ++struct MediaSourcePrivate : public android::MediaSource ++{ ++public: ++ static MediaSourcePrivate* toPrivate(MediaSourceWrapper *source); + -+#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__) ++ android::status_t start(android::MetaData *params = NULL); ++ android::status_t stop(); ++ android::sp getFormat(); ++ android::status_t read(android::MediaBuffer **buffer, const android::MediaSource::ReadOptions *options = NULL); ++ android::status_t pause(); ++ ++ android::sp format; ++ ++ MediaSourceStartCallback start_callback; ++ void *start_callback_data; ++ MediaSourceStopCallback stop_callback; ++ void *stop_callback_data; ++ MediaSourceReadCallback read_callback; ++ void *read_callback_data; ++ MediaSourcePauseCallback pause_callback; ++ void *pause_callback_data; ++}; + -+namespace android ++MediaSourcePrivate* MediaSourcePrivate::toPrivate(MediaSourceWrapper *source) +{ -+NativeBufferAlloc::NativeBufferAlloc() { -+} ++ if (!source) ++ return NULL; + -+NativeBufferAlloc::~NativeBufferAlloc() { ++ return static_cast(source); +} + -+sp NativeBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h, -+ PixelFormat format, uint32_t usage, status_t* error) { -+ sp graphicBuffer(new GraphicBuffer(w, h, format, usage)); -+ status_t err = graphicBuffer->initCheck(); -+ *error = err; -+ if (err != 0 || graphicBuffer->handle == 0) { -+ if (err == NO_MEMORY) { -+ GraphicBuffer::dumpAllocationsToSystemLog(); -+ } -+ ALOGI("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) " -+ "failed (%s), handle=%p", -+ w, h, strerror(-err), graphicBuffer->handle); -+ return 0; -+ } -+ return graphicBuffer; -+} -+} -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+struct FrameAvailableListener : public android::SurfaceTexture::FrameAvailableListener -+#else -+struct FrameAvailableListener : public android::GLConsumer::FrameAvailableListener -+#endif ++android::status_t MediaSourcePrivate::start(android::MetaData *params) +{ -+ public: -+ FrameAvailableListener() -+ : set_video_texture_needs_update_cb(NULL), -+ video_texture_needs_update_context(NULL) -+ { -+ } ++ if(!start_callback) ++ return android::ERROR_UNSUPPORTED; + -+ // From android::GLConsumer/SurfaceTexture::FrameAvailableListener -+ void onFrameAvailable() -+ { -+ if (set_video_texture_needs_update_cb != NULL) -+ set_video_texture_needs_update_cb(video_texture_needs_update_context); -+ } ++ return start_callback(nullptr, start_callback_data); ++} + -+ void setVideoTextureNeedsUpdateCb(on_video_texture_needs_update cb, void *context) -+ { -+ set_video_texture_needs_update_cb = cb; -+ video_texture_needs_update_context = context; -+ } ++android::status_t MediaSourcePrivate::stop() ++{ ++ if (!stop_callback) ++ return android::ERROR_UNSUPPORTED; + -+ private: -+ on_video_texture_needs_update set_video_texture_needs_update_cb; -+ void *video_texture_needs_update_context; -+}; ++ return stop_callback(stop_callback_data); ++} + -+class MediaPlayerListenerWrapper : public android::MediaPlayerListener ++android::sp MediaSourcePrivate::getFormat() +{ -+ public: -+ MediaPlayerListenerWrapper() -+ : set_video_size_cb(NULL), -+ video_size_context(NULL), -+ error_cb(NULL), -+ error_context(NULL), -+ playback_complete_cb(NULL), -+ playback_complete_context(NULL), -+ media_prepared_cb(NULL), -+ media_prepared_context(NULL) -+ { -+ } ++ return format; ++} + -+ void notify(int msg, int ext1, int ext2, const android::Parcel *obj) -+ { -+ ALOGV("\tmsg: %d, ext1: %d, ext2: %d \n", msg, ext1, ext2); ++android::status_t MediaSourcePrivate::read(android::MediaBuffer **buffer, const android::MediaSource::ReadOptions *options) ++{ ++ (void) options; + -+ switch (msg) { -+ case android::MEDIA_PREPARED: -+ ALOGV("\tMEDIA_PREPARED msg\n"); -+ if (media_prepared_cb != NULL) -+ media_prepared_cb(media_prepared_context); -+ else -+ ALOGW("Failed to signal media prepared, callback not set."); -+ break; -+ case android::MEDIA_PLAYBACK_COMPLETE: -+ ALOGV("\tMEDIA_PLAYBACK_COMPLETE msg\n"); -+ if (playback_complete_cb != NULL) -+ playback_complete_cb(playback_complete_context); -+ else -+ ALOGW("Failed to signal end of playback, callback not set."); -+ break; -+ case android::MEDIA_BUFFERING_UPDATE: -+ ALOGV("\tMEDIA_BUFFERING_UPDATE msg\n"); -+ break; -+ case android::MEDIA_SEEK_COMPLETE: -+ ALOGV("\tMEDIA_SEEK_COMPLETE msg\n"); -+ break; -+ case android::MEDIA_SET_VIDEO_SIZE: -+ ALOGV("\tMEDIA_SET_VIDEO_SIZE msg\n"); -+ if (set_video_size_cb != NULL) -+ set_video_size_cb(ext2, ext1, video_size_context); -+ else -+ ALOGE("Failed to set video size. set_video_size_cb is NULL."); -+ break; -+ case android::MEDIA_TIMED_TEXT: -+ ALOGV("\tMEDIA_TIMED_TEXT msg\n"); -+ break; -+ case android::MEDIA_ERROR: -+ ALOGV("\tMEDIA_ERROR msg\n"); -+ // TODO: Extend this cb to include the error message -+ if (error_cb != NULL) -+ error_cb(error_context); -+ else -+ ALOGE("Failed to signal error to app layer, callback not set."); -+ break; -+ case android::MEDIA_INFO: -+ ALOGV("\tMEDIA_INFO msg\n"); -+ break; -+ default: -+ ALOGV("\tUnknown media msg\n"); -+ } -+ } ++ if (!read_callback) ++ return android::ERROR_UNSUPPORTED; + -+ void setVideoSizeCb(on_msg_set_video_size cb, void *context) -+ { -+ REPORT_FUNCTION(); ++ MediaBufferPrivate *buf = NULL; + -+ set_video_size_cb = cb; -+ video_size_context = context; -+ } ++ int err = read_callback(reinterpret_cast(&buf), read_callback_data); ++ if (!buf) ++ return err; + -+ void setErrorCb(on_msg_error cb, void *context) -+ { -+ REPORT_FUNCTION(); ++ *buffer = buf->buffer; + -+ error_cb = cb; -+ error_context = context; -+ } ++ return err; ++} + -+ void setPlaybackCompleteCb(on_playback_complete cb, void *context) -+ { -+ REPORT_FUNCTION(); ++android::status_t MediaSourcePrivate::pause() ++{ ++ if (!pause_callback) ++ return android::ERROR_UNSUPPORTED; + -+ playback_complete_cb = cb; -+ playback_complete_context = context; -+ } ++ return pause_callback(pause_callback_data); ++} + -+ void setMediaPreparedCb(on_media_prepared cb, void *context) -+ { -+ REPORT_FUNCTION(); ++MediaSourceWrapper* media_source_create(void) ++{ ++ MediaSourcePrivate *d = new MediaSourcePrivate; ++ if (!d) ++ return NULL; + -+ media_prepared_cb = cb; -+ media_prepared_context = context; -+ } ++ return d; ++} + -+ private: -+ on_msg_set_video_size set_video_size_cb; -+ void *video_size_context; -+ on_msg_error error_cb; -+ void *error_context; -+ on_playback_complete playback_complete_cb; -+ void *playback_complete_context; -+ on_media_prepared media_prepared_cb; -+ void *media_prepared_context; -+}; ++void media_source_release(MediaSourceWrapper *source) ++{ ++ MediaSourcePrivate *d = MediaSourcePrivate::toPrivate(source); ++ if (!d) ++ return; + -+// ----- MediaPlayer Wrapper ----- // ++ delete d; ++} + -+struct MediaPlayerWrapper : public android::MediaPlayer ++void media_source_set_format(MediaSourceWrapper *source, MediaMetaDataWrapper *meta) +{ -+ public: -+ MediaPlayerWrapper() -+ : MediaPlayer(), -+ texture(NULL), -+ media_player_listener(new MediaPlayerListenerWrapper()), -+ frame_listener(new FrameAvailableListener), -+ left_volume(1), // Set vol to 100% for this track by default -+ right_volume(1), -+ source_fd(-1) -+ { -+ setListener(media_player_listener); -+ // Update the live volume with the cached values -+ MediaPlayer::setVolume(left_volume, right_volume); -+ } ++ MediaSourcePrivate *d = MediaSourcePrivate::toPrivate(source); ++ if (!d) ++ return; + -+ ~MediaPlayerWrapper() -+ { -+ reset(); -+ source_fd = -1; -+ } ++ auto dm = MediaMetaDataPrivate::toPrivate(meta); ++ if (!dm) ++ return; + -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+ android::status_t setVideoSurfaceTexture(const android::sp &surfaceTexture) -+#else -+ android::status_t setVideoSurfaceTexture(android::sp bq, const android::sp &surfaceTexture) -+#endif -+ { -+ REPORT_FUNCTION(); ++ d->format = dm->data; ++} + -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+ surfaceTexture->getBufferQueue()->setBufferCount(5); -+#else -+ bq->setBufferCount(5); -+#endif -+ texture = surfaceTexture; -+ texture->setFrameAvailableListener(frame_listener); ++void media_source_set_start_callback(MediaSourceWrapper *source, MediaSourceStartCallback callback, void *user_data) ++{ ++ MediaSourcePrivate *d = MediaSourcePrivate::toPrivate(source); ++ if (!d) ++ return; + -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+ return MediaPlayer::setVideoSurfaceTexture(surfaceTexture->getBufferQueue()); -+#else -+ return MediaPlayer::setVideoSurfaceTexture(bq); -+#endif -+ } ++ d->start_callback = callback; ++ d->start_callback_data = user_data; ++} + -+ void updateGLConsumer() -+ { -+ assert(texture != NULL); -+ texture->updateTexImage(); -+ } ++void media_source_set_stop_callback(MediaSourceWrapper *source, MediaSourceStopCallback callback, void *user_data) ++{ ++ MediaSourcePrivate *d = MediaSourcePrivate::toPrivate(source); ++ if (!d) ++ return; + -+ void get_transformation_matrix_for_surface_texture(GLfloat* matrix) -+ { -+ assert(texture != NULL); -+ texture->getTransformMatrix(matrix); -+ } ++ d->stop_callback = callback; ++ d->stop_callback_data = user_data; ++} + -+ void setVideoSizeCb(on_msg_set_video_size cb, void *context) -+ { -+ REPORT_FUNCTION(); ++void media_source_set_read_callback(MediaSourceWrapper *source, MediaSourceReadCallback callback, void *user_data) ++{ ++ MediaSourcePrivate *d = MediaSourcePrivate::toPrivate(source); ++ if (!d) ++ return; + -+ assert(media_player_listener != NULL); -+ media_player_listener->setVideoSizeCb(cb, context); -+ } ++ d->read_callback = callback; ++ d->read_callback_data = user_data; ++} + -+ void setVideoTextureNeedsUpdateCb(on_video_texture_needs_update cb, void *context) -+ { -+ REPORT_FUNCTION(); ++void media_source_set_pause_callback(MediaSourceWrapper *source, MediaSourcePauseCallback callback, void *user_data) ++{ ++ MediaSourcePrivate *d = MediaSourcePrivate::toPrivate(source); ++ if (!d) ++ return; + -+ assert(frame_listener != NULL); -+ frame_listener->setVideoTextureNeedsUpdateCb(cb, context); -+ } ++ d->pause_callback = callback; ++ d->pause_callback_data = user_data; ++} + -+ void setErrorCb(on_msg_error cb, void *context) -+ { -+ REPORT_FUNCTION(); ++struct MediaCodecSourcePrivate : public android::AHandler ++{ ++public: ++ static MediaCodecSourcePrivate* toPrivate(MediaCodecSourceWrapper *source); + -+ assert(media_player_listener != NULL); -+ media_player_listener->setErrorCb(cb, context); -+ } ++ explicit MediaCodecSourcePrivate(void *context); ++ virtual ~MediaCodecSourcePrivate(); + -+ void setPlaybackCompleteCb(on_playback_complete cb, void *context) -+ { -+ REPORT_FUNCTION(); ++protected: ++ virtual void onMessageReceived(const android::sp &msg); + -+ assert(media_player_listener != NULL); -+ media_player_listener->setPlaybackCompleteCb(cb, context); -+ } ++public: ++ void *context; ++ unsigned int refcount; ++ android::sp looper; ++ android::sp codec; ++ android::sp input_surface; ++ android::sp source; ++}; + -+ void setMediaPreparedCb(on_media_prepared cb, void *context) -+ { -+ REPORT_FUNCTION(); ++MediaCodecSourcePrivate* MediaCodecSourcePrivate::toPrivate(MediaCodecSourceWrapper *source) ++{ ++ if (!source) ++ return NULL; + -+ assert(media_player_listener != NULL); -+ media_player_listener->setMediaPreparedCb(cb, context); -+ } ++ return static_cast(source); ++} + -+ void getVolume(float *leftVolume, float *rightVolume) -+ { -+ *leftVolume = left_volume; -+ *rightVolume = right_volume; -+ } ++MediaCodecSourcePrivate::MediaCodecSourcePrivate(void *context) : ++ context(context), ++ refcount(1) ++{ ++ REPORT_FUNCTION(); ++} + -+ android::status_t setVolume(float leftVolume, float rightVolume) -+ { -+ REPORT_FUNCTION(); ++MediaCodecSourcePrivate::~MediaCodecSourcePrivate() ++{ ++ REPORT_FUNCTION(); ++} + -+ left_volume = leftVolume; -+ right_volume = rightVolume; -+ return MediaPlayer::setVolume(leftVolume, rightVolume); -+ } ++void MediaCodecSourcePrivate::onMessageReceived(const android::sp &msg) ++{ ++ (void) msg; ++} + -+ int getSourceFd() const { return source_fd; } -+ void setSourceFd(int fd) { source_fd = fd; } ++MediaCodecSourceWrapper* media_codec_source_create(MediaMessageWrapper *format, MediaSourceWrapper *source, int flags) ++{ ++ if (!format) ++ return NULL; + -+ private: -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+ android::sp texture; ++ MediaCodecSourcePrivate *d = new MediaCodecSourcePrivate(NULL); ++ if (!d) ++ return NULL; ++ ++ d->looper = new android::ALooper(); ++ d->looper->start(); ++ ++ d->source = MediaSourcePrivate::toPrivate(source); ++ ++ MediaMessagePrivate *dm = MediaMessagePrivate::toPrivate(format); ++ ++ ALOGV("Creating media codec source"); ++#if ANDROID_VERSION_MAJOR>=6 ++ // We don't use persistent input surface ++ d->codec = android::MediaCodecSource::Create(d->looper, dm->msg, d->source, NULL, flags); +#else -+ android::sp texture; ++ d->codec = android::MediaCodecSource::Create(d->looper, dm->msg, d->source, flags); +#endif -+ android::sp media_player_listener; -+ android::sp frame_listener; -+ float left_volume; -+ float right_volume; -+ int source_fd; -+}; // MediaPlayerWrapper + -+using namespace android; -+ -+// ----- Media Player C API Implementation ----- // ++ return d; ++} + -+void android_media_set_video_size_cb(MediaPlayerWrapper *mp, on_msg_set_video_size cb, void *context) ++void media_codec_source_release(MediaCodecSourceWrapper *source) +{ -+ REPORT_FUNCTION(); -+ -+ if (mp == NULL) { -+ ALOGE("mp must not be NULL"); -+ return; -+ } ++ MediaCodecSourcePrivate *d = MediaCodecSourcePrivate::toPrivate(source); ++ if (!d) ++ return; + -+ mp->setVideoSizeCb(cb, context); ++ delete d; +} + -+void android_media_set_video_texture_needs_update_cb(MediaPlayerWrapper *mp, on_video_texture_needs_update cb, void *context) ++MediaNativeWindowHandle* media_codec_source_get_native_window_handle(MediaCodecSourceWrapper *source) +{ -+ REPORT_FUNCTION(); ++ MediaCodecSourcePrivate *d = MediaCodecSourcePrivate::toPrivate(source); ++ if (!d) ++ return NULL; + -+ if (mp == NULL) { -+ ALOGE("mp must not be NULL"); -+ return; -+ } ++ if (!d->input_surface.get()) ++ d->input_surface = new android::Surface(d->codec->getGraphicBufferProducer()); + -+ mp->setVideoTextureNeedsUpdateCb(cb, context); ++ return static_cast(d->input_surface.get()); +} + -+void android_media_set_error_cb(MediaPlayerWrapper *mp, on_msg_error cb, void *context) ++MediaMetaDataWrapper* media_codec_source_get_format(MediaCodecSourceWrapper *source) +{ -+ REPORT_FUNCTION(); -+ -+ if (mp == NULL) { -+ ALOGE("mp must not be NULL"); -+ return; -+ } ++ MediaCodecSourcePrivate *d = MediaCodecSourcePrivate::toPrivate(source); ++ if (!d) ++ return NULL; + -+ mp->setErrorCb(cb, context); ++ return new MediaMetaDataPrivate(d->codec->getFormat()); +} + -+void android_media_set_playback_complete_cb(MediaPlayerWrapper *mp, on_playback_complete cb, void *context) ++bool media_codec_source_start(MediaCodecSourceWrapper *source) +{ -+ REPORT_FUNCTION(); ++ MediaCodecSourcePrivate *d = MediaCodecSourcePrivate::toPrivate(source); ++ if (!d) ++ return false; + -+ if (mp == NULL) { -+ ALOGE("mp must not be NULL"); -+ return; -+ } ++ android::status_t err = d->codec->start(NULL); ++ if (err != android::OK) ++ return false; + -+ mp->setPlaybackCompleteCb(cb, context); ++ return true; +} + -+void android_media_set_media_prepared_cb(MediaPlayerWrapper *mp, on_media_prepared cb, void *context) ++bool media_codec_source_stop(MediaCodecSourceWrapper *source) +{ -+ REPORT_FUNCTION(); ++ MediaCodecSourcePrivate *d = MediaCodecSourcePrivate::toPrivate(source); ++ if (!d) ++ return false; + -+ if (mp == NULL) { -+ ALOGE("mp must not be NULL"); -+ return; -+ } ++ android::status_t err = d->codec->stop(); ++ if (err != android::OK) ++ return false; + -+ mp->setMediaPreparedCb(cb, context); ++ return true; +} + -+MediaPlayerWrapper *android_media_new_player() ++bool media_codec_source_pause(MediaCodecSourceWrapper *source) +{ -+ REPORT_FUNCTION(); -+ -+ MediaPlayerWrapper *mp = new MediaPlayerWrapper(); -+ if (mp == NULL) { -+ ALOGE("Failed to create new MediaPlayerWrapper instance."); -+ return NULL; -+ } ++ MediaCodecSourcePrivate *d = MediaCodecSourcePrivate::toPrivate(source); ++ if (!d) ++ return false; + -+ // Required for internal player state processing. Without this, prepare() and start() hang. -+ ProcessState::self()->startThreadPool(); ++ android::status_t err = d->codec->pause(); ++ if (err != android::OK) ++ return false; + -+ return mp; ++ return true; +} + -+int android_media_set_data_source(MediaPlayerWrapper *mp, const char* url) ++bool media_codec_source_read(MediaCodecSourceWrapper *source, MediaBufferWrapper **buffer) +{ -+ REPORT_FUNCTION(); ++ MediaCodecSourcePrivate *d = MediaCodecSourcePrivate::toPrivate(source); ++ if (!d) ++ return false; + -+ if (mp == NULL) { -+ ALOGE("mp must not be NULL"); -+ return BAD_VALUE; -+ } ++ android::MediaBuffer *buff = NULL; ++ android::status_t err = d->codec->read(&buff); ++ if (err != android::OK) ++ return false; + -+ if (url == NULL) { -+ ALOGE("url must not be NULL"); -+ return BAD_VALUE; -+ } ++ *buffer = new MediaBufferPrivate(buff); + -+ ALOGD("url: %s", url); ++ return true; ++} + -+ String16 src(url); -+ if (src.startsWith(String16("http://")) == true) { -+ ALOGD("HTTP source URL detected"); -+ mp->setDataSource(url, NULL); -+ } else { -+ ALOGD("File source URL detected"); -+ int fd = open(url, O_RDONLY); -+ if (fd < 0) -+ { -+ ALOGE("Failed to open source data at: %s\n", url); -+ return BAD_VALUE; -+ } ++bool media_codec_source_request_idr_frame(MediaCodecSourceWrapper *source) ++{ ++ MediaCodecSourcePrivate *d = MediaCodecSourcePrivate::toPrivate(source); ++ if (!d || !d->codec.get()) ++ return false; + -+ mp->setSourceFd(fd); -+ -+ struct stat st; -+ stat(url, &st); -+ -+ ALOGD("source file length: %lld\n", st.st_size); -+ -+ mp->setDataSource(fd, 0, st.st_size); -+ } -+ mp->prepare(); -+ -+ return OK; -+} -+ -+int android_media_set_preview_texture(MediaPlayerWrapper *mp, int texture_id) -+{ -+ REPORT_FUNCTION(); -+ -+ if (mp == NULL) { -+ ALOGE("mp must not be NULL"); -+ return BAD_VALUE; -+ } -+ -+ android::sp native_alloc( -+ new android::NativeBufferAlloc() -+ ); -+ -+ android::sp buffer_queue( -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 -+ new android::BufferQueue(false, NULL, native_alloc) -+#else -+ new android::BufferQueue(NULL) -+#endif -+ ); -+ -+ static const bool allow_synchronous_mode = true; -+ // Create a new GLConsumer/SurfaceTexture from the texture_id in synchronous mode (don't wait on all data in the buffer) -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+ mp->setVideoSurfaceTexture(android::sp( -+ new android::SurfaceTexture( -+#else -+ mp->setVideoSurfaceTexture(buffer_queue, android::sp( -+ new android::GLConsumer( -+#endif -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 -+ texture_id, -+ allow_synchronous_mode, -+ GL_TEXTURE_EXTERNAL_OES, -+ true, -+ buffer_queue))); -+#else -+ buffer_queue, -+ texture_id, -+ GL_TEXTURE_EXTERNAL_OES, -+ true, -+ false))); -+#endif -+ -+ return OK; -+} -+ -+void android_media_update_surface_texture(MediaPlayerWrapper *mp) -+{ -+ if (mp == NULL) { -+ ALOGE("mp must not be NULL"); -+ return; -+ } -+ -+ mp->updateGLConsumer(); -+} -+ -+void android_media_surface_texture_get_transformation_matrix(MediaPlayerWrapper *mp, GLfloat* matrix) -+{ -+ if (mp == NULL) { -+ ALOGE("mp must not be NULL"); -+ return; -+ } -+ -+ mp->get_transformation_matrix_for_surface_texture(matrix); -+} -+ -+int android_media_play(MediaPlayerWrapper *mp) -+{ -+ REPORT_FUNCTION(); -+ -+ if (mp == NULL) { -+ ALOGE("mp must not be NULL"); -+ return BAD_VALUE; -+ } -+ -+ mp->start(); -+ const char *tmp = mp->isPlaying() ? "yes" : "no"; -+ ALOGV("Is playing?: %s\n", tmp); -+ -+ return OK; -+} -+ -+int android_media_pause(MediaPlayerWrapper *mp) -+{ -+ REPORT_FUNCTION(); -+ -+ if (mp == NULL) { -+ ALOGE("mp must not be NULL"); -+ return BAD_VALUE; -+ } -+ -+ mp->pause(); -+ -+ return OK; -+} -+ -+int android_media_stop(MediaPlayerWrapper *mp) -+{ -+ REPORT_FUNCTION(); -+ -+ if (mp == NULL) { -+ ALOGE("mp must not be NULL"); -+ return BAD_VALUE; -+ } -+ -+ mp->stop(); -+ -+ int fd = mp->getSourceFd(); -+ if (fd > -1) -+ close(fd); -+ -+ return OK; -+} -+ -+bool android_media_is_playing(MediaPlayerWrapper *mp) -+{ -+ if (mp != NULL) { -+ if (mp->isPlaying()) -+ return true; -+ } -+ -+ return false; -+} -+ -+int android_media_seek_to(MediaPlayerWrapper *mp, int msec) -+{ -+ REPORT_FUNCTION(); -+ -+ if (mp == NULL) { -+ ALOGE("mp must not be NULL"); -+ return BAD_VALUE; -+ } -+ -+ return mp->seekTo(msec); -+} -+ -+int android_media_get_current_position(MediaPlayerWrapper *mp, int *msec) -+{ -+ if (mp == NULL) { -+ ALOGE("mp must not be NULL"); -+ return BAD_VALUE; -+ } -+ -+ return mp->getCurrentPosition(msec); -+} -+ -+int android_media_get_duration(MediaPlayerWrapper *mp, int *msec) -+{ -+ REPORT_FUNCTION(); -+ -+ if (mp == NULL) { -+ ALOGE("mp must not be NULL"); -+ return BAD_VALUE; -+ } -+ -+ return mp->getDuration(msec); -+} -+ -+int android_media_get_volume(MediaPlayerWrapper *mp, int *volume) -+{ -+ REPORT_FUNCTION(); -+ -+ if (volume == NULL) { -+ ALOGE("volume must not be NULL"); -+ return BAD_VALUE; -+ } -+ -+ if (mp == NULL) { -+ ALOGE("mp must not be NULL"); -+ return BAD_VALUE; -+ } -+ -+ float left_volume = 0, right_volume = 0; -+ mp->getVolume(&left_volume, &right_volume); -+ *volume = left_volume * 100; -+ -+ return OK; -+} -+ -+int android_media_set_volume(MediaPlayerWrapper *mp, int volume) -+{ -+ REPORT_FUNCTION(); -+ -+ if (mp == NULL) { -+ ALOGE("mp must not be NULL"); -+ return BAD_VALUE; -+ } ++ android::status_t err = d->codec->requestIDRFrame(); ++ if (err != android::OK) ++ return false; + -+ float left_volume = float(volume / 100); -+ float right_volume = float(volume / 100); -+ return mp->setVolume(left_volume, right_volume); ++ return true; +} --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_format_layer.cpp -@@ -0,0 +1,245 @@ ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_compatibility_layer.cpp +@@ -0,0 +1,690 @@ +/* + * Copyright (C) 2013 Canonical Ltd + * @@ -5477,1386 +6068,1305 @@ + * limitations under the License. + * + * Authored by: Jim Hodapp ++ * Ricardo Salveti de Araujo + */ + +// Uncomment to enable verbose debug output +#define LOG_NDEBUG 0 + +#undef LOG_TAG -+#define LOG_TAG "MediaFormatLayer" -+ -+#include -+#include "media_format_layer_priv.h" ++#define LOG_TAG "MediaCompatibilityLayer" + -+#include ++#include + -+#include ++#include ++#include + -+#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__); ++#include + -+using namespace android; ++#include ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++#include ++#else ++#include ++#endif + -+static inline _MediaFormat *get_internal_format(MediaFormat format) -+{ -+ if (format == NULL) -+ { -+ ALOGE("format must not be NULL"); -+ return NULL; -+ } ++#include ++#include + -+ _MediaFormat *mf = static_cast<_MediaFormat*>(format); -+ assert(mf->refcount >= 1); ++#include + -+ return mf; -+} ++#include + -+MediaFormat media_format_create_video_format(const char *mime, int32_t width, int32_t height, int64_t duration_us, int32_t max_input_size) -+{ -+ REPORT_FUNCTION() ++#include + -+ _MediaFormat *format = new _MediaFormat(); -+ format->mime = AString(mime); -+ format->width = width; -+ format->height = height; -+ format->duration_us = duration_us; -+ format->max_input_size = max_input_size; ++#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__) + -+ return format; ++namespace android ++{ ++NativeBufferAlloc::NativeBufferAlloc() { +} + -+void media_format_destroy(MediaFormat format) ++NativeBufferAlloc::~NativeBufferAlloc() { ++} ++ ++sp NativeBufferAlloc::createGraphicBuffer(uint32_t w, uint32_t h, ++ PixelFormat format, uint32_t usage, status_t* error) { ++ sp graphicBuffer(new GraphicBuffer(w, h, format, usage)); ++ status_t err = graphicBuffer->initCheck(); ++ *error = err; ++ if (err != 0 || graphicBuffer->handle == 0) { ++ if (err == NO_MEMORY) { ++ GraphicBuffer::dumpAllocationsToSystemLog(); ++ } ++ ALOGI("GraphicBufferAlloc::createGraphicBuffer(w=%d, h=%d) " ++ "failed (%s), handle=%p", ++ w, h, strerror(-err), graphicBuffer->handle); ++ return 0; ++ } ++ return graphicBuffer; ++} ++} ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++struct FrameAvailableListener : public android::SurfaceTexture::FrameAvailableListener ++#else ++struct FrameAvailableListener : public android::GLConsumer::FrameAvailableListener ++#endif +{ -+ REPORT_FUNCTION() ++ public: ++ FrameAvailableListener() ++ : set_video_texture_needs_update_cb(NULL), ++ video_texture_needs_update_context(NULL) ++ { ++ } + -+ _MediaFormat *mf = get_internal_format(format); -+ if (mf == NULL) -+ return; ++ // From android::GLConsumer/SurfaceTexture::FrameAvailableListener ++#if ANDROID_VERSION_MAJOR==5 && ANDROID_VERSION_MINOR>=1 || ANDROID_VERSION_MAJOR>=6 ++ virtual void onFrameAvailable(const android::BufferItem& item) ++#else ++ virtual void onFrameAvailable() ++#endif ++ { ++ if (set_video_texture_needs_update_cb != NULL) ++ set_video_texture_needs_update_cb(video_texture_needs_update_context); ++ } + -+ if (mf->refcount) -+ return; ++ void setVideoTextureNeedsUpdateCb(on_video_texture_needs_update cb, void *context) ++ { ++ set_video_texture_needs_update_cb = cb; ++ video_texture_needs_update_context = context; ++ } + -+ delete mf; -+} ++ private: ++ on_video_texture_needs_update set_video_texture_needs_update_cb; ++ void *video_texture_needs_update_context; ++}; + -+void media_format_ref(MediaFormat format) ++class MediaPlayerListenerWrapper : public android::MediaPlayerListener +{ -+ REPORT_FUNCTION() ++ public: ++ MediaPlayerListenerWrapper() ++ : set_video_size_cb(NULL), ++ video_size_context(NULL), ++ error_cb(NULL), ++ error_context(NULL), ++ playback_complete_cb(NULL), ++ playback_complete_context(NULL), ++ media_prepared_cb(NULL), ++ media_prepared_context(NULL) ++ { ++ } + -+ _MediaFormat *mf = get_internal_format(format); -+ if (mf == NULL) -+ return; ++ void notify(int msg, int ext1, int ext2, const android::Parcel *obj) ++ { ++ ALOGV("\tmsg: %d, ext1: %d, ext2: %d \n", msg, ext1, ext2); + -+ mf->refcount++; -+} ++ switch (msg) { ++ case android::MEDIA_PREPARED: ++ ALOGV("\tMEDIA_PREPARED msg\n"); ++ if (media_prepared_cb != NULL) ++ media_prepared_cb(media_prepared_context); ++ else ++ ALOGW("Failed to signal media prepared, callback not set."); ++ break; ++ case android::MEDIA_PLAYBACK_COMPLETE: ++ ALOGV("\tMEDIA_PLAYBACK_COMPLETE msg\n"); ++ if (playback_complete_cb != NULL) ++ playback_complete_cb(playback_complete_context); ++ else ++ ALOGW("Failed to signal end of playback, callback not set."); ++ break; ++ case android::MEDIA_BUFFERING_UPDATE: ++ ALOGV("\tMEDIA_BUFFERING_UPDATE msg\n"); ++ break; ++ case android::MEDIA_SEEK_COMPLETE: ++ ALOGV("\tMEDIA_SEEK_COMPLETE msg\n"); ++ break; ++ case android::MEDIA_SET_VIDEO_SIZE: ++ ALOGV("\tMEDIA_SET_VIDEO_SIZE msg\n"); ++ if (set_video_size_cb != NULL) ++ set_video_size_cb(ext2, ext1, video_size_context); ++ else ++ ALOGE("Failed to set video size. set_video_size_cb is NULL."); ++ break; ++ case android::MEDIA_TIMED_TEXT: ++ ALOGV("\tMEDIA_TIMED_TEXT msg\n"); ++ break; ++ case android::MEDIA_ERROR: ++ ALOGV("\tMEDIA_ERROR msg\n"); ++ // TODO: Extend this cb to include the error message ++ if (error_cb != NULL) ++ error_cb(error_context); ++ else ++ ALOGE("Failed to signal error to app layer, callback not set."); ++ break; ++ case android::MEDIA_INFO: ++ ALOGV("\tMEDIA_INFO msg\n"); ++ break; ++ default: ++ ALOGV("\tUnknown media msg\n"); ++ } ++ } + -+void media_format_unref(MediaFormat format) -+{ -+ REPORT_FUNCTION() ++ void setVideoSizeCb(on_msg_set_video_size cb, void *context) ++ { ++ REPORT_FUNCTION(); + -+ _MediaFormat *mf = get_internal_format(format); -+ if (mf == NULL) -+ return; ++ set_video_size_cb = cb; ++ video_size_context = context; ++ } + -+ if (mf->refcount) -+ mf->refcount--; -+} ++ void setErrorCb(on_msg_error cb, void *context) ++ { ++ REPORT_FUNCTION(); + -+void media_format_set_byte_buffer(MediaFormat format, const char *key, uint8_t *data, size_t size) -+{ -+ REPORT_FUNCTION() ++ error_cb = cb; ++ error_context = context; ++ } + -+ _MediaFormat *mf = get_internal_format(format); -+ if (mf == NULL) -+ return; -+ if (key == NULL || data == NULL || size == 0) -+ return; ++ void setPlaybackCompleteCb(on_playback_complete cb, void *context) ++ { ++ REPORT_FUNCTION(); + -+ mf->csd_key_name = AString(key); -+ mf->csd = sp(new ABuffer(data, size)); -+} ++ playback_complete_cb = cb; ++ playback_complete_context = context; ++ } + -+const char* media_format_get_mime(MediaFormat format) -+{ -+ REPORT_FUNCTION() ++ void setMediaPreparedCb(on_media_prepared cb, void *context) ++ { ++ REPORT_FUNCTION(); + -+ _MediaFormat *mf = get_internal_format(format); -+ if (mf == NULL) -+ return NULL; ++ media_prepared_cb = cb; ++ media_prepared_context = context; ++ } + -+ return mf->mime.c_str(); -+} ++ private: ++ on_msg_set_video_size set_video_size_cb; ++ void *video_size_context; ++ on_msg_error error_cb; ++ void *error_context; ++ on_playback_complete playback_complete_cb; ++ void *playback_complete_context; ++ on_media_prepared media_prepared_cb; ++ void *media_prepared_context; ++}; + -+int64_t media_format_get_duration_us(MediaFormat format) ++// ----- MediaPlayer Wrapper ----- // ++ ++struct MediaPlayerWrapper : public android::MediaPlayer +{ -+ REPORT_FUNCTION() ++ public: ++ MediaPlayerWrapper() ++ : MediaPlayer(), ++ texture(NULL), ++ media_player_listener(new MediaPlayerListenerWrapper()), ++ frame_listener(new FrameAvailableListener), ++ left_volume(1), // Set vol to 100% for this track by default ++ right_volume(1), ++ source_fd(-1) ++ { ++ setListener(media_player_listener); ++ // Update the live volume with the cached values ++ MediaPlayer::setVolume(left_volume, right_volume); ++ } + -+ _MediaFormat *mf = get_internal_format(format); -+ if (mf == NULL) -+ return 0; ++ ~MediaPlayerWrapper() ++ { ++ reset(); ++ source_fd = -1; ++ } + -+ return mf->duration_us; -+} ++#if ANDROID_VERSION_MAJOR>=5 ++ android::status_t setVideoSurfaceTexture(android::sp bq, const android::sp &surfaceTexture) ++#elif ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++ android::status_t setVideoSurfaceTexture(const android::sp &surfaceTexture) ++#else ++ android::status_t setVideoSurfaceTexture(android::sp bq, const android::sp &surfaceTexture) ++#endif ++ { ++ REPORT_FUNCTION(); + -+int32_t media_format_get_width(MediaFormat format) -+{ -+ REPORT_FUNCTION() ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++ surfaceTexture->getBufferQueue()->setBufferCount(5); ++#else ++ bq->setBufferCount(5); ++#endif ++ texture = surfaceTexture; ++ texture->setFrameAvailableListener(frame_listener); + -+ _MediaFormat *mf = get_internal_format(format); -+ if (mf == NULL) -+ return 0; ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++ return MediaPlayer::setVideoSurfaceTexture(surfaceTexture->getBufferQueue()); ++#else ++ return MediaPlayer::setVideoSurfaceTexture(bq); ++#endif ++ } + -+ return mf->width; -+} ++ void updateGLConsumer() ++ { ++ assert(texture != NULL); ++ texture->updateTexImage(); ++ } + -+int32_t media_format_get_height(MediaFormat format) -+{ -+ REPORT_FUNCTION() ++ void get_transformation_matrix_for_surface_texture(GLfloat* matrix) ++ { ++ assert(texture != NULL); ++ texture->getTransformMatrix(matrix); ++ } + -+ _MediaFormat *mf = get_internal_format(format); -+ if (mf == NULL) -+ return 0; ++ void setVideoSizeCb(on_msg_set_video_size cb, void *context) ++ { ++ REPORT_FUNCTION(); + -+ return mf->height; -+} ++ assert(media_player_listener != NULL); ++ media_player_listener->setVideoSizeCb(cb, context); ++ } + -+int32_t media_format_get_max_input_size(MediaFormat format) -+{ -+ REPORT_FUNCTION() ++ void setVideoTextureNeedsUpdateCb(on_video_texture_needs_update cb, void *context) ++ { ++ REPORT_FUNCTION(); + -+ _MediaFormat *mf = get_internal_format(format); -+ if (mf == NULL) -+ return 0; ++ assert(frame_listener != NULL); ++ frame_listener->setVideoTextureNeedsUpdateCb(cb, context); ++ } + -+ return mf->max_input_size; -+} ++ void setErrorCb(on_msg_error cb, void *context) ++ { ++ REPORT_FUNCTION(); + -+int32_t media_format_get_stride(MediaFormat format) -+{ -+ REPORT_FUNCTION() ++ assert(media_player_listener != NULL); ++ media_player_listener->setErrorCb(cb, context); ++ } + -+ _MediaFormat *mf = get_internal_format(format); -+ if (mf == NULL) -+ return 0; ++ void setPlaybackCompleteCb(on_playback_complete cb, void *context) ++ { ++ REPORT_FUNCTION(); + -+ return mf->stride; -+} ++ assert(media_player_listener != NULL); ++ media_player_listener->setPlaybackCompleteCb(cb, context); ++ } + -+int32_t media_format_get_slice_height(MediaFormat format) ++ void setMediaPreparedCb(on_media_prepared cb, void *context) ++ { ++ REPORT_FUNCTION(); ++ ++ assert(media_player_listener != NULL); ++ media_player_listener->setMediaPreparedCb(cb, context); ++ } ++ ++ void getVolume(float *leftVolume, float *rightVolume) ++ { ++ *leftVolume = left_volume; ++ *rightVolume = right_volume; ++ } ++ ++ android::status_t setVolume(float leftVolume, float rightVolume) ++ { ++ REPORT_FUNCTION(); ++ ++ left_volume = leftVolume; ++ right_volume = rightVolume; ++ return MediaPlayer::setVolume(leftVolume, rightVolume); ++ } ++ ++ int getSourceFd() const { return source_fd; } ++ void setSourceFd(int fd) { source_fd = fd; } ++ ++ private: ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++ android::sp texture; ++#else ++ android::sp texture; ++#endif ++ android::sp media_player_listener; ++ android::sp frame_listener; ++ float left_volume; ++ float right_volume; ++ int source_fd; ++}; // MediaPlayerWrapper ++ ++using namespace android; ++ ++// ----- Media Player C API Implementation ----- // ++ ++void android_media_set_video_size_cb(MediaPlayerWrapper *mp, on_msg_set_video_size cb, void *context) +{ -+ REPORT_FUNCTION() ++ REPORT_FUNCTION(); + -+ _MediaFormat *mf = get_internal_format(format); -+ if (mf == NULL) -+ return 0; ++ if (mp == NULL) { ++ ALOGE("mp must not be NULL"); ++ return; ++ } + -+ return mf->height; ++ mp->setVideoSizeCb(cb, context); +} + -+int32_t media_format_get_color_format(MediaFormat format) ++void android_media_set_video_texture_needs_update_cb(MediaPlayerWrapper *mp, on_video_texture_needs_update cb, void *context) +{ -+ REPORT_FUNCTION() ++ REPORT_FUNCTION(); + -+ _MediaFormat *mf = get_internal_format(format); -+ if (mf == NULL) -+ return 0; ++ if (mp == NULL) { ++ ALOGE("mp must not be NULL"); ++ return; ++ } + -+ return mf->color_format; ++ mp->setVideoTextureNeedsUpdateCb(cb, context); +} + -+int32_t media_format_get_crop_left(MediaFormat format) ++void android_media_set_error_cb(MediaPlayerWrapper *mp, on_msg_error cb, void *context) +{ -+ REPORT_FUNCTION() ++ REPORT_FUNCTION(); + -+ _MediaFormat *mf = get_internal_format(format); -+ if (mf == NULL) -+ return 0; ++ if (mp == NULL) { ++ ALOGE("mp must not be NULL"); ++ return; ++ } + -+ return mf->crop_left; ++ mp->setErrorCb(cb, context); +} + -+int32_t media_format_get_crop_right(MediaFormat format) ++void android_media_set_playback_complete_cb(MediaPlayerWrapper *mp, on_playback_complete cb, void *context) +{ -+ REPORT_FUNCTION() ++ REPORT_FUNCTION(); + -+ _MediaFormat *mf = get_internal_format(format); -+ if (mf == NULL) -+ return 0; ++ if (mp == NULL) { ++ ALOGE("mp must not be NULL"); ++ return; ++ } + -+ return mf->crop_right; ++ mp->setPlaybackCompleteCb(cb, context); +} + -+int32_t media_format_get_crop_top(MediaFormat format) ++void android_media_set_media_prepared_cb(MediaPlayerWrapper *mp, on_media_prepared cb, void *context) +{ -+ REPORT_FUNCTION() ++ REPORT_FUNCTION(); + -+ _MediaFormat *mf = get_internal_format(format); -+ if (mf == NULL) -+ return 0; ++ if (mp == NULL) { ++ ALOGE("mp must not be NULL"); ++ return; ++ } + -+ return mf->crop_top; ++ mp->setMediaPreparedCb(cb, context); +} + -+int32_t media_format_get_crop_bottom(MediaFormat format) ++MediaPlayerWrapper *android_media_new_player() +{ -+ REPORT_FUNCTION() ++ REPORT_FUNCTION(); + -+ _MediaFormat *mf = get_internal_format(format); -+ if (mf == NULL) -+ return 0; ++ MediaPlayerWrapper *mp = new MediaPlayerWrapper(); ++ if (mp == NULL) { ++ ALOGE("Failed to create new MediaPlayerWrapper instance."); ++ return NULL; ++ } + -+ return mf->crop_bottom; ++ // Required for internal player state processing. Without this, prepare() and start() hang. ++ ProcessState::self()->startThreadPool(); ++ ++ return mp; +} ---- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_format_layer_priv.cpp -@@ -0,0 +1,50 @@ -+/* -+ * Copyright (C) 2013 Canonical Ltd -+ * -+ * 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. -+ * -+ * Authored by: Jim Hodapp -+ */ + -+#include -+#include ++int android_media_set_data_source(MediaPlayerWrapper *mp, const char* url) ++{ ++ REPORT_FUNCTION(); + -+#include ++ if (mp == NULL) { ++ ALOGE("mp must not be NULL"); ++ return BAD_VALUE; ++ } + -+#include ++ if (url == NULL) { ++ ALOGE("url must not be NULL"); ++ return BAD_VALUE; ++ } + -+#ifdef __cplusplus -+extern "C" { ++ ALOGD("url: %s", url); ++ ++ String16 src(url); ++ if (src.startsWith(String16("http://")) == true) { ++ ALOGD("HTTP source URL detected"); ++#if 0 // remarked for future debugging - chunsang ++#if ANDROID_VERSION_MAJOR==5 ++ mp->setDataSource(NULL,url, NULL); ++#else ++ mp->setDataSource(url, NULL); ++#endif +#endif ++ } else { ++ ALOGD("File source URL detected"); ++ int fd = open(url, O_RDONLY); ++ if (fd < 0) ++ { ++ ALOGE("Failed to open source data at: %s\n", url); ++ return BAD_VALUE; ++ } + -+struct _MediaFormat : public RefBase -+{ -+ _MediaFormat() -+ : refcount(1) -+ { -+ } ++ mp->setSourceFd(fd); + -+ AString mime; -+ int64_t duration_us; -+ int32_t width; -+ int32_t height; -+ int32_t max_input_size; ++ struct stat st; ++ stat(url, &st); + -+ unsigned int refcount; -+}; ++ ALOGD("source file length: %lld\n", st.st_size); + -+#ifdef __cplusplus ++ mp->setDataSource(fd, 0, st.st_size); ++ } ++ mp->prepare(); ++ ++ return OK; +} -+#endif + -+#endif ---- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_format_layer_priv.h -@@ -0,0 +1,68 @@ -+/* -+ * Copyright (C) 2013 Canonical Ltd -+ * -+ * 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. -+ * -+ * Authored by: Jim Hodapp -+ */ -+ -+#ifndef MEDIA_FORMAT_LAYER_PRIV_H_ -+#define MEDIA_FORMAT_LAYER_PRIV_H_ ++int android_media_set_preview_texture(MediaPlayerWrapper *mp, int texture_id) ++{ ++ REPORT_FUNCTION(); + -+#include -+#include ++ if (mp == NULL) { ++ ALOGE("mp must not be NULL"); ++ return BAD_VALUE; ++ } + -+#include -+#include ++ android::sp native_alloc( ++ new android::NativeBufferAlloc() ++ ); + -+#include ++#if ANDROID_VERSION_MAJOR>=5 ++ android::sp producer; ++ android::sp consumer; ++ BufferQueue::createBufferQueue(&producer, &consumer); ++#else ++ android::sp buffer_queue( ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 ++ new android::BufferQueue(false, NULL, native_alloc) ++#else ++ new android::BufferQueue(NULL) ++#endif ++ ); ++#endif + -+struct _MediaFormat : public android::RefBase -+{ -+ _MediaFormat() -+ : duration_us(0), -+ width(0), -+ height(0), -+ max_input_size(0), -+ csd(NULL), -+ stride(0), -+ slice_height(0), -+ color_format(0), -+ crop_left(0), -+ crop_right(0), -+ crop_top(0), -+ crop_bottom(0), -+ refcount(1) -+ { -+ } ++ static const bool allow_synchronous_mode = true; ++ // Create a new GLConsumer/SurfaceTexture from the texture_id in synchronous mode (don't wait on all data in the buffer) ++#if ANDROID_VERSION_MAJOR>=5 ++ mp->setVideoSurfaceTexture(producer, android::sp( ++ new android::GLConsumer( ++#elif ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++ mp->setVideoSurfaceTexture(android::sp( ++ new android::SurfaceTexture( ++#else ++ mp->setVideoSurfaceTexture(buffer_queue, android::sp( ++ new android::GLConsumer( ++#endif ++#if ANDROID_VERSION_MAJOR>=5 ++ consumer, ++ texture_id, ++ GL_TEXTURE_EXTERNAL_OES, ++ true, ++ false))); + -+ android::AString mime; -+ int64_t duration_us; -+ int32_t width; -+ int32_t height; -+ int32_t max_input_size; -+ android::AString csd_key_name; -+ android::sp csd; ++#elif ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 ++ texture_id, ++ allow_synchronous_mode, ++ GL_TEXTURE_EXTERNAL_OES, ++ true, ++ buffer_queue))); ++#else ++ buffer_queue, ++ texture_id, ++ GL_TEXTURE_EXTERNAL_OES, ++ true, ++ false))); ++#endif + -+ int32_t stride; -+ int32_t slice_height; -+ int32_t color_format; -+ int32_t crop_left; -+ int32_t crop_right; -+ int32_t crop_top; -+ int32_t crop_bottom; ++ return OK; ++} + -+ unsigned int refcount; -+}; ++void android_media_update_surface_texture(MediaPlayerWrapper *mp) ++{ ++ if (mp == NULL) { ++ ALOGE("mp must not be NULL"); ++ return; ++ } + -+#endif // MEDIA_FORMAT_LAYER_PRIV_H_ ---- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_recorder.cpp -@@ -0,0 +1,747 @@ -+/* -+ ** Copyright (c) 2008 The Android Open Source Project -+ ** Copyright (C) 2014 Canonical Ltd -+ ** -+ ** Adapted from the Android equivalent code for use in Ubuntu. -+ ** -+ ** 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. -+ */ ++ mp->updateGLConsumer(); ++} + -+#define LOG_NDEBUG 0 -+#define LOG_TAG "MediaRecorder" ++void android_media_surface_texture_get_transformation_matrix(MediaPlayerWrapper *mp, GLfloat* matrix) ++{ ++ if (mp == NULL) { ++ ALOGE("mp must not be NULL"); ++ return; ++ } + -+#include "media_recorder.h" -+#include "media_recorder_factory.h" ++ mp->get_transformation_matrix_for_surface_texture(matrix); ++} + -+#include -+#include -+#include -+#include -+#include -+#include // for MEDIA_ERROR_SERVER_DIED -+#include ++int android_media_play(MediaPlayerWrapper *mp) ++{ ++ REPORT_FUNCTION(); + -+namespace android { ++ if (mp == NULL) { ++ ALOGE("mp must not be NULL"); ++ return BAD_VALUE; ++ } + -+status_t MediaRecorder::setCamera(const sp& camera, const sp& proxy) -+{ -+ ALOGV("setCamera(%p,%p)", camera.get(), proxy.get()); -+ if (mMediaRecorder == NULL) { -+ ALOGE("media recorder is not initialized yet"); -+ return INVALID_OPERATION; -+ } -+ if (!(mCurrentState & MEDIA_RECORDER_IDLE)) { -+ ALOGE("setCamera called in an invalid state(%d)", mCurrentState); -+ return INVALID_OPERATION; -+ } ++ mp->start(); ++ const char *tmp = mp->isPlaying() ? "yes" : "no"; ++ ALOGV("Is playing?: %s\n", tmp); + -+ status_t ret = mMediaRecorder->setCamera(camera, proxy); -+ if (OK != ret) { -+ ALOGV("setCamera failed: %d", ret); -+ mCurrentState = MEDIA_RECORDER_ERROR; -+ return ret; -+ } -+ return ret; ++ return OK; +} + -+status_t MediaRecorder::setPreviewSurface(const sp& surface) ++int android_media_pause(MediaPlayerWrapper *mp) +{ -+ ALOGV("setPreviewSurface(%p)", surface.get()); -+ if (mMediaRecorder == NULL) { -+ ALOGE("media recorder is not initialized yet"); -+ return INVALID_OPERATION; -+ } -+ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { -+ ALOGE("setPreviewSurface called in an invalid state(%d)", mCurrentState); -+ return INVALID_OPERATION; -+ } -+ if (!mIsVideoSourceSet) { -+ ALOGE("try to set preview surface without setting the video source first"); -+ return INVALID_OPERATION; -+ } ++ REPORT_FUNCTION(); + -+ status_t ret = mMediaRecorder->setPreviewSurface(surface); -+ if (OK != ret) { -+ ALOGV("setPreviewSurface failed: %d", ret); -+ mCurrentState = MEDIA_RECORDER_ERROR; -+ return ret; -+ } -+ return ret; ++ if (mp == NULL) { ++ ALOGE("mp must not be NULL"); ++ return BAD_VALUE; ++ } ++ ++ mp->pause(); ++ ++ return OK; +} + -+status_t MediaRecorder::init() ++int android_media_stop(MediaPlayerWrapper *mp) +{ -+ ALOGV("init"); -+ if (mMediaRecorder == NULL) { -+ ALOGE("media recorder is not initialized yet"); -+ return INVALID_OPERATION; -+ } -+ if (!(mCurrentState & MEDIA_RECORDER_IDLE)) { -+ ALOGE("init called in an invalid state(%d)", mCurrentState); -+ return INVALID_OPERATION; -+ } ++ REPORT_FUNCTION(); + -+ status_t ret = mMediaRecorder->init(); -+ if (OK != ret) { -+ ALOGV("init failed: %d", ret); -+ mCurrentState = MEDIA_RECORDER_ERROR; -+ return ret; -+ } ++ if (mp == NULL) { ++ ALOGE("mp must not be NULL"); ++ return BAD_VALUE; ++ } + -+ ret = mMediaRecorder->setListener(this); -+ if (OK != ret) { -+ ALOGV("setListener failed: %d", ret); -+ mCurrentState = MEDIA_RECORDER_ERROR; -+ return ret; -+ } ++ mp->stop(); + -+ mCurrentState = MEDIA_RECORDER_INITIALIZED; -+ return ret; ++ int fd = mp->getSourceFd(); ++ if (fd > -1) ++ close(fd); ++ ++ return OK; +} + -+status_t MediaRecorder::setVideoSource(int vs) ++bool android_media_is_playing(MediaPlayerWrapper *mp) +{ -+ ALOGV("setVideoSource(%d)", vs); -+ if (mMediaRecorder == NULL) { -+ ALOGE("media recorder is not initialized yet"); -+ return INVALID_OPERATION; -+ } -+ if (mIsVideoSourceSet) { -+ ALOGE("video source has already been set"); -+ return INVALID_OPERATION; -+ } -+ if (mCurrentState & MEDIA_RECORDER_IDLE) { -+ ALOGV("Call init() since the media recorder is not initialized yet"); -+ status_t ret = init(); -+ if (OK != ret) { -+ return ret; -+ } -+ } -+ if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { -+ ALOGE("setVideoSource called in an invalid state(%d)", mCurrentState); -+ return INVALID_OPERATION; -+ } -+ -+ // following call is made over the Binder Interface -+ status_t ret = mMediaRecorder->setVideoSource(vs); ++ if (mp != NULL) { ++ if (mp->isPlaying()) ++ return true; ++ } + -+ if (OK != ret) { -+ ALOGV("setVideoSource failed: %d", ret); -+ mCurrentState = MEDIA_RECORDER_ERROR; -+ return ret; -+ } -+ mIsVideoSourceSet = true; -+ return ret; ++ return false; +} + -+status_t MediaRecorder::setAudioSource(int as) ++int android_media_seek_to(MediaPlayerWrapper *mp, int msec) +{ -+ ALOGV("setAudioSource(%d)", as); -+ if (mMediaRecorder == NULL) { -+ ALOGE("media recorder is not initialized yet"); -+ return INVALID_OPERATION; -+ } -+ if (mCurrentState & MEDIA_RECORDER_IDLE) { -+ ALOGV("Call init() since the media recorder is not initialized yet"); -+ status_t ret = init(); -+ if (OK != ret) { -+ return ret; -+ } -+ } -+ if (mIsAudioSourceSet) { -+ ALOGE("audio source has already been set"); -+ return INVALID_OPERATION; -+ } -+ if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { -+ ALOGE("setAudioSource called in an invalid state(%d)", mCurrentState); -+ return INVALID_OPERATION; -+ } -+ -+ status_t ret = mMediaRecorder->setAudioSource(as); -+ if (OK != ret) { -+ ALOGV("setAudioSource failed: %d", ret); -+ mCurrentState = MEDIA_RECORDER_ERROR; -+ return ret; -+ } -+ mIsAudioSourceSet = true; -+ return ret; -+} ++ REPORT_FUNCTION(); + -+status_t MediaRecorder::setOutputFormat(int of) -+{ -+ ALOGV("setOutputFormat(%d)", of); -+ if (mMediaRecorder == NULL) { -+ ALOGE("media recorder is not initialized yet"); -+ return INVALID_OPERATION; -+ } -+ if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { -+ ALOGE("setOutputFormat called in an invalid state: %d", mCurrentState); -+ return INVALID_OPERATION; -+ } -+ if (mIsVideoSourceSet && of >= OUTPUT_FORMAT_AUDIO_ONLY_START && of != OUTPUT_FORMAT_RTP_AVP && of != OUTPUT_FORMAT_MPEG2TS) { //first non-video output format -+ ALOGE("output format (%d) is meant for audio recording only and incompatible with video recording", of); -+ return INVALID_OPERATION; -+ } ++ if (mp == NULL) { ++ ALOGE("mp must not be NULL"); ++ return BAD_VALUE; ++ } + -+ status_t ret = mMediaRecorder->setOutputFormat(of); -+ if (OK != ret) { -+ ALOGE("setOutputFormat failed: %d", ret); -+ mCurrentState = MEDIA_RECORDER_ERROR; -+ return ret; -+ } -+ mCurrentState = MEDIA_RECORDER_DATASOURCE_CONFIGURED; -+ return ret; ++ return mp->seekTo(msec); +} + -+status_t MediaRecorder::setVideoEncoder(int ve) ++int android_media_get_current_position(MediaPlayerWrapper *mp, int *msec) +{ -+ ALOGV("setVideoEncoder(%d)", ve); -+ if (mMediaRecorder == NULL) { -+ ALOGE("media recorder is not initialized yet"); -+ return INVALID_OPERATION; -+ } -+ if (!mIsVideoSourceSet) { -+ ALOGE("try to set the video encoder without setting the video source first"); -+ return INVALID_OPERATION; -+ } -+ if (mIsVideoEncoderSet) { -+ ALOGE("video encoder has already been set"); -+ return INVALID_OPERATION; -+ } -+ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { -+ ALOGE("setVideoEncoder called in an invalid state(%d)", mCurrentState); -+ return INVALID_OPERATION; -+ } ++ if (mp == NULL) { ++ ALOGE("mp must not be NULL"); ++ return BAD_VALUE; ++ } + -+ status_t ret = mMediaRecorder->setVideoEncoder(ve); -+ if (OK != ret) { -+ ALOGV("setVideoEncoder failed: %d", ret); -+ mCurrentState = MEDIA_RECORDER_ERROR; -+ return ret; -+ } -+ mIsVideoEncoderSet = true; -+ return ret; ++ return mp->getCurrentPosition(msec); +} + -+status_t MediaRecorder::setAudioEncoder(int ae) ++int android_media_get_duration(MediaPlayerWrapper *mp, int *msec) +{ -+ ALOGV("setAudioEncoder(%d)", ae); -+ if (mMediaRecorder == NULL) { -+ ALOGE("media recorder is not initialized yet"); -+ return INVALID_OPERATION; -+ } -+ if (!mIsAudioSourceSet) { -+ ALOGE("try to set the audio encoder without setting the audio source first"); -+ return INVALID_OPERATION; -+ } -+ if (mIsAudioEncoderSet) { -+ ALOGE("audio encoder has already been set"); -+ return INVALID_OPERATION; -+ } -+ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { -+ ALOGE("setAudioEncoder called in an invalid state(%d)", mCurrentState); -+ return INVALID_OPERATION; -+ } ++ REPORT_FUNCTION(); + -+ status_t ret = mMediaRecorder->setAudioEncoder(ae); -+ if (OK != ret) { -+ ALOGV("setAudioEncoder failed: %d", ret); -+ mCurrentState = MEDIA_RECORDER_ERROR; -+ return ret; -+ } -+ mIsAudioEncoderSet = true; -+ return ret; ++ if (mp == NULL) { ++ ALOGE("mp must not be NULL"); ++ return BAD_VALUE; ++ } ++ ++ return mp->getDuration(msec); +} + -+status_t MediaRecorder::setOutputFile(const char* path) ++int android_media_get_volume(MediaPlayerWrapper *mp, int *volume) +{ -+ ALOGV("setOutputFile(%s)", path); -+ if (mMediaRecorder == NULL) { -+ ALOGE("media recorder is not initialized yet"); -+ return INVALID_OPERATION; -+ } -+ if (mIsOutputFileSet) { -+ ALOGE("output file has already been set"); -+ return INVALID_OPERATION; -+ } -+ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { -+ ALOGE("setOutputFile called in an invalid state(%d)", mCurrentState); -+ return INVALID_OPERATION; -+ } ++ REPORT_FUNCTION(); + -+ status_t ret = mMediaRecorder->setOutputFile(path); -+ if (OK != ret) { -+ ALOGV("setOutputFile failed: %d", ret); -+ mCurrentState = MEDIA_RECORDER_ERROR; -+ return ret; -+ } -+ mIsOutputFileSet = true; -+ return ret; -+} ++ if (volume == NULL) { ++ ALOGE("volume must not be NULL"); ++ return BAD_VALUE; ++ } + -+status_t MediaRecorder::setOutputFile(int fd, int64_t offset, int64_t length) -+{ -+ ALOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length); -+ if (mMediaRecorder == NULL) { -+ ALOGE("media recorder is not initialized yet"); -+ return INVALID_OPERATION; -+ } -+ if (mIsOutputFileSet) { -+ ALOGE("output file has already been set"); -+ return INVALID_OPERATION; -+ } -+ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { -+ ALOGE("setOutputFile called in an invalid state(%d)", mCurrentState); -+ return INVALID_OPERATION; -+ } ++ if (mp == NULL) { ++ ALOGE("mp must not be NULL"); ++ return BAD_VALUE; ++ } + -+ // It appears that if an invalid file descriptor is passed through -+ // binder calls, the server-side of the inter-process function call -+ // is skipped. As a result, the check at the server-side to catch -+ // the invalid file descritpor never gets invoked. This is to workaround -+ // this issue by checking the file descriptor first before passing -+ // it through binder call. -+ if (fd < 0) { -+ ALOGE("Invalid file descriptor: %d", fd); -+ return BAD_VALUE; -+ } ++ float left_volume = 0, right_volume = 0; ++ mp->getVolume(&left_volume, &right_volume); ++ *volume = left_volume * 100; + -+ status_t ret = mMediaRecorder->setOutputFile(fd, offset, length); -+ if (OK != ret) { -+ ALOGV("setOutputFile failed: %d", ret); -+ mCurrentState = MEDIA_RECORDER_ERROR; -+ return ret; -+ } -+ mIsOutputFileSet = true; -+ return ret; ++ return OK; +} + -+status_t MediaRecorder::setVideoSize(int width, int height) ++int android_media_set_volume(MediaPlayerWrapper *mp, int volume) +{ -+ ALOGV("setVideoSize(%d, %d)", width, height); -+ if (mMediaRecorder == NULL) { -+ ALOGE("media recorder is not initialized yet"); -+ return INVALID_OPERATION; -+ } -+ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { -+ ALOGE("setVideoSize called in an invalid state: %d", mCurrentState); -+ return INVALID_OPERATION; -+ } -+ if (!mIsVideoSourceSet) { -+ ALOGE("Cannot set video size without setting video source first"); -+ return INVALID_OPERATION; -+ } ++ REPORT_FUNCTION(); + -+ status_t ret = mMediaRecorder->setVideoSize(width, height); -+ if (OK != ret) { -+ ALOGE("setVideoSize failed: %d", ret); -+ mCurrentState = MEDIA_RECORDER_ERROR; -+ return ret; -+ } ++ if (mp == NULL) { ++ ALOGE("mp must not be NULL"); ++ return BAD_VALUE; ++ } + -+ return ret; ++ float left_volume = float(volume / 100); ++ float right_volume = float(volume / 100); ++ return mp->setVolume(left_volume, right_volume); +} -+ -+// Query a SurfaceMediaSurface through the Mediaserver, over the -+// binder interface. This is used by the Filter Framework (MediaEncoder) -+// to get an object to hook up to ANativeWindow. -+sp MediaRecorder:: -+ querySurfaceMediaSourceFromMediaServer() +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_core.cpp +@@ -0,0 +1,37 @@ ++/* ++ * Copyright (C) 2016 Canonical Ltd ++ * ++ * 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. ++ * ++ * Authored by: Simon Fels ++ */ ++ ++unsigned int hybris_media_get_version(void) +{ -+ Mutex::Autolock _l(mLock); -+ mSurfaceMediaSource = -+ mMediaRecorder->querySurfaceMediaSource(); -+ if (mSurfaceMediaSource == NULL) { -+ ALOGE("SurfaceMediaSource could not be initialized!"); -+ } -+ return mSurfaceMediaSource; ++ /* The version number here will be bumped when the ABI of the ++ * media compatibility layer changes. This version number will ++ * be used by clients to track newly added functionality. ++ * ++ * If new functionality is added the client side is responsible ++ * to continue working on platforms where the new functionality ++ * is not yet available. ++ * ++ * Changelog: ++ * 1: ++ * - Introduction of the new versioning approach ++ * - MediaCodecSource support for Android 5.x based platforms ++ * - Wrappers for AMessage, MediaBuffer, MediaMetaData etc. to ++ * support MediaCodecSource implementation ++ */ ++ return 1; +} +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_format_layer.cpp +@@ -0,0 +1,245 @@ ++/* ++ * Copyright (C) 2013 Canonical Ltd ++ * ++ * 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. ++ * ++ * Authored by: Jim Hodapp ++ */ + -+status_t MediaRecorder::setVideoFrameRate(int frames_per_second) -+{ -+ ALOGV("setVideoFrameRate(%d)", frames_per_second); -+ if (mMediaRecorder == NULL) { -+ ALOGE("media recorder is not initialized yet"); -+ return INVALID_OPERATION; -+ } -+ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { -+ ALOGE("setVideoFrameRate called in an invalid state: %d", mCurrentState); -+ return INVALID_OPERATION; -+ } -+ if (!mIsVideoSourceSet) { -+ ALOGE("Cannot set video frame rate without setting video source first"); -+ return INVALID_OPERATION; -+ } ++// Uncomment to enable verbose debug output ++#define LOG_NDEBUG 0 + -+ status_t ret = mMediaRecorder->setVideoFrameRate(frames_per_second); -+ if (OK != ret) { -+ ALOGE("setVideoFrameRate failed: %d", ret); -+ mCurrentState = MEDIA_RECORDER_ERROR; -+ return ret; -+ } -+ return ret; -+} ++#undef LOG_TAG ++#define LOG_TAG "MediaFormatLayer" + -+status_t MediaRecorder::setParameters(const String8& params) { -+ ALOGV("setParameters(%s)", params.string()); -+ if (mMediaRecorder == NULL) { -+ ALOGE("media recorder is not initialized yet"); -+ return INVALID_OPERATION; -+ } ++#include ++#include "media_format_layer_priv.h" + -+ bool isInvalidState = (mCurrentState & -+ (MEDIA_RECORDER_PREPARED | -+ MEDIA_RECORDER_RECORDING | -+ MEDIA_RECORDER_ERROR)); -+ if (isInvalidState) { -+ ALOGE("setParameters is called in an invalid state: %d", mCurrentState); -+ return INVALID_OPERATION; -+ } ++#include + -+ status_t ret = mMediaRecorder->setParameters(params); -+ if (OK != ret) { -+ ALOGE("setParameters(%s) failed: %d", params.string(), ret); -+ // Do not change our current state to MEDIA_RECORDER_ERROR, failures -+ // of the only currently supported parameters, "max-duration" and -+ // "max-filesize" are _not_ fatal. ++#include ++ ++#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__); ++ ++using namespace android; ++ ++static inline _MediaFormat *get_internal_format(MediaFormat format) ++{ ++ if (format == NULL) ++ { ++ ALOGE("format must not be NULL"); ++ return NULL; + } + -+ return ret; ++ _MediaFormat *mf = static_cast<_MediaFormat*>(format); ++ assert(mf->refcount >= 1); ++ ++ return mf; +} + -+status_t MediaRecorder::prepare() ++MediaFormat media_format_create_video_format(const char *mime, int32_t width, int32_t height, int64_t duration_us, int32_t max_input_size) +{ -+ ALOGV("prepare"); -+ if (mMediaRecorder == NULL) { -+ ALOGE("media recorder is not initialized yet"); -+ return INVALID_OPERATION; -+ } -+ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { -+ ALOGE("prepare called in an invalid state: %d", mCurrentState); -+ return INVALID_OPERATION; -+ } -+ if (mIsAudioSourceSet != mIsAudioEncoderSet) { -+ if (mIsAudioSourceSet) { -+ ALOGE("audio source is set, but audio encoder is not set"); -+ } else { // must not happen, since setAudioEncoder checks this already -+ ALOGE("audio encoder is set, but audio source is not set"); -+ } -+ return INVALID_OPERATION; -+ } ++ REPORT_FUNCTION() + -+ if (mIsVideoSourceSet != mIsVideoEncoderSet) { -+ if (mIsVideoSourceSet) { -+ ALOGE("video source is set, but video encoder is not set"); -+ } else { // must not happen, since setVideoEncoder checks this already -+ ALOGE("video encoder is set, but video source is not set"); -+ } -+ return INVALID_OPERATION; -+ } ++ _MediaFormat *format = new _MediaFormat(); ++ format->mime = AString(mime); ++ format->width = width; ++ format->height = height; ++ format->duration_us = duration_us; ++ format->max_input_size = max_input_size; + -+ status_t ret = mMediaRecorder->prepare(); -+ if (OK != ret) { -+ ALOGE("prepare failed: %d", ret); -+ mCurrentState = MEDIA_RECORDER_ERROR; -+ return ret; -+ } -+ mCurrentState = MEDIA_RECORDER_PREPARED; -+ return ret; ++ return format; +} + -+status_t MediaRecorder::getMaxAmplitude(int* max) ++void media_format_destroy(MediaFormat format) +{ -+ ALOGV("getMaxAmplitude"); -+ if (mMediaRecorder == NULL) { -+ ALOGE("media recorder is not initialized yet"); -+ return INVALID_OPERATION; -+ } -+ if (mCurrentState & MEDIA_RECORDER_ERROR) { -+ ALOGE("getMaxAmplitude called in an invalid state: %d", mCurrentState); -+ return INVALID_OPERATION; -+ } ++ REPORT_FUNCTION() + -+ status_t ret = mMediaRecorder->getMaxAmplitude(max); -+ if (OK != ret) { -+ ALOGE("getMaxAmplitude failed: %d", ret); -+ mCurrentState = MEDIA_RECORDER_ERROR; -+ return ret; -+ } -+ return ret; ++ _MediaFormat *mf = get_internal_format(format); ++ if (mf == NULL) ++ return; ++ ++ if (mf->refcount) ++ return; ++ ++ delete mf; +} + -+status_t MediaRecorder::start() ++void media_format_ref(MediaFormat format) +{ -+ ALOGV("start"); -+ if (mMediaRecorder == NULL) { -+ ALOGE("media recorder is not initialized yet"); -+ return INVALID_OPERATION; -+ } -+ if (!(mCurrentState & MEDIA_RECORDER_PREPARED)) { -+ ALOGE("start called in an invalid state: %d", mCurrentState); -+ return INVALID_OPERATION; -+ } ++ REPORT_FUNCTION() + -+ status_t ret = mMediaRecorder->start(); -+ if (OK != ret) { -+ ALOGE("start failed: %d", ret); -+ mCurrentState = MEDIA_RECORDER_ERROR; -+ return ret; -+ } -+ mCurrentState = MEDIA_RECORDER_RECORDING; -+ return ret; ++ _MediaFormat *mf = get_internal_format(format); ++ if (mf == NULL) ++ return; ++ ++ mf->refcount++; +} + -+status_t MediaRecorder::stop() ++void media_format_unref(MediaFormat format) +{ -+ ALOGV("stop"); -+ if (mMediaRecorder == NULL) { -+ ALOGE("media recorder is not initialized yet"); -+ return INVALID_OPERATION; -+ } -+ if (!(mCurrentState & MEDIA_RECORDER_RECORDING)) { -+ ALOGE("stop called in an invalid state: %d", mCurrentState); -+ return INVALID_OPERATION; -+ } ++ REPORT_FUNCTION() + -+ status_t ret = mMediaRecorder->stop(); -+ if (OK != ret) { -+ ALOGE("stop failed: %d", ret); -+ mCurrentState = MEDIA_RECORDER_ERROR; -+ return ret; -+ } ++ _MediaFormat *mf = get_internal_format(format); ++ if (mf == NULL) ++ return; + -+ // FIXME: -+ // stop and reset are semantically different. -+ // We treat them the same for now, and will change this in the future. -+ doCleanUp(); -+ mCurrentState = MEDIA_RECORDER_IDLE; -+ return ret; ++ if (mf->refcount) ++ mf->refcount--; +} + -+// Reset should be OK in any state -+status_t MediaRecorder::reset() ++void media_format_set_byte_buffer(MediaFormat format, const char *key, uint8_t *data, size_t size) +{ -+ ALOGV("reset"); -+ if (mMediaRecorder == NULL) { -+ ALOGE("media recorder is not initialized yet"); -+ return INVALID_OPERATION; -+ } ++ REPORT_FUNCTION() + -+ doCleanUp(); -+ status_t ret = UNKNOWN_ERROR; -+ switch (mCurrentState) { -+ case MEDIA_RECORDER_IDLE: -+ ret = OK; -+ break; ++ _MediaFormat *mf = get_internal_format(format); ++ if (mf == NULL) ++ return; ++ if (key == NULL || data == NULL || size == 0) ++ return; + -+ case MEDIA_RECORDER_RECORDING: -+ case MEDIA_RECORDER_DATASOURCE_CONFIGURED: -+ case MEDIA_RECORDER_PREPARED: -+ case MEDIA_RECORDER_ERROR: { -+ ret = doReset(); -+ if (OK != ret) { -+ return ret; // No need to continue -+ } -+ } // Intentional fall through -+ case MEDIA_RECORDER_INITIALIZED: -+ ret = close(); -+ break; -+ -+ default: { -+ ALOGE("Unexpected non-existing state: %d", mCurrentState); -+ break; -+ } -+ } -+ return ret; ++ mf->csd_key_name = AString(key); ++ mf->csd = sp(new ABuffer(data, size)); +} + -+status_t MediaRecorder::close() ++const char* media_format_get_mime(MediaFormat format) +{ -+ ALOGV("close"); -+ if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { -+ ALOGE("close called in an invalid state: %d", mCurrentState); -+ return INVALID_OPERATION; -+ } -+ status_t ret = mMediaRecorder->close(); -+ if (OK != ret) { -+ ALOGE("close failed: %d", ret); -+ mCurrentState = MEDIA_RECORDER_ERROR; -+ return UNKNOWN_ERROR; -+ } else { -+ mCurrentState = MEDIA_RECORDER_IDLE; -+ } -+ return ret; -+} ++ REPORT_FUNCTION() + -+status_t MediaRecorder::doReset() -+{ -+ ALOGV("doReset"); -+ status_t ret = mMediaRecorder->reset(); -+ if (OK != ret) { -+ ALOGE("doReset failed: %d", ret); -+ mCurrentState = MEDIA_RECORDER_ERROR; -+ return ret; -+ } else { -+ mCurrentState = MEDIA_RECORDER_INITIALIZED; -+ } -+ return ret; ++ _MediaFormat *mf = get_internal_format(format); ++ if (mf == NULL) ++ return NULL; ++ ++ return mf->mime.c_str(); +} + -+void MediaRecorder::doCleanUp() ++int64_t media_format_get_duration_us(MediaFormat format) +{ -+ ALOGV("doCleanUp"); -+ mIsAudioSourceSet = false; -+ mIsVideoSourceSet = false; -+ mIsAudioEncoderSet = false; -+ mIsVideoEncoderSet = false; -+ mIsOutputFileSet = false; ++ REPORT_FUNCTION() ++ ++ _MediaFormat *mf = get_internal_format(format); ++ if (mf == NULL) ++ return 0; ++ ++ return mf->duration_us; +} + -+// Release should be OK in any state -+status_t MediaRecorder::release() ++int32_t media_format_get_width(MediaFormat format) +{ -+ ALOGV("release"); -+ if (mMediaRecorder != NULL) { -+ return mMediaRecorder->release(); -+ } -+ return INVALID_OPERATION; -+} ++ REPORT_FUNCTION() ++ ++ _MediaFormat *mf = get_internal_format(format); ++ if (mf == NULL) ++ return 0; + ++ return mf->width; ++} + -+MediaRecorder::MediaRecorder() -+ : mMediaRecorderFactory(NULL), -+ mSurfaceMediaSource(NULL) ++int32_t media_format_get_height(MediaFormat format) +{ -+ ALOGV("constructor (custom)"); ++ REPORT_FUNCTION() + -+ if (mMediaRecorderFactory == NULL) { -+ sp sm = defaultServiceManager(); -+ sp binder; -+ do { -+ binder = sm->getService(String16(IMediaRecorderFactory::exported_service_name())); -+ if (binder != 0) { -+ break; -+ } -+ ALOGW("MediaRecorderFactory service not published, waiting..."); -+ usleep(500000); // 0.5 s -+ } while (true); ++ _MediaFormat *mf = get_internal_format(format); ++ if (mf == NULL) ++ return 0; + -+ mMediaRecorderFactory = interface_cast(binder); -+ } ++ return mf->height; ++} + -+ ALOGE_IF(mMediaRecorderFactory == NULL, "no MediaRecorderFactory!?"); ++int32_t media_format_get_max_input_size(MediaFormat format) ++{ ++ REPORT_FUNCTION() + -+ mMediaRecorder = mMediaRecorderFactory->createMediaRecorder(); -+ if (mMediaRecorder != NULL) { -+ mCurrentState = MEDIA_RECORDER_IDLE; -+ } ++ _MediaFormat *mf = get_internal_format(format); ++ if (mf == NULL) ++ return 0; + -+ doCleanUp(); ++ return mf->max_input_size; +} + -+status_t MediaRecorder::initCheck() ++int32_t media_format_get_stride(MediaFormat format) +{ -+ return mMediaRecorder != 0 ? NO_ERROR : NO_INIT; ++ REPORT_FUNCTION() ++ ++ _MediaFormat *mf = get_internal_format(format); ++ if (mf == NULL) ++ return 0; ++ ++ return mf->stride; +} + -+MediaRecorder::~MediaRecorder() ++int32_t media_format_get_slice_height(MediaFormat format) +{ -+ ALOGV("destructor"); -+ if (mMediaRecorder != NULL) { -+ mMediaRecorder.clear(); -+ } ++ REPORT_FUNCTION() + -+ if (mSurfaceMediaSource != NULL) { -+ mSurfaceMediaSource.clear(); -+ } ++ _MediaFormat *mf = get_internal_format(format); ++ if (mf == NULL) ++ return 0; ++ ++ return mf->slice_height; +} + -+status_t MediaRecorder::setListener(const sp& listener) ++int32_t media_format_get_color_format(MediaFormat format) +{ -+ ALOGV("setListener"); -+ Mutex::Autolock _l(mLock); -+ mListener = listener; ++ REPORT_FUNCTION() + -+ if (mMediaRecorder != NULL) { -+ // Sets a listener so that when the named pipe reader in RecordThread is ready, -+ // we can bubble up to media_recorder_layer to signal the app that it's ready -+ // to do audio recording -+ mMediaRecorder->setListener(this); -+ } ++ _MediaFormat *mf = get_internal_format(format); ++ if (mf == NULL) ++ return 0; + -+ return NO_ERROR; ++ return mf->color_format; +} + -+status_t MediaRecorder::setClientName(const String16& clientName) ++int32_t media_format_get_crop_left(MediaFormat format) +{ -+ ALOGV("setClientName"); -+ if (mMediaRecorder == NULL) { -+ ALOGE("media recorder is not initialized yet"); -+ return INVALID_OPERATION; -+ } -+ bool isInvalidState = (mCurrentState & -+ (MEDIA_RECORDER_PREPARED | -+ MEDIA_RECORDER_RECORDING | -+ MEDIA_RECORDER_ERROR)); -+ if (isInvalidState) { -+ ALOGE("setClientName is called in an invalid state: %d", mCurrentState); -+ return INVALID_OPERATION; -+ } ++ REPORT_FUNCTION() + -+ mMediaRecorder->setClientName(clientName); ++ _MediaFormat *mf = get_internal_format(format); ++ if (mf == NULL) ++ return 0; + -+ return NO_ERROR; ++ return mf->crop_left; +} + -+void MediaRecorder::notify(int msg, int ext1, int ext2) ++int32_t media_format_get_crop_right(MediaFormat format) +{ -+ ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2); ++ REPORT_FUNCTION() + -+ sp listener; -+ mLock.lock(); -+ listener = mListener; -+ mLock.unlock(); ++ _MediaFormat *mf = get_internal_format(format); ++ if (mf == NULL) ++ return 0; + -+ if (listener != NULL) { -+ Mutex::Autolock _l(mNotifyLock); -+ ALOGV("callback application"); -+ listener->notify(msg, ext1, ext2); -+ ALOGV("back from callback"); -+ } ++ return mf->crop_right; +} + -+void MediaRecorder::readAudio() ++int32_t media_format_get_crop_top(MediaFormat format) +{ -+ ALOGV("%s", __PRETTY_FUNCTION__); ++ REPORT_FUNCTION() + -+ sp listener; -+ status_t ret = NO_ERROR; -+ mLock.lock(); -+ listener = mListener; -+ mLock.unlock(); ++ _MediaFormat *mf = get_internal_format(format); ++ if (mf == NULL) ++ return 0; + -+ if (listener != NULL) { -+ Mutex::Autolock _l(mReadAudioLock); -+ ALOGV("callback application"); -+ listener->readAudio(); -+ ALOGV("back from callback"); -+ } ++ return mf->crop_top; +} + -+void MediaRecorder::died() ++int32_t media_format_get_crop_bottom(MediaFormat format) +{ -+ ALOGV("died"); -+ notify(MEDIA_RECORDER_EVENT_ERROR, MEDIA_ERROR_SERVER_DIED, 0); -+} ++ REPORT_FUNCTION() + -+} // namespace android ++ _MediaFormat *mf = get_internal_format(format); ++ if (mf == NULL) ++ return 0; ++ ++ return mf->crop_bottom; ++} --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_recorder.h -@@ -0,0 +1,269 @@ ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_format_layer_priv.cpp +@@ -0,0 +1,50 @@ +/* -+ ** Copyright (C) 2008 The Android Open Source Project -+ ** Copyright (C) 2014 Canonical Ltd -+ ** -+ ** Adapted from the Android equivalent code for use in Ubuntu. -+ ** -+ ** 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_MEDIARECORDER_H -+#define ANDROID_MEDIARECORDER_H ++ * Copyright (C) 2013 Canonical Ltd ++ * ++ * 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. ++ * ++ * Authored by: Jim Hodapp ++ */ + -+#include -+#include -+#include -+#include -+#include -+#include -+#include ++#include ++#include + -+namespace android { ++#include + -+class Surface; -+class IMediaRecorder; -+class IMediaRecorderFactory; -+class ICamera; -+class ICameraRecordingProxy; -+class IGraphicBufferProducer; -+class Surface; ++#include + -+typedef void (*media_completion_f)(status_t status, void *cookie); ++#ifdef __cplusplus ++extern "C" { ++#endif + -+enum video_source { -+ VIDEO_SOURCE_DEFAULT = 0, -+ VIDEO_SOURCE_CAMERA = 1, -+ VIDEO_SOURCE_GRALLOC_BUFFER = 2, ++struct _MediaFormat : public RefBase ++{ ++ _MediaFormat() ++ : refcount(1) ++ { ++ } + -+ VIDEO_SOURCE_LIST_END // must be last - used to validate audio source type -+}; ++ AString mime; ++ int64_t duration_us; ++ int32_t width; ++ int32_t height; ++ int32_t max_input_size; + -+// Please update media/java/android/media/MediaRecorder.java if the following is updated. -+enum output_format { -+ OUTPUT_FORMAT_DEFAULT = 0, -+ OUTPUT_FORMAT_THREE_GPP = 1, -+ OUTPUT_FORMAT_MPEG_4 = 2, ++ unsigned int refcount; ++}; + ++#ifdef __cplusplus ++} ++#endif + -+ OUTPUT_FORMAT_AUDIO_ONLY_START = 3, // Used in validating the output format. Should be the -+ // at the start of the audio only output formats. ++#endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_format_layer_priv.h +@@ -0,0 +1,68 @@ ++/* ++ * Copyright (C) 2013 Canonical Ltd ++ * ++ * 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. ++ * ++ * Authored by: Jim Hodapp ++ */ + -+ /* These are audio only file formats */ -+ OUTPUT_FORMAT_RAW_AMR = 3, //to be backward compatible -+ OUTPUT_FORMAT_AMR_NB = 3, -+ OUTPUT_FORMAT_AMR_WB = 4, -+ OUTPUT_FORMAT_AAC_ADIF = 5, -+ OUTPUT_FORMAT_AAC_ADTS = 6, ++#ifndef MEDIA_FORMAT_LAYER_PRIV_H_ ++#define MEDIA_FORMAT_LAYER_PRIV_H_ + -+ /* Stream over a socket, limited to a single stream */ -+ OUTPUT_FORMAT_RTP_AVP = 7, ++#include ++#include + -+ /* H.264/AAC data encapsulated in MPEG2/TS */ -+ OUTPUT_FORMAT_MPEG2TS = 8, ++#include ++#include + -+ OUTPUT_FORMAT_LIST_END // must be last - used to validate format type -+}; ++#include + -+enum audio_encoder { -+ AUDIO_ENCODER_DEFAULT = 0, -+ AUDIO_ENCODER_AMR_NB = 1, -+ AUDIO_ENCODER_AMR_WB = 2, -+ AUDIO_ENCODER_AAC = 3, -+ AUDIO_ENCODER_HE_AAC = 4, -+ AUDIO_ENCODER_AAC_ELD = 5, ++struct _MediaFormat : public android::RefBase ++{ ++ _MediaFormat() ++ : duration_us(0), ++ width(0), ++ height(0), ++ max_input_size(0), ++ csd(NULL), ++ stride(0), ++ slice_height(0), ++ color_format(0), ++ crop_left(0), ++ crop_right(0), ++ crop_top(0), ++ crop_bottom(0), ++ refcount(1) ++ { ++ } + -+ AUDIO_ENCODER_LIST_END // must be the last - used to validate the audio encoder type -+}; ++ android::AString mime; ++ int64_t duration_us; ++ int32_t width; ++ int32_t height; ++ int32_t max_input_size; ++ android::AString csd_key_name; ++ android::sp csd; + -+enum video_encoder { -+ VIDEO_ENCODER_DEFAULT = 0, -+ VIDEO_ENCODER_H263 = 1, -+ VIDEO_ENCODER_H264 = 2, -+ VIDEO_ENCODER_MPEG_4_SP = 3, ++ int32_t stride; ++ int32_t slice_height; ++ int32_t color_format; ++ int32_t crop_left; ++ int32_t crop_right; ++ int32_t crop_top; ++ int32_t crop_bottom; + -+ VIDEO_ENCODER_LIST_END // must be the last - used to validate the video encoder type ++ unsigned int refcount; +}; + ++#endif // MEDIA_FORMAT_LAYER_PRIV_H_ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_message_layer.cpp +@@ -0,0 +1,205 @@ +/* -+ * The state machine of the media_recorder. ++ * Copyright (C) 2016 Canonical Ltd ++ * ++ * 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. ++ * ++ * Authored by: Simon Fels + */ -+enum media_recorder_states { -+ // Error state. -+ MEDIA_RECORDER_ERROR = 0, + -+ // Recorder was just created. -+ MEDIA_RECORDER_IDLE = 1 << 0, ++#define LOG_NDEBUG 0 ++#undef LOG_TAG ++#define LOG_TAG "MediaCompatibilityLayer" + -+ // Recorder has been initialized. -+ MEDIA_RECORDER_INITIALIZED = 1 << 1, ++#include + -+ // Configuration of the recorder has been completed. -+ MEDIA_RECORDER_DATASOURCE_CONFIGURED = 1 << 2, ++#include "media_message_priv.h" + -+ // Recorder is ready to start. -+ MEDIA_RECORDER_PREPARED = 1 << 3, ++MediaMessagePrivate* MediaMessagePrivate::toPrivate(MediaMessageWrapper *msg) ++{ ++ if (!msg) ++ return NULL; + -+ // Recording is in progress. -+ MEDIA_RECORDER_RECORDING = 1 << 4, -+}; ++ return static_cast(msg); ++} + -+// The "msg" code passed to the listener in notify. -+enum media_recorder_event_type { -+ MEDIA_RECORDER_EVENT_LIST_START = 1, -+ MEDIA_RECORDER_EVENT_ERROR = 1, -+ MEDIA_RECORDER_EVENT_INFO = 2, -+ MEDIA_RECORDER_EVENT_LIST_END = 99, ++MediaMessagePrivate::MediaMessagePrivate() : ++ msg(new android::AMessage) ++{ ++} + -+ // Track related event types -+ MEDIA_RECORDER_TRACK_EVENT_LIST_START = 100, -+ MEDIA_RECORDER_TRACK_EVENT_ERROR = 100, -+ MEDIA_RECORDER_TRACK_EVENT_INFO = 101, -+ MEDIA_RECORDER_TRACK_EVENT_LIST_END = 1000, -+}; ++MediaMessagePrivate::~MediaMessagePrivate() ++{ ++} + -+/* -+ * The (part of) "what" code passed to the listener in notify. -+ * When the error or info type is track specific, the what has -+ * the following layout: -+ * the left-most 16-bit is meant for error or info type. -+ * the right-most 4-bit is meant for track id. -+ * the rest is reserved. -+ * -+ * | track id | reserved | error or info type | -+ * 31 28 16 0 -+ * -+ */ -+enum media_recorder_error_type { -+ MEDIA_RECORDER_ERROR_UNKNOWN = 1, ++MediaMessageWrapper* media_message_create() ++{ ++ MediaMessagePrivate *d = new MediaMessagePrivate; ++ if (!d) ++ return NULL; + -+ // Track related error type -+ MEDIA_RECORDER_TRACK_ERROR_LIST_START = 100, -+ MEDIA_RECORDER_TRACK_ERROR_GENERAL = 100, -+ MEDIA_RECORDER_ERROR_VIDEO_NO_SYNC_FRAME = 200, -+ MEDIA_RECORDER_TRACK_ERROR_LIST_END = 1000, -+}; ++ return d; ++} + -+// The codes are distributed as follow: -+// 0xx: Reserved -+// 8xx: General info/warning -+// -+enum media_recorder_info_type { -+ MEDIA_RECORDER_INFO_UNKNOWN = 1, ++void media_message_release(MediaMessageWrapper *msg) ++{ ++ MediaMessagePrivate *d = MediaMessagePrivate::toPrivate(msg); ++ if (!d) ++ return; + -+ MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800, -+ MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801, ++ delete d; ++} + -+ // All track related informtional events start here -+ MEDIA_RECORDER_TRACK_INFO_LIST_START = 1000, -+ MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS = 1000, -+ MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME = 1001, -+ MEDIA_RECORDER_TRACK_INFO_TYPE = 1002, -+ MEDIA_RECORDER_TRACK_INFO_DURATION_MS = 1003, ++void media_message_clear(MediaMessageWrapper *msg) ++{ ++ MediaMessagePrivate *d = MediaMessagePrivate::toPrivate(msg); ++ if (!d) ++ return; + -+ // The time to measure the max chunk duration -+ MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS = 1004, ++ d->msg->clear(); ++} + -+ MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES = 1005, ++const char* media_message_dump(MediaMessageWrapper *msg) ++{ ++ MediaMessagePrivate *d = MediaMessagePrivate::toPrivate(msg); ++ if (!d) ++ return NULL; + -+ // The time to measure how well the audio and video -+ // track data is interleaved. -+ MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS = 1006, ++ return d->msg->debugString().c_str(); ++} + -+ // The time to measure system response. Note that -+ // the delay does not include the intentional delay -+ // we use to eliminate the recording sound. -+ MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS = 1007, ++void media_message_set_int32(MediaMessageWrapper *msg, const char *name, int32_t value) ++{ ++ MediaMessagePrivate *d = MediaMessagePrivate::toPrivate(msg); ++ if (!d) ++ return; + -+ // The time used to compensate for initial A/V sync. -+ MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS = 1008, ++ d->msg->setInt32(name, value); ++} + -+ // Total number of bytes of the media data. -+ MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES = 1009, ++void media_message_set_int64(MediaMessageWrapper *msg, const char *name, int64_t value) ++{ ++ MediaMessagePrivate *d = MediaMessagePrivate::toPrivate(msg); ++ if (!d) ++ return; + -+ MEDIA_RECORDER_TRACK_INFO_LIST_END = 2000, -+}; ++ d->msg->setInt64(name, value); ++} + -+class MediaPlayerService; ++void media_message_set_size(MediaMessageWrapper *msg, const char *name, ssize_t value) ++{ ++ MediaMessagePrivate *d = MediaMessagePrivate::toPrivate(msg); ++ if (!d) ++ return; + -+// ---------------------------------------------------------------------------- -+// ref-counted object for callbacks -+class MediaRecorderListener: virtual public RefBase ++ d->msg->setSize(name, value); ++} ++ ++void media_message_set_float(MediaMessageWrapper *msg, const char *name, float value) +{ -+public: -+ virtual void notify(int msg, int ext1, int ext2) = 0; -+ virtual void readAudio() = 0; -+}; ++ MediaMessagePrivate *d = MediaMessagePrivate::toPrivate(msg); ++ if (!d) ++ return; + -+class MediaRecorder : public BnMediaRecorderClient, -+ public virtual IMediaDeathNotifier ++ d->msg->setFloat(name, value); ++} ++ ++void media_message_set_double(MediaMessageWrapper *msg, const char *name, double value) +{ -+public: -+ MediaRecorder(); -+ ~MediaRecorder(); ++ MediaMessagePrivate *d = MediaMessagePrivate::toPrivate(msg); ++ if (!d) ++ return; + -+ void died(); -+ status_t initCheck(); -+ status_t setCamera(const sp& camera, const sp& proxy); -+ status_t setPreviewSurface(const sp& surface); -+ status_t setVideoSource(int vs); -+ status_t setAudioSource(int as); -+ status_t setOutputFormat(int of); -+ status_t setVideoEncoder(int ve); -+ status_t setAudioEncoder(int ae); -+ status_t setOutputFile(const char* path); -+ status_t setOutputFile(int fd, int64_t offset, int64_t length); -+ status_t setVideoSize(int width, int height); -+ status_t setVideoFrameRate(int frames_per_second); -+ status_t setParameters(const String8& params); -+ status_t setListener(const sp& listener); -+ status_t setClientName(const String16& clientName); -+ status_t prepare(); -+ status_t getMaxAmplitude(int* max); -+ status_t start(); -+ status_t stop(); -+ status_t reset(); -+ status_t init(); -+ status_t close(); -+ status_t release(); -+ void notify(int msg, int ext1, int ext2); -+ void readAudio(); -+ sp querySurfaceMediaSourceFromMediaServer(); ++ d->msg->setDouble(name, value); ++} + -+private: -+ void doCleanUp(); -+ status_t doReset(); ++void media_message_set_string(MediaMessageWrapper *msg, const char *name, const char *value, ssize_t len) ++{ ++ MediaMessagePrivate *d = MediaMessagePrivate::toPrivate(msg); ++ if (!d) ++ return; + -+ sp mMediaRecorder; -+ sp mListener; -+ sp mMediaRecorderFactory; + -+ // Reference to IGraphicBufferProducer -+ // for encoding GL Frames. That is useful only when the -+ // video source is set to VIDEO_SOURCE_GRALLOC_BUFFER -+ sp mSurfaceMediaSource; ++ d->msg->setString(name, value); ++} + -+ media_recorder_states mCurrentState; -+ bool mIsAudioSourceSet; -+ bool mIsVideoSourceSet; -+ bool mIsAudioEncoderSet; -+ bool mIsVideoEncoderSet; -+ bool mIsOutputFileSet; -+ Mutex mLock; -+ Mutex mNotifyLock; -+ Mutex mReadAudioLock; -+}; ++bool media_message_find_int32(MediaMessageWrapper *msg, const char *name, int32_t *value) ++{ ++ MediaMessagePrivate *d = MediaMessagePrivate::toPrivate(msg); ++ if (!d) ++ return false; + -+}; // namespace android ++ return d->msg->findInt32(name, value); ++} + -+#endif // ANDROID_MEDIARECORDER_H ++bool media_message_find_int64(MediaMessageWrapper *msg, const char *name, int64_t *value) ++{ ++ MediaMessagePrivate *d = MediaMessagePrivate::toPrivate(msg); ++ if (!d) ++ return false; ++ ++ int64_t v; ++ if (!d->msg->findInt64(name, &v)) ++ return false; ++ ++ if (value) ++ *value = v; ++ return true; ++} ++ ++bool media_message_find_size(MediaMessageWrapper *msg, const char *name, size_t *value) ++{ ++ MediaMessagePrivate *d = MediaMessagePrivate::toPrivate(msg); ++ if (!d) ++ return false; ++ ++ size_t v; ++ if (d->msg->findSize(name, &v)) ++ return false; ++ ++ if (value) ++ *value = v; ++ ++ return true; ++} ++ ++bool media_message_find_float(MediaMessageWrapper *msg, const char *name, float *value) ++{ ++ MediaMessagePrivate *d = MediaMessagePrivate::toPrivate(msg); ++ if (!d) ++ return false; ++ ++ float v; ++ if (!d->msg->findFloat(name, &v)) ++ return false; ++ ++ if (value) ++ *value = v; ++ ++ return true; ++} ++ ++bool media_message_find_double(MediaMessageWrapper *msg, const char *name, double *value) ++{ ++ MediaMessagePrivate *d = MediaMessagePrivate::toPrivate(msg); ++ if (!d) ++ return false; ++ ++ double v; ++ if (!d->msg->findDouble(name, &v)) ++ return false; ++ ++ if (value) ++ *value = v; ++ ++ return true; ++} --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_recorder_client.cpp -@@ -0,0 +1,319 @@ ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_message_priv.h +@@ -0,0 +1,37 @@ +/* -+ * Copyright (C) 2013-2014 Canonical Ltd ++ * Copyright (C) 2016 Canonical Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. @@ -6870,315 +7380,282 @@ + * See the License for the specific language governing permissions and + * limitations under the License. + * -+ * Authored by: Jim Hodapp ++ * Authored by: Simon Fels + */ + -+#include "media_recorder_client.h" ++#ifndef MEDIA_MESSAGE_PRIV_H_ ++#define MEDIA_MESSAGE_PRIV_H_ + -+#include -+#include ++#include + -+#define LOG_NDEBUG 0 -+#define LOG_TAG "MediaRecorderClient" ++#include + -+#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__) ++struct MediaMessagePrivate ++{ ++public: ++ static MediaMessagePrivate* toPrivate(MediaMessageWrapper *msg); + -+using namespace android; ++ explicit MediaMessagePrivate(); ++ virtual ~MediaMessagePrivate(); + -+MediaRecorderClient::MediaRecorderClient() -+{ -+ REPORT_FUNCTION(); ++ android::sp msg; ++}; + -+ sp service_manager = defaultServiceManager(); -+ sp service = service_manager->getService( -+ String16(IMediaRecorderObserver::exported_service_name())); ++#endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_meta_data_layer.cpp +@@ -0,0 +1,246 @@ ++/* ++ * Copyright (C) 2016 Canonical Ltd ++ * ++ * 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. ++ * ++ * Authored by: Simon Fels ++ */ + -+ media_recorder_observer = new BpMediaRecorderObserver(service); ++#define LOG_NDEBUG 0 ++#undef LOG_TAG ++#define LOG_TAG "MediaCompatibilityLayer" + -+ recorder = new android::StagefrightRecorder; -+} ++#include + -+MediaRecorderClient::~MediaRecorderClient() ++#include "media_meta_data_priv.h" ++ ++MediaMetaDataPrivate* MediaMetaDataPrivate::toPrivate(MediaMetaDataWrapper *md) +{ -+ REPORT_FUNCTION(); -+ release(); ++ if (!md) ++ return NULL; ++ ++ return static_cast(md); +} + -+status_t MediaRecorderClient::setCamera(const sp& camera, -+ const sp& proxy) ++MediaMetaDataPrivate::MediaMetaDataPrivate() : ++ data(new android::MetaData) +{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock lock(recorder_lock); -+ if (recorder == NULL) { -+ ALOGE("recorder must not be NULL"); -+ return NO_INIT; -+ } -+ return recorder->setCamera(camera, proxy); +} + -+status_t MediaRecorderClient::setPreviewSurface(const android::sp& surface) ++MediaMetaDataPrivate::MediaMetaDataPrivate(const android::sp &md) : ++ data(md) +{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock lock(recorder_lock); -+ if (recorder == NULL) { -+ ALOGE("recorder must not be NULL"); -+ return NO_INIT; -+ } -+ return recorder->setPreviewSurface(surface); +} + -+status_t MediaRecorderClient::setVideoSource(int vs) ++MediaMetaDataPrivate::~MediaMetaDataPrivate() +{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock lock(recorder_lock); -+ if (recorder == NULL) { -+ ALOGE("recorder must not be NULL"); -+ return NO_INIT; -+ } -+ return recorder->setVideoSource((android::video_source)vs); +} + -+status_t MediaRecorderClient::setAudioSource(int as) ++uint32_t media_meta_data_get_key_id(int key) +{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock lock(recorder_lock); -+ if (recorder == NULL) { -+ ALOGE("recorder must not be NULL"); -+ return NO_INIT; ++ switch (key) ++ { ++ case MEDIA_META_DATA_KEY_TIME: ++ return android::kKeyTime; ++ case MEDIA_META_DATA_KEY_IS_CODEC_CONFIG: ++ return android::kKeyIsCodecConfig; ++ case MEDIA_META_DATA_KEY_MIME: ++ return android::kKeyMIMEType; ++ case MEDIA_META_DATA_KEY_NUM_BUFFERS: ++ return android::kKeyNumBuffers; ++ case MEDIA_META_DATA_KEY_WIDTH: ++ return android::kKeyWidth; ++ case MEDIA_META_DATA_KEY_HEIGHT: ++ return android::kKeyHeight; ++ case MEDIA_META_DATA_KEY_STRIDE: ++ return android::kKeyStride; ++ case MEDIA_META_DATA_KEY_COLOR_FORMAT: ++ return android::kKeyColorFormat; ++ case MEDIA_META_DATA_KEY_SLICE_HEIGHT: ++ return android::kKeySliceHeight; ++ case MEDIA_META_DATA_KEY_FRAMERATE: ++ return android::kKeyFrameRate; ++ case MEDIA_META_DATA_KEY_MEDIA_BUFFER: ++ return 'mediaBuffer'; ++ default: ++ break; + } -+ return recorder->setAudioSource((audio_source_t)as); ++ ++ return 0; +} + -+status_t MediaRecorderClient::setOutputFormat(int of) ++MediaMetaDataWrapper* media_meta_data_create() +{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock lock(recorder_lock); -+ if (recorder == NULL) { -+ ALOGE("recorder must not be NULL"); -+ return NO_INIT; -+ } -+ return recorder->setOutputFormat((android::output_format)of); ++ MediaMetaDataPrivate *d = new MediaMetaDataPrivate; ++ if (!d) ++ return NULL; ++ ++ return d; +} + -+status_t MediaRecorderClient::setVideoEncoder(int ve) ++void media_meta_data_release(MediaMetaDataWrapper *meta_data) +{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock lock(recorder_lock); -+ if (recorder == NULL) { -+ ALOGE("recorder must not be NULL"); -+ return NO_INIT; -+ } -+ return recorder->setVideoEncoder((android::video_encoder)ve); ++ MediaMetaDataPrivate *d = MediaMetaDataPrivate::toPrivate(meta_data); ++ if (!d) ++ return; ++ ++ delete d; +} + -+status_t MediaRecorderClient::setAudioEncoder(int ae) ++void media_meta_data_clear(MediaMetaDataWrapper *meta_data) +{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock lock(recorder_lock); -+ if (recorder == NULL) { -+ ALOGE("recorder must not be NULL"); -+ return NO_INIT; -+ } -+ return recorder->setAudioEncoder((android::audio_encoder)ae); ++ MediaMetaDataPrivate *d = MediaMetaDataPrivate::toPrivate(meta_data); ++ if (!d || !d->data.get()) ++ return; ++ ++ d->data->clear(); +} + -+status_t MediaRecorderClient::setOutputFile(const char* path) ++bool media_meta_data_remove(MediaMetaDataWrapper *meta_data, uint32_t key) +{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock lock(recorder_lock); -+ if (recorder == NULL) { -+ ALOGE("recorder must not be NULL"); -+ return NO_INIT; -+ } -+ return recorder->setOutputFile(path); ++ MediaMetaDataPrivate *d = MediaMetaDataPrivate::toPrivate(meta_data); ++ if (!d || !d->data.get()) ++ return false; ++ ++ return d->data->remove(key); +} + -+status_t MediaRecorderClient::setOutputFile(int fd, int64_t offset, int64_t length) ++bool media_meta_data_set_cstring(MediaMetaDataWrapper *meta_data, uint32_t key, const char *value) +{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock lock(recorder_lock); -+ if (recorder == NULL) { -+ ALOGE("recorder must not be NULL"); -+ return NO_INIT; -+ } -+ return recorder->setOutputFile(fd, offset, length); -+} ++ MediaMetaDataPrivate *d = MediaMetaDataPrivate::toPrivate(meta_data); ++ if (!d || !d->data.get()) ++ return false; + -+status_t MediaRecorderClient::setVideoSize(int width, int height) -+{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock lock(recorder_lock); -+ if (recorder == NULL) { -+ ALOGE("recorder must not be NULL"); -+ return NO_INIT; -+ } -+ return recorder->setVideoSize(width, height); ++ android::status_t err = d->data->setCString(key, value); ++ return err == android::OK; +} + -+status_t MediaRecorderClient::setVideoFrameRate(int frames_per_second) ++bool media_meta_data_set_int32(MediaMetaDataWrapper *meta_data, uint32_t key, int32_t value) +{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock lock(recorder_lock); -+ if (recorder == NULL) { -+ ALOGE("recorder must not be NULL"); -+ return NO_INIT; -+ } -+ return recorder->setVideoFrameRate(frames_per_second); -+} ++ MediaMetaDataPrivate *d = MediaMetaDataPrivate::toPrivate(meta_data); ++ if (!d || !d->data.get()) ++ return false; + -+status_t MediaRecorderClient::setParameters(const android::String8& params) -+{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock lock(recorder_lock); -+ if (recorder == NULL) { -+ ALOGE("recorder must not be NULL"); -+ return NO_INIT; -+ } -+ return recorder->setParameters(params); ++ android::status_t err = d->data->setInt32(key, value); ++ return err == android::OK; +} + -+status_t MediaRecorderClient::setListener(const android::sp& listener) ++bool media_meta_data_set_int64(MediaMetaDataWrapper *meta_data, uint32_t key, int64_t value) +{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock lock(recorder_lock); -+ if (recorder == NULL) { -+ ALOGE("recorder must not be NULL"); -+ return NO_INIT; -+ } -+ return recorder->setListener(listener); -+} ++ MediaMetaDataPrivate *d = MediaMetaDataPrivate::toPrivate(meta_data); ++ if (!d || !d->data.get()) ++ return false; + -+status_t MediaRecorderClient::setClientName(const android::String16& clientName) -+{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock lock(recorder_lock); -+ if (recorder == NULL) { -+ ALOGE("recorder must not be NULL"); -+ return NO_INIT; -+ } -+ return recorder->setClientName(clientName); ++ android::status_t err = d->data->setInt64(key, value); ++ return err == android::OK; +} + -+status_t MediaRecorderClient::prepare() ++bool media_meta_data_set_float(MediaMetaDataWrapper *meta_data, uint32_t key, float value) +{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock lock(recorder_lock); -+ if (recorder == NULL) { -+ ALOGE("recorder must not be NULL"); -+ return NO_INIT; -+ } -+ return recorder->prepare(); ++ MediaMetaDataPrivate *d = MediaMetaDataPrivate::toPrivate(meta_data); ++ if (!d || !d->data.get()) ++ return false; ++ ++ android::status_t err = d->data->setFloat(key, value); ++ return err == android::OK; +} + -+status_t MediaRecorderClient::getMaxAmplitude(int* max) ++bool media_meta_data_set_pointer(MediaMetaDataWrapper *meta_data, uint32_t key, void *value) +{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock lock(recorder_lock); -+ if (recorder == NULL) { -+ ALOGE("recorder must not be NULL"); -+ return NO_INIT; -+ } -+ return recorder->getMaxAmplitude(max); ++ MediaMetaDataPrivate *d = MediaMetaDataPrivate::toPrivate(meta_data); ++ if (!d || !d->data.get()) ++ return false; ++ ++ android::status_t err = d->data->setPointer(key, value); ++ return err == android::OK; +} + -+status_t MediaRecorderClient::start() ++bool media_meta_data_find_cstring(MediaMetaDataWrapper *meta_data, uint32_t key, const char **value) +{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock lock(recorder_lock); -+ if (recorder == NULL) { -+ ALOGE("recorder must not be NULL"); -+ return NO_INIT; -+ } ++ MediaMetaDataPrivate *d = MediaMetaDataPrivate::toPrivate(meta_data); ++ if (!d || !d->data.get()) ++ return false; + -+ if (media_recorder_observer != NULL) -+ media_recorder_observer->recordingStarted(); ++ const char *v = NULL; ++ if (!d->data->findCString(key, &v)) ++ return false; + -+ return recorder->start(); ++ if (value) ++ *value = v; ++ ++ return true; +} + -+status_t MediaRecorderClient::stop() ++bool media_meta_data_find_int32(MediaMetaDataWrapper *meta_data, uint32_t key, int32_t *value) +{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock lock(recorder_lock); -+ if (recorder == NULL) { -+ ALOGE("recorder must not be NULL"); -+ return NO_INIT; -+ } ++ MediaMetaDataPrivate *d = MediaMetaDataPrivate::toPrivate(meta_data); ++ if (!d || !d->data.get()) ++ return false; + -+ if (media_recorder_observer != NULL) -+ media_recorder_observer->recordingStopped(); ++ int32_t v; ++ if (!d->data->findInt32(key, &v)) ++ return false; + -+ return recorder->stop(); -+} ++ if (value) ++ *value = v; + -+status_t MediaRecorderClient::reset() -+{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock lock(recorder_lock); -+ if (recorder == NULL) { -+ ALOGE("recorder must not be NULL"); -+ return NO_INIT; -+ } -+ return recorder->reset(); ++ return true; +} + -+status_t MediaRecorderClient::init() ++bool media_meta_data_find_int64(MediaMetaDataWrapper *meta_data, uint32_t key, int64_t *value) +{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock lock(recorder_lock); -+ if (recorder == NULL) { -+ ALOGE("recorder must not be NULL"); -+ return NO_INIT; -+ } -+ return recorder->init(); -+} ++ MediaMetaDataPrivate *d = MediaMetaDataPrivate::toPrivate(meta_data); ++ if (!d || !d->data.get()) ++ return false; + -+status_t MediaRecorderClient::close() -+{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock lock(recorder_lock); -+ if (recorder == NULL) { -+ ALOGE("recorder must not be NULL"); -+ return NO_INIT; -+ } -+ return recorder->close(); -+} ++ int64_t v; ++ if (!d->data->findInt64(key, &v)) ++ return false; + -+status_t MediaRecorderClient::release() -+{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock lock(recorder_lock); -+ if (recorder != NULL) { -+ delete recorder; -+ recorder = NULL; -+ } -+ return NO_ERROR; ++ if (value) ++ *value = v; ++ ++ return true; +} + -+status_t MediaRecorderClient::dump(int fd, const Vector& args) const ++bool media_meta_data_find_float(MediaMetaDataWrapper *meta_data, uint32_t key, float *value) +{ -+ REPORT_FUNCTION(); -+ if (recorder != NULL) { -+ return recorder->dump(fd, args); -+ } -+ return android::OK; ++ MediaMetaDataPrivate *d = MediaMetaDataPrivate::toPrivate(meta_data); ++ if (!d || !d->data.get()) ++ return false; ++ ++ float v; ++ if (!d->data->findFloat(key, &v)) ++ return false; ++ ++ if (value) ++ *value = v; ++ ++ return true; +} + -+sp MediaRecorderClient::querySurfaceMediaSource() ++bool media_meta_data_find_pointer(MediaMetaDataWrapper *meta_data, uint32_t key, void **value) +{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock lock(recorder_lock); -+ if (recorder == NULL) { -+ ALOGE("recorder is not initialized"); -+ return NULL; -+ } -+ return recorder->querySurfaceMediaSource(); ++ MediaMetaDataPrivate *d = MediaMetaDataPrivate::toPrivate(meta_data); ++ if (!d || !d->data.get()) ++ return false; ++ ++ void *v = NULL; ++ if (!d->data->findPointer(key, &v)) ++ return false; ++ ++ if (value) ++ *value = v; ++ ++ return true; +} --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_recorder_client.h -@@ -0,0 +1,78 @@ ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_meta_data_priv.h +@@ -0,0 +1,36 @@ +/* -+ * Copyright (C) 2013-2014 Canonical Ltd ++ * Copyright (C) 2016 Canonical Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. @@ -7192,1024 +7669,1057 @@ + * See the License for the specific language governing permissions and + * limitations under the License. + * -+ * Authored by: Jim Hodapp ++ * Authored by: Simon Fels + */ + -+#ifndef MEDIA_RECORDER_CLIENT_H_ -+#define MEDIA_RECORDER_CLIENT_H_ -+ -+#include -+#include -+ -+#include "media_recorder_observer.h" -+ -+#include -+ -+namespace android { ++#ifndef MEDIA_META_DATA_PRIV_H_ ++#define MEDIA_META_DATA_PRIV_H_ + -+class MediaRecorderBase; -+class Mutex; -+class BpMediaRecorderObserver; ++#include + -+/*! -+ * \brief The MediaRecorderClient struct wraps the service side of the MediaRecorder class -+ */ -+struct MediaRecorderClient : public BnMediaRecorder ++struct MediaMetaDataPrivate +{ +public: -+ MediaRecorderClient(); -+ virtual ~MediaRecorderClient(); ++ static MediaMetaDataPrivate* toPrivate(MediaMetaDataWrapper *md); + -+ virtual status_t setCamera(const sp& camera, -+ const sp& proxy); -+ virtual status_t setPreviewSurface(const sp& surface); -+ virtual status_t setVideoSource(int vs); -+ virtual status_t setAudioSource(int as); -+ virtual status_t setOutputFormat(int of); -+ virtual status_t setVideoEncoder(int ve); -+ virtual status_t setAudioEncoder(int ae); -+ virtual status_t setOutputFile(const char* path); -+ virtual status_t setOutputFile(int fd, int64_t offset, int64_t length); -+ virtual status_t setVideoSize(int width, int height); -+ virtual status_t setVideoFrameRate(int frames_per_second); -+ virtual status_t setParameters(const String8& params); -+ virtual status_t setListener(const sp& listener); -+ virtual status_t setClientName(const String16& clientName); -+ virtual status_t prepare(); -+ virtual status_t getMaxAmplitude(int* max); -+ virtual status_t start(); -+ virtual status_t stop(); -+ virtual status_t reset(); -+ virtual status_t init(); -+ virtual status_t close(); -+ virtual status_t release(); -+ virtual status_t dump(int fd, const Vector& args) const; -+ virtual sp querySurfaceMediaSource(); ++ MediaMetaDataPrivate(); ++ MediaMetaDataPrivate(const android::sp &md); ++ ~MediaMetaDataPrivate(); + -+private: -+ sp media_recorder_observer; -+ MediaRecorderBase *recorder; -+ Mutex recorder_lock; ++ android::sp data; +}; + -+} -+ +#endif --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_recorder_factory.cpp -@@ -0,0 +1,133 @@ ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_recorder.cpp +@@ -0,0 +1,748 @@ +/* -+ * Copyright (C) 2014 Canonical Ltd -+ * -+ * 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. -+ * -+ * Authored by: Jim Hodapp ++ ** Copyright (c) 2008 The Android Open Source Project ++ ** Copyright (C) 2014 Canonical Ltd ++ ** ++ ** Adapted from the Android equivalent code for use in Ubuntu. ++ ** ++ ** 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. + */ + -+//#define LOG_NDEBUG 0 -+#undef LOG_TAG -+#define LOG_TAG "MediaRecorderFactory" ++#define LOG_NDEBUG 0 ++#define LOG_TAG "MediaRecorder" + ++#include "media_recorder.h" +#include "media_recorder_factory.h" -+#include "media_recorder_client.h" -+#include -+ -+#include -+#include -+#include + +#include -+#include -+ -+#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__) ++#include ++#include ++#include ++#include ++#include // for MEDIA_ERROR_SERVER_DIED ++#include + +namespace android { + -+enum { -+ CREATE_MEDIA_RECORDER = IBinder::FIRST_CALL_TRANSACTION, -+}; -+ -+class BpMediaRecorderFactory: public BpInterface ++status_t MediaRecorder::setCamera(const sp& camera, const sp& proxy) +{ -+public: -+ BpMediaRecorderFactory(const sp& impl) -+ : BpInterface(impl) -+ { ++ ALOGV("setCamera(%p,%p)", camera.get(), proxy.get()); ++ if (mMediaRecorder == NULL) { ++ ALOGE("media recorder is not initialized yet"); ++ return INVALID_OPERATION; + } -+ -+ virtual sp createMediaRecorder() -+ { -+ Parcel data, reply; -+ data.writeInterfaceToken(IMediaRecorderFactory::getInterfaceDescriptor()); -+ remote()->transact(CREATE_MEDIA_RECORDER, data, &reply); -+ return interface_cast(reply.readStrongBinder()); ++ if (!(mCurrentState & MEDIA_RECORDER_IDLE)) { ++ ALOGE("setCamera called in an invalid state(%d)", mCurrentState); ++ return INVALID_OPERATION; + } -+}; + -+// ---------------------------------------------------------------------------- ++ status_t ret = mMediaRecorder->setCamera(camera, proxy); ++ if (OK != ret) { ++ ALOGV("setCamera failed: %d", ret); ++ mCurrentState = MEDIA_RECORDER_ERROR; ++ return ret; ++ } ++ return ret; ++} + -+IMPLEMENT_META_INTERFACE(MediaRecorderFactory, "android.media.IMediaRecorderFactory"); ++status_t MediaRecorder::setPreviewSurface(const sp& surface) ++{ ++ ALOGV("setPreviewSurface(%p)", surface.get()); ++ if (mMediaRecorder == NULL) { ++ ALOGE("media recorder is not initialized yet"); ++ return INVALID_OPERATION; ++ } ++ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { ++ ALOGE("setPreviewSurface called in an invalid state(%d)", mCurrentState); ++ return INVALID_OPERATION; ++ } ++ if (!mIsVideoSourceSet) { ++ ALOGE("try to set preview surface without setting the video source first"); ++ return INVALID_OPERATION; ++ } + -+// ---------------------------------------------------------------------- ++ status_t ret = mMediaRecorder->setPreviewSurface(surface); ++ if (OK != ret) { ++ ALOGV("setPreviewSurface failed: %d", ret); ++ mCurrentState = MEDIA_RECORDER_ERROR; ++ return ret; ++ } ++ return ret; ++} + -+status_t BnMediaRecorderFactory::onTransact( -+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) ++status_t MediaRecorder::init() +{ -+ switch (code) { -+ case CREATE_MEDIA_RECORDER: { -+ CHECK_INTERFACE(IMediaRecorderFactory, data, reply); -+ sp recorder = createMediaRecorder(); -+ reply->writeStrongBinder(recorder->asBinder()); -+ return NO_ERROR; -+ } break; -+ default: -+ return BBinder::onTransact(code, data, reply, flags); ++ ALOGV("init"); ++ if (mMediaRecorder == NULL) { ++ ALOGE("media recorder is not initialized yet"); ++ return INVALID_OPERATION; ++ } ++ if (!(mCurrentState & MEDIA_RECORDER_IDLE)) { ++ ALOGE("init called in an invalid state(%d)", mCurrentState); ++ return INVALID_OPERATION; + } -+} + -+// ---------------------------------------------------------------------------- ++ status_t ret = mMediaRecorder->init(); ++ if (OK != ret) { ++ ALOGV("init failed: %d", ret); ++ mCurrentState = MEDIA_RECORDER_ERROR; ++ return ret; ++ } + -+sp MediaRecorderFactory::media_recorder_factory; -+Mutex MediaRecorderFactory::s_lock; ++ ret = mMediaRecorder->setListener(this); ++ if (OK != ret) { ++ ALOGV("setListener failed: %d", ret); ++ mCurrentState = MEDIA_RECORDER_ERROR; ++ return ret; ++ } + -+MediaRecorderFactory::MediaRecorderFactory() -+{ -+ REPORT_FUNCTION(); ++ mCurrentState = MEDIA_RECORDER_INITIALIZED; ++ return ret; +} + -+MediaRecorderFactory::~MediaRecorderFactory() ++status_t MediaRecorder::setVideoSource(int vs) +{ -+ REPORT_FUNCTION(); ++ ALOGV("setVideoSource(%d)", vs); ++ if (mMediaRecorder == NULL) { ++ ALOGE("media recorder is not initialized yet"); ++ return INVALID_OPERATION; ++ } ++ if (mIsVideoSourceSet) { ++ ALOGE("video source has already been set"); ++ return INVALID_OPERATION; ++ } ++ if (mCurrentState & MEDIA_RECORDER_IDLE) { ++ ALOGV("Call init() since the media recorder is not initialized yet"); ++ status_t ret = init(); ++ if (OK != ret) { ++ return ret; ++ } ++ } ++ if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { ++ ALOGE("setVideoSource called in an invalid state(%d)", mCurrentState); ++ return INVALID_OPERATION; ++ } ++ ++ // following call is made over the Binder Interface ++ status_t ret = mMediaRecorder->setVideoSource(vs); ++ ++ if (OK != ret) { ++ ALOGV("setVideoSource failed: %d", ret); ++ mCurrentState = MEDIA_RECORDER_ERROR; ++ return ret; ++ } ++ mIsVideoSourceSet = true; ++ return ret; +} + -+/*! -+ * \brief Creates and adds the MediaRecorderFactory service to the default Binder ServiceManager -+ */ -+void MediaRecorderFactory::instantiate() ++status_t MediaRecorder::setAudioSource(int as) +{ -+ defaultServiceManager()->addService( -+ String16(IMediaRecorderFactory::exported_service_name()), factory_instance()); -+ ALOGV("Added Binder service '%s' to ServiceManager", IMediaRecorderFactory::exported_service_name()); ++ ALOGV("setAudioSource(%d)", as); ++ if (mMediaRecorder == NULL) { ++ ALOGE("media recorder is not initialized yet"); ++ return INVALID_OPERATION; ++ } ++ if (mCurrentState & MEDIA_RECORDER_IDLE) { ++ ALOGV("Call init() since the media recorder is not initialized yet"); ++ status_t ret = init(); ++ if (OK != ret) { ++ return ret; ++ } ++ } ++ if (mIsAudioSourceSet) { ++ ALOGE("audio source has already been set"); ++ return INVALID_OPERATION; ++ } ++ if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { ++ ALOGE("setAudioSource called in an invalid state(%d)", mCurrentState); ++ return INVALID_OPERATION; ++ } ++ ++ status_t ret = mMediaRecorder->setAudioSource(as); ++ if (OK != ret) { ++ ALOGV("setAudioSource failed: %d", ret); ++ mCurrentState = MEDIA_RECORDER_ERROR; ++ return ret; ++ } ++ mIsAudioSourceSet = true; ++ return ret; +} + -+/*! -+ * \brief Creates a new MediaRecorderClient instance over Binder -+ * \return A new MediaRecorderClient instance -+ */ -+sp MediaRecorderFactory::createMediaRecorder() ++status_t MediaRecorder::setOutputFormat(int of) +{ -+ REPORT_FUNCTION(); -+ sp recorder = new MediaRecorderClient(); -+ return recorder; ++ ALOGV("setOutputFormat(%d)", of); ++ if (mMediaRecorder == NULL) { ++ ALOGE("media recorder is not initialized yet"); ++ return INVALID_OPERATION; ++ } ++ if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { ++ ALOGE("setOutputFormat called in an invalid state: %d", mCurrentState); ++ return INVALID_OPERATION; ++ } ++ if (mIsVideoSourceSet && of >= OUTPUT_FORMAT_AUDIO_ONLY_START && of != OUTPUT_FORMAT_RTP_AVP && of != OUTPUT_FORMAT_MPEG2TS) { //first non-video output format ++ ALOGE("output format (%d) is meant for audio recording only and incompatible with video recording", of); ++ return INVALID_OPERATION; ++ } ++ ++ status_t ret = mMediaRecorder->setOutputFormat(of); ++ if (OK != ret) { ++ ALOGE("setOutputFormat failed: %d", ret); ++ mCurrentState = MEDIA_RECORDER_ERROR; ++ return ret; ++ } ++ mCurrentState = MEDIA_RECORDER_DATASOURCE_CONFIGURED; ++ return ret; +} + -+/*! -+ * \brief Get a reference to the MediaRecorderFactory singleton instance -+ * \return The MediaRecorderFactory singleton instance -+ */ -+sp& MediaRecorderFactory::factory_instance() ++status_t MediaRecorder::setVideoEncoder(int ve) +{ -+ REPORT_FUNCTION(); -+ Mutex::Autolock _l(s_lock); -+ if (media_recorder_factory == NULL) -+ { -+ ALOGD("Creating new static instance of MediaRecorderFactory"); -+ media_recorder_factory = new MediaRecorderFactory(); ++ ALOGV("setVideoEncoder(%d)", ve); ++ if (mMediaRecorder == NULL) { ++ ALOGE("media recorder is not initialized yet"); ++ return INVALID_OPERATION; ++ } ++ if (!mIsVideoSourceSet) { ++ ALOGE("try to set the video encoder without setting the video source first"); ++ return INVALID_OPERATION; ++ } ++ if (mIsVideoEncoderSet) { ++ ALOGE("video encoder has already been set"); ++ return INVALID_OPERATION; ++ } ++ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { ++ ALOGE("setVideoEncoder called in an invalid state(%d)", mCurrentState); ++ return INVALID_OPERATION; + } + -+ return media_recorder_factory; ++ status_t ret = mMediaRecorder->setVideoEncoder(ve); ++ if (OK != ret) { ++ ALOGV("setVideoEncoder failed: %d", ret); ++ mCurrentState = MEDIA_RECORDER_ERROR; ++ return ret; ++ } ++ mIsVideoEncoderSet = true; ++ return ret; +} + -+} // namespace android ---- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_recorder_factory.h -@@ -0,0 +1,72 @@ -+/* -+ * Copyright (C) 2014 Canonical Ltd -+ * -+ * 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. -+ * -+ * Authored by: Jim Hodapp -+ */ ++status_t MediaRecorder::setAudioEncoder(int ae) ++{ ++ ALOGV("setAudioEncoder(%d)", ae); ++ if (mMediaRecorder == NULL) { ++ ALOGE("media recorder is not initialized yet"); ++ return INVALID_OPERATION; ++ } ++ if (!mIsAudioSourceSet) { ++ ALOGE("try to set the audio encoder without setting the audio source first"); ++ return INVALID_OPERATION; ++ } ++ if (mIsAudioEncoderSet) { ++ ALOGE("audio encoder has already been set"); ++ return INVALID_OPERATION; ++ } ++ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { ++ ALOGE("setAudioEncoder called in an invalid state(%d)", mCurrentState); ++ return INVALID_OPERATION; ++ } + -+#ifndef MEDIA_RECORDER_FACTORY_H_ -+#define MEDIA_RECORDER_FACTORY_H_ ++ status_t ret = mMediaRecorder->setAudioEncoder(ae); ++ if (OK != ret) { ++ ALOGV("setAudioEncoder failed: %d", ret); ++ mCurrentState = MEDIA_RECORDER_ERROR; ++ return ret; ++ } ++ mIsAudioEncoderSet = true; ++ return ret; ++} ++#if ANDROID_VERSION_MAJOR<=5 ++status_t MediaRecorder::setOutputFile(const char* path) ++{ ++ ALOGV("setOutputFile(%s)", path); ++ if (mMediaRecorder == NULL) { ++ ALOGE("media recorder is not initialized yet"); ++ return INVALID_OPERATION; ++ } ++ if (mIsOutputFileSet) { ++ ALOGE("output file has already been set"); ++ return INVALID_OPERATION; ++ } ++ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { ++ ALOGE("setOutputFile called in an invalid state(%d)", mCurrentState); ++ return INVALID_OPERATION; ++ } + -+#include ++ status_t ret = mMediaRecorder->setOutputFile(path); ++ if (OK != ret) { ++ ALOGV("setOutputFile failed: %d", ret); ++ mCurrentState = MEDIA_RECORDER_ERROR; ++ return ret; ++ } ++ mIsOutputFileSet = true; ++ return ret; ++} ++#endif + -+#include -+#include ++status_t MediaRecorder::setOutputFile(int fd, int64_t offset, int64_t length) ++{ ++ ALOGV("setOutputFile(%d, %lld, %lld)", fd, offset, length); ++ if (mMediaRecorder == NULL) { ++ ALOGE("media recorder is not initialized yet"); ++ return INVALID_OPERATION; ++ } ++ if (mIsOutputFileSet) { ++ ALOGE("output file has already been set"); ++ return INVALID_OPERATION; ++ } ++ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { ++ ALOGE("setOutputFile called in an invalid state(%d)", mCurrentState); ++ return INVALID_OPERATION; ++ } + -+namespace android { ++ // It appears that if an invalid file descriptor is passed through ++ // binder calls, the server-side of the inter-process function call ++ // is skipped. As a result, the check at the server-side to catch ++ // the invalid file descritpor never gets invoked. This is to workaround ++ // this issue by checking the file descriptor first before passing ++ // it through binder call. ++ if (fd < 0) { ++ ALOGE("Invalid file descriptor: %d", fd); ++ return BAD_VALUE; ++ } + -+class Mutex; ++ status_t ret = mMediaRecorder->setOutputFile(fd, offset, length); ++ if (OK != ret) { ++ ALOGV("setOutputFile failed: %d", ret); ++ mCurrentState = MEDIA_RECORDER_ERROR; ++ return ret; ++ } ++ mIsOutputFileSet = true; ++ return ret; ++} + -+class IMediaRecorderFactory: public IInterface ++status_t MediaRecorder::setVideoSize(int width, int height) +{ -+public: -+ DECLARE_META_INTERFACE(MediaRecorderFactory); -+ -+ static const char* exported_service_name() { return "android.media.IMediaRecorderFactory"; } ++ ALOGV("setVideoSize(%d, %d)", width, height); ++ if (mMediaRecorder == NULL) { ++ ALOGE("media recorder is not initialized yet"); ++ return INVALID_OPERATION; ++ } ++ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { ++ ALOGE("setVideoSize called in an invalid state: %d", mCurrentState); ++ return INVALID_OPERATION; ++ } ++ if (!mIsVideoSourceSet) { ++ ALOGE("Cannot set video size without setting video source first"); ++ return INVALID_OPERATION; ++ } + -+ virtual sp createMediaRecorder() = 0; -+}; ++ status_t ret = mMediaRecorder->setVideoSize(width, height); ++ if (OK != ret) { ++ ALOGE("setVideoSize failed: %d", ret); ++ mCurrentState = MEDIA_RECORDER_ERROR; ++ return ret; ++ } + -+// ---------------------------------------------------------------------------- ++ return ret; ++} + -+class BnMediaRecorderFactory: public BnInterface ++// Query a SurfaceMediaSurface through the Mediaserver, over the ++// binder interface. This is used by the Filter Framework (MediaEncoder) ++// to get an object to hook up to ANativeWindow. ++sp MediaRecorder:: ++ querySurfaceMediaSourceFromMediaServer() +{ -+public: -+ virtual status_t onTransact( uint32_t code, -+ const Parcel& data, -+ Parcel* reply, -+ uint32_t flags = 0); -+}; -+ -+// ---------------------------------------------------------------------------- ++ Mutex::Autolock _l(mLock); ++ mSurfaceMediaSource = ++ mMediaRecorder->querySurfaceMediaSource(); ++ if (mSurfaceMediaSource == NULL) { ++ ALOGE("SurfaceMediaSource could not be initialized!"); ++ } ++ return mSurfaceMediaSource; ++} + -+class MediaRecorderFactory : public BnMediaRecorderFactory ++status_t MediaRecorder::setVideoFrameRate(int frames_per_second) +{ -+public: -+ MediaRecorderFactory(); -+ virtual ~MediaRecorderFactory(); -+ -+ static void instantiate(); -+ -+ virtual sp createMediaRecorder(); -+private: -+ static sp& factory_instance(); -+ -+ static sp media_recorder_factory; -+ static Mutex s_lock; -+}; ++ ALOGV("setVideoFrameRate(%d)", frames_per_second); ++ if (mMediaRecorder == NULL) { ++ ALOGE("media recorder is not initialized yet"); ++ return INVALID_OPERATION; ++ } ++ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { ++ ALOGE("setVideoFrameRate called in an invalid state: %d", mCurrentState); ++ return INVALID_OPERATION; ++ } ++ if (!mIsVideoSourceSet) { ++ ALOGE("Cannot set video frame rate without setting video source first"); ++ return INVALID_OPERATION; ++ } + ++ status_t ret = mMediaRecorder->setVideoFrameRate(frames_per_second); ++ if (OK != ret) { ++ ALOGE("setVideoFrameRate failed: %d", ret); ++ mCurrentState = MEDIA_RECORDER_ERROR; ++ return ret; ++ } ++ return ret; +} + -+#endif ---- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_recorder_layer.cpp -@@ -0,0 +1,506 @@ -+/* -+ * Copyright (C) 2013-2014 Canonical Ltd -+ * -+ * 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. -+ * -+ * Authored by: Jim Hodapp -+ * Guenter Schwann -+ * Ricardo Salveti de Araujo -+ */ -+ -+#define LOG_NDEBUG 0 -+#undef LOG_TAG -+#define LOG_TAG "MediaRecorderCompatibilityLayer" ++status_t MediaRecorder::setParameters(const String8& params) { ++ ALOGV("setParameters(%s)", params.string()); ++ if (mMediaRecorder == NULL) { ++ ALOGE("media recorder is not initialized yet"); ++ return INVALID_OPERATION; ++ } + -+#include "media_recorder.h" ++ bool isInvalidState = (mCurrentState & ++ (MEDIA_RECORDER_PREPARED | ++ MEDIA_RECORDER_RECORDING | ++ MEDIA_RECORDER_ERROR)); ++ if (isInvalidState) { ++ ALOGE("setParameters is called in an invalid state: %d", mCurrentState); ++ return INVALID_OPERATION; ++ } + -+#include -+#include ++ status_t ret = mMediaRecorder->setParameters(params); ++ if (OK != ret) { ++ ALOGE("setParameters(%s) failed: %d", params.string(), ret); ++ // Do not change our current state to MEDIA_RECORDER_ERROR, failures ++ // of the only currently supported parameters, "max-duration" and ++ // "max-filesize" are _not_ fatal. ++ } + -+#include -+#include ++ return ret; ++} + -+#include -+#include -+#include -+ -+#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__) -+ -+using namespace android; -+ -+/*! -+ * \brief The MediaRecorderListenerWrapper class is used to listen to camera events -+ * from the MediaRecorder instance -+ */ -+class MediaRecorderListenerWrapper : public android::MediaRecorderListener -+{ -+public: -+ MediaRecorderListenerWrapper() -+ : error_cb(NULL), -+ error_context(NULL), -+ read_audio_cb(NULL), -+ read_audio_context(NULL) ++status_t MediaRecorder::prepare() +{ -+} -+ -+ void notify(int msg, int ext1, int ext2) -+ { -+ ALOGV("\tmsg: %d, ext1: %d, ext2: %d \n", msg, ext1, ext2); -+ -+ switch (msg) { -+ case android::MEDIA_RECORDER_EVENT_ERROR: -+ ALOGV("\tMEDIA_RECORDER_EVENT_ERROR msg\n"); -+ // TODO: Extend this cb to include the error message -+ if (error_cb != NULL) -+ error_cb(error_context); -+ else -+ ALOGE("Failed to signal error to app layer, callback not set."); -+ break; -+ default: -+ ALOGV("\tUnknown notification\n"); -+ } ++ ALOGV("prepare"); ++ if (mMediaRecorder == NULL) { ++ ALOGE("media recorder is not initialized yet"); ++ return INVALID_OPERATION; + } -+ -+ void readAudio() -+ { -+ REPORT_FUNCTION(); -+ if (read_audio_cb != NULL) { -+ read_audio_cb(read_audio_context); ++ if (!(mCurrentState & MEDIA_RECORDER_DATASOURCE_CONFIGURED)) { ++ ALOGE("prepare called in an invalid state: %d", mCurrentState); ++ return INVALID_OPERATION; ++ } ++ if (mIsAudioSourceSet != mIsAudioEncoderSet) { ++ if (mIsAudioSourceSet) { ++ ALOGE("audio source is set, but audio encoder is not set"); ++ } else { // must not happen, since setAudioEncoder checks this already ++ ALOGE("audio encoder is set, but audio source is not set"); + } -+ else -+ ALOGW("Failed to call read_audio_cb since it's NULL"); ++ return INVALID_OPERATION; + } + -+ void setErrorCb(on_recorder_msg_error cb, void *context) -+ { -+ REPORT_FUNCTION(); -+ error_cb = cb; -+ error_context = context; ++ if (mIsVideoSourceSet != mIsVideoEncoderSet) { ++ if (mIsVideoSourceSet) { ++ ALOGE("video source is set, but video encoder is not set"); ++ } else { // must not happen, since setVideoEncoder checks this already ++ ALOGE("video encoder is set, but video source is not set"); ++ } ++ return INVALID_OPERATION; + } + -+ void setReadAudioCb(on_recorder_read_audio cb, void *context) -+ { -+ REPORT_FUNCTION(); -+ read_audio_cb = cb; -+ read_audio_context = context; ++ status_t ret = mMediaRecorder->prepare(); ++ if (OK != ret) { ++ ALOGE("prepare failed: %d", ret); ++ mCurrentState = MEDIA_RECORDER_ERROR; ++ return ret; + } -+ -+private: -+ on_recorder_msg_error error_cb; -+ void *error_context; -+ on_recorder_read_audio read_audio_cb; -+ void *read_audio_context; -+}; -+ -+/*! -+ * \brief The MediaRecorderWrapper struct wraps the MediaRecorder class -+ */ -+struct MediaRecorderWrapper : public android::MediaRecorder -+{ -+public: -+ MediaRecorderWrapper() -+ : MediaRecorder(), -+ media_recorder_listener(new MediaRecorderListenerWrapper()) -+{ ++ mCurrentState = MEDIA_RECORDER_PREPARED; ++ return ret; +} + -+ ~MediaRecorderWrapper() -+ { -+ reset(); -+ } -+ -+ void init() -+ { -+ setListener(media_recorder_listener); ++status_t MediaRecorder::getMaxAmplitude(int* max) ++{ ++ ALOGV("getMaxAmplitude"); ++ if (mMediaRecorder == NULL) { ++ ALOGE("media recorder is not initialized yet"); ++ return INVALID_OPERATION; + } -+ -+ void setErrorCb(on_recorder_msg_error cb, void *context) -+ { -+ REPORT_FUNCTION(); -+ -+ assert(media_recorder_listener != NULL); -+ media_recorder_listener->setErrorCb(cb, context); ++ if (mCurrentState & MEDIA_RECORDER_ERROR) { ++ ALOGE("getMaxAmplitude called in an invalid state: %d", mCurrentState); ++ return INVALID_OPERATION; + } + -+ void setAudioReadCb(on_recorder_read_audio cb, void *context) -+ { -+ REPORT_FUNCTION(); -+ -+ assert(media_recorder_listener != NULL); -+ media_recorder_listener->setReadAudioCb(cb, context); ++ status_t ret = mMediaRecorder->getMaxAmplitude(max); ++ if (OK != ret) { ++ ALOGE("getMaxAmplitude failed: %d", ret); ++ mCurrentState = MEDIA_RECORDER_ERROR; ++ return ret; + } ++ return ret; ++} + -+private: -+ android::sp media_recorder_listener; -+}; -+ -+/*! -+ * \brief android_recorder_set_error_cb -+ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() -+ * \param cb The callback function to be called when a recording error occurs -+ * \param user context to pass through to the error handler -+ */ -+void android_recorder_set_error_cb(MediaRecorderWrapper *mr, on_recorder_msg_error cb, -+ void *context) ++status_t MediaRecorder::start() +{ -+ REPORT_FUNCTION(); -+ -+ if (mr == NULL) { -+ ALOGE("mr must not be NULL"); -+ return; ++ ALOGV("start"); ++ if (mMediaRecorder == NULL) { ++ ALOGE("media recorder is not initialized yet"); ++ return INVALID_OPERATION; ++ } ++ if (!(mCurrentState & MEDIA_RECORDER_PREPARED)) { ++ ALOGE("start called in an invalid state: %d", mCurrentState); ++ return INVALID_OPERATION; + } + -+ mr->setErrorCb(cb, context); ++ status_t ret = mMediaRecorder->start(); ++ if (OK != ret) { ++ ALOGE("start failed: %d", ret); ++ mCurrentState = MEDIA_RECORDER_ERROR; ++ return ret; ++ } ++ mCurrentState = MEDIA_RECORDER_RECORDING; ++ return ret; +} + -+void android_recorder_set_audio_read_cb(MediaRecorderWrapper *mr, on_recorder_read_audio cb, -+ void *context) ++status_t MediaRecorder::stop() +{ -+ REPORT_FUNCTION(); ++ ALOGV("stop"); ++ if (mMediaRecorder == NULL) { ++ ALOGE("media recorder is not initialized yet"); ++ return INVALID_OPERATION; ++ } ++ if (!(mCurrentState & MEDIA_RECORDER_RECORDING)) { ++ ALOGE("stop called in an invalid state: %d", mCurrentState); ++ return INVALID_OPERATION; ++ } + -+ if (mr == NULL) { -+ ALOGE("mr must not be NULL"); -+ return; ++ status_t ret = mMediaRecorder->stop(); ++ if (OK != ret) { ++ ALOGE("stop failed: %d", ret); ++ mCurrentState = MEDIA_RECORDER_ERROR; ++ return ret; + } + -+ mr->setAudioReadCb(cb, context); ++ // FIXME: ++ // stop and reset are semantically different. ++ // We treat them the same for now, and will change this in the future. ++ doCleanUp(); ++ mCurrentState = MEDIA_RECORDER_IDLE; ++ return ret; +} + -+/*! -+ * \brief android_media_new_recorder creates a new MediaRecorder -+ * \return New MediaRecorder object, or NULL if the object could not be created. -+ */ -+MediaRecorderWrapper *android_media_new_recorder() ++// Reset should be OK in any state ++status_t MediaRecorder::reset() +{ -+ REPORT_FUNCTION(); -+ -+ MediaRecorderWrapper *mr = new MediaRecorderWrapper; -+ if (mr == NULL) { -+ ALOGE("Failed to create new MediaRecorder instance."); -+ return NULL; ++ ALOGV("reset"); ++ if (mMediaRecorder == NULL) { ++ ALOGE("media recorder is not initialized yet"); ++ return INVALID_OPERATION; + } + -+ return mr; -+} ++ doCleanUp(); ++ status_t ret = UNKNOWN_ERROR; ++ switch (mCurrentState) { ++ case MEDIA_RECORDER_IDLE: ++ ret = OK; ++ break; + -+/*! -+ * \brief android_recorder_initCheck -+ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() -+ * \return negative value if an error occured -+ */ -+int android_recorder_initCheck(MediaRecorderWrapper *mr) -+{ -+ REPORT_FUNCTION(); ++ case MEDIA_RECORDER_RECORDING: ++ case MEDIA_RECORDER_DATASOURCE_CONFIGURED: ++ case MEDIA_RECORDER_PREPARED: ++ case MEDIA_RECORDER_ERROR: { ++ ret = doReset(); ++ if (OK != ret) { ++ return ret; // No need to continue ++ } ++ } // Intentional fall through ++ case MEDIA_RECORDER_INITIALIZED: ++ ret = close(); ++ break; + -+ if (mr == NULL) { -+ ALOGE("mr must not be NULL"); -+ return android::BAD_VALUE; ++ default: { ++ ALOGE("Unexpected non-existing state: %d", mCurrentState); ++ break; ++ } + } -+ -+ return mr->initCheck(); ++ return ret; +} + -+/*! -+ * \brief android_recorder_setCamera sets the camera object for recording videos from the camera -+ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() -+ * \param control Wrapper for the camera (see camera in hybris) -+ * \return negative value if an error occured -+ */ -+int android_recorder_setCamera(MediaRecorderWrapper *mr, CameraControl* control) ++status_t MediaRecorder::close() +{ -+ REPORT_FUNCTION(); -+ -+ if (mr == NULL) { -+ ALOGE("mr must not be NULL"); -+ return android::BAD_VALUE; ++ ALOGV("close"); ++ if (!(mCurrentState & MEDIA_RECORDER_INITIALIZED)) { ++ ALOGE("close called in an invalid state: %d", mCurrentState); ++ return INVALID_OPERATION; + } -+ if (control == NULL) { -+ ALOGE("control must not be NULL"); -+ return android::BAD_VALUE; ++ status_t ret = mMediaRecorder->close(); ++ if (OK != ret) { ++ ALOGE("close failed: %d", ret); ++ mCurrentState = MEDIA_RECORDER_ERROR; ++ return UNKNOWN_ERROR; ++ } else { ++ mCurrentState = MEDIA_RECORDER_IDLE; + } -+ -+ mr->init(); -+ -+ return mr->setCamera(control->camera->remote(), control->camera->getRecordingProxy()); ++ return ret; +} + -+/*! -+ * \brief android_recorder_setVideoSource sets the video source. -+ * If no video source is set, only audio is recorded. -+ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() -+ * \param vs The video source. It's either a camera or a gralloc buffer -+ * \return negative value if an error occured -+ */ -+int android_recorder_setVideoSource(MediaRecorderWrapper *mr, VideoSource vs) ++status_t MediaRecorder::doReset() +{ -+ REPORT_FUNCTION(); -+ -+ if (mr == NULL) { -+ ALOGE("mr must not be NULL"); -+ return android::BAD_VALUE; ++ ALOGV("doReset"); ++ status_t ret = mMediaRecorder->reset(); ++ if (OK != ret) { ++ ALOGE("doReset failed: %d", ret); ++ mCurrentState = MEDIA_RECORDER_ERROR; ++ return ret; ++ } else { ++ mCurrentState = MEDIA_RECORDER_INITIALIZED; + } -+ -+ return mr->setVideoSource(static_cast(vs)); ++ return ret; +} + -+/*! -+ * \brief android_recorder_setAudioSource -+ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() -+ * \param as The audio source. -+ * \return negative value if an error occured -+ */ -+int android_recorder_setAudioSource(MediaRecorderWrapper *mr, AudioSource as) ++void MediaRecorder::doCleanUp() +{ -+ REPORT_FUNCTION(); ++ ALOGV("doCleanUp"); ++ mIsAudioSourceSet = false; ++ mIsVideoSourceSet = false; ++ mIsAudioEncoderSet = false; ++ mIsVideoEncoderSet = false; ++ mIsOutputFileSet = false; ++} + -+ if (mr == NULL) { -+ ALOGE("mr must not be NULL"); -+ return android::BAD_VALUE; ++// Release should be OK in any state ++status_t MediaRecorder::release() ++{ ++ ALOGV("release"); ++ if (mMediaRecorder != NULL) { ++ return mMediaRecorder->release(); + } -+ -+ return mr->setAudioSource(static_cast(as)); ++ return INVALID_OPERATION; +} + -+/*! -+ * \brief android_recorder_setOutputFormat -+ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() -+ * \param of The output file container format -+ * \return negative value if an error occured -+ */ -+int android_recorder_setOutputFormat(MediaRecorderWrapper *mr, OutputFormat of) ++ ++MediaRecorder::MediaRecorder() ++ : mMediaRecorderFactory(NULL), ++ mSurfaceMediaSource(NULL) +{ -+ REPORT_FUNCTION(); ++ ALOGV("constructor (custom)"); + -+ if (mr == NULL) { -+ ALOGE("mr must not be NULL"); -+ return android::BAD_VALUE; -+ } ++ if (mMediaRecorderFactory == NULL) { ++ sp sm = defaultServiceManager(); ++ sp binder; ++ do { ++ binder = sm->getService(String16(IMediaRecorderFactory::exported_service_name())); ++ if (binder != 0) { ++ break; ++ } ++ ALOGW("MediaRecorderFactory service not published, waiting..."); ++ usleep(500000); // 0.5 s ++ } while (true); + -+ return mr->setOutputFormat(static_cast(of)); -+} ++ mMediaRecorderFactory = interface_cast(binder); ++ } + -+/*! -+ * \brief android_recorder_setVideoEncoder -+ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() -+ * \param ve The video encoder sets the codec type for encoding/recording video -+ * \return negative value if an error occured -+ */ -+int android_recorder_setVideoEncoder(MediaRecorderWrapper *mr, VideoEncoder ve) -+{ -+ REPORT_FUNCTION(); ++ ALOGE_IF(mMediaRecorderFactory == NULL, "no MediaRecorderFactory!?"); + -+ if (mr == NULL) { -+ ALOGE("mr must not be NULL"); -+ return android::BAD_VALUE; ++ mMediaRecorder = mMediaRecorderFactory->createMediaRecorder(); ++ if (mMediaRecorder != NULL) { ++ mCurrentState = MEDIA_RECORDER_IDLE; + } + -+ return mr->setVideoEncoder(static_cast(ve)); ++ doCleanUp(); +} + -+/*! -+ * \brief android_recorder_setAudioEncoder -+ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() -+ * \param ae The audio encoder sets the codec type for encoding/recording audio -+ * \return negative value if an error occured -+ */ -+int android_recorder_setAudioEncoder(MediaRecorderWrapper *mr, AudioEncoder ae) ++status_t MediaRecorder::initCheck() +{ -+ REPORT_FUNCTION(); ++ return mMediaRecorder != 0 ? NO_ERROR : NO_INIT; ++} + -+ if (mr == NULL) { -+ ALOGE("mr must not be NULL"); -+ return android::BAD_VALUE; ++MediaRecorder::~MediaRecorder() ++{ ++ ALOGV("destructor"); ++ if (mMediaRecorder != NULL) { ++ mMediaRecorder.clear(); + } + -+ return mr->setAudioEncoder(static_cast(ae)); ++ if (mSurfaceMediaSource != NULL) { ++ mSurfaceMediaSource.clear(); ++ } +} + -+/*! -+ * \brief android_recorder_setOutputFile sets the output file to the given file descriptor -+ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() -+ * \param fd File descriptor of an open file, that the stream can be written to -+ * \return negative value if an error occured -+ */ -+int android_recorder_setOutputFile(MediaRecorderWrapper *mr, int fd) ++status_t MediaRecorder::setListener(const sp& listener) +{ -+ REPORT_FUNCTION(); ++ ALOGV("setListener"); ++ Mutex::Autolock _l(mLock); ++ mListener = listener; + -+ if (mr == NULL) { -+ ALOGE("mr must not be NULL"); -+ return android::BAD_VALUE; ++ if (mMediaRecorder != NULL) { ++ // Sets a listener so that when the named pipe reader in RecordThread is ready, ++ // we can bubble up to media_recorder_layer to signal the app that it's ready ++ // to do audio recording ++ mMediaRecorder->setListener(this); + } + -+ return mr->setOutputFile(fd, 0, 0); ++ return NO_ERROR; +} + -+/*! -+ * \brief android_recorder_setVideoSize -+ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() -+ * \param width output width for the video to record -+ * \param height output height for the video to record -+ * \return negative value if an error occured -+ */ -+int android_recorder_setVideoSize(MediaRecorderWrapper *mr, int width, int height) ++status_t MediaRecorder::setClientName(const String16& clientName) +{ -+ REPORT_FUNCTION(); -+ -+ if (mr == NULL) { -+ ALOGE("mr must not be NULL"); -+ return android::BAD_VALUE; ++ ALOGV("setClientName"); ++ if (mMediaRecorder == NULL) { ++ ALOGE("media recorder is not initialized yet"); ++ return INVALID_OPERATION; ++ } ++ bool isInvalidState = (mCurrentState & ++ (MEDIA_RECORDER_PREPARED | ++ MEDIA_RECORDER_RECORDING | ++ MEDIA_RECORDER_ERROR)); ++ if (isInvalidState) { ++ ALOGE("setClientName is called in an invalid state: %d", mCurrentState); ++ return INVALID_OPERATION; + } + -+ return mr->setVideoSize(width, height); ++ mMediaRecorder->setClientName(clientName); ++ ++ return NO_ERROR; +} + -+/*! -+ * \brief android_recorder_setVideoFrameRate -+ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() -+ * \param frames_per_second How many frames per second to record at (e.g. 720p is typically 30) -+ * \return negative value if an error occured -+ */ -+int android_recorder_setVideoFrameRate(MediaRecorderWrapper *mr, int frames_per_second) ++void MediaRecorder::notify(int msg, int ext1, int ext2) +{ -+ REPORT_FUNCTION(); ++ ALOGV("message received msg=%d, ext1=%d, ext2=%d", msg, ext1, ext2); + -+ if (mr == NULL) { -+ ALOGE("mr must not be NULL"); -+ return android::BAD_VALUE; -+ } ++ sp listener; ++ mLock.lock(); ++ listener = mListener; ++ mLock.unlock(); + -+ return mr->setVideoFrameRate(frames_per_second); ++ if (listener != NULL) { ++ Mutex::Autolock _l(mNotifyLock); ++ ALOGV("callback application"); ++ listener->notify(msg, ext1, ext2); ++ ALOGV("back from callback"); ++ } +} + -+/*! -+ * \brief android_recorder_setParameters sets a parameter. Even those without -+ * explicit function. -+ * For possible parameter pairs look for examples in StagefrightRecorder::setParameter() -+ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() -+ * \param parameters list of parameters. format is "parameter1=value;parameter2=value" -+ * \return negative value if an error occured -+ */ -+int android_recorder_setParameters(MediaRecorderWrapper *mr, const char *parameters) ++void MediaRecorder::readAudio() +{ -+ REPORT_FUNCTION(); ++ ALOGV("%s", __PRETTY_FUNCTION__); + -+ if (mr == NULL) { -+ ALOGE("mr must not be NULL"); -+ return android::BAD_VALUE; -+ } ++ sp listener; ++ status_t ret = NO_ERROR; ++ mLock.lock(); ++ listener = mListener; ++ mLock.unlock(); + -+ android::String8 params(parameters); -+ return mr->setParameters(params); -+} -+ -+/*! -+ * \brief android_recorder_start starts the recording. -+ * The MediaRecorder has to be in state "prepared" (call android_recorder_prepare() first) -+ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() -+ * \return negative value if an error occured -+ */ -+int android_recorder_start(MediaRecorderWrapper *mr) -+{ -+ REPORT_FUNCTION(); -+ -+ if (mr == NULL) { -+ ALOGE("mr must not be NULL"); -+ return android::BAD_VALUE; ++ if (listener != NULL) { ++ Mutex::Autolock _l(mReadAudioLock); ++ ALOGV("callback application"); ++ listener->readAudio(); ++ ALOGV("back from callback"); + } -+ -+ return mr->start(); +} + -+/*! -+ * \brief android_recorder_stop Stops a running recording. -+ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() -+ * \return negative value if an error occured -+ */ -+int android_recorder_stop(MediaRecorderWrapper *mr) ++void MediaRecorder::died() +{ -+ REPORT_FUNCTION(); -+ -+ if (mr == NULL) { -+ ALOGE("mr must not be NULL"); -+ return android::BAD_VALUE; -+ } -+ -+ return mr->stop(); ++ ALOGV("died"); ++ notify(MEDIA_RECORDER_EVENT_ERROR, MEDIA_ERROR_SERVER_DIED, 0); +} + -+/*! -+ * \brief android_recorder_prepare put the MediaRecorder into state "prepare" -+ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() -+ * \return negative value if an error occured ++} // namespace android +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_recorder.h +@@ -0,0 +1,271 @@ ++/* ++ ** Copyright (C) 2008 The Android Open Source Project ++ ** Copyright (C) 2014 Canonical Ltd ++ ** ++ ** Adapted from the Android equivalent code for use in Ubuntu. ++ ** ++ ** 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. + */ -+int android_recorder_prepare(MediaRecorderWrapper *mr) -+{ -+ REPORT_FUNCTION(); + -+ if (mr == NULL) { -+ ALOGE("mr must not be NULL"); -+ return android::BAD_VALUE; -+ } ++#ifndef ANDROID_MEDIARECORDER_H ++#define ANDROID_MEDIARECORDER_H + -+ return mr->prepare(); -+} ++#include ++#include ++#include ++#include ++#include ++#include ++#include + -+/*! -+ * \brief android_recorder_reset resets the MediaRecorder -+ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() -+ * \return negative value if an error occured -+ */ -+int android_recorder_reset(MediaRecorderWrapper *mr) -+{ -+ REPORT_FUNCTION(); ++namespace android { + -+ if (mr == NULL) { -+ ALOGE("mr must not be NULL"); -+ return android::BAD_VALUE; -+ } ++class Surface; ++class IMediaRecorder; ++class IMediaRecorderFactory; ++class ICamera; ++class ICameraRecordingProxy; ++class IGraphicBufferProducer; ++class Surface; + -+ return mr->reset(); -+} ++typedef void (*media_completion_f)(status_t status, void *cookie); + -+/*! -+ * \brief android_recorder_close closes the MediaRecorder -+ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() -+ * \return negative value if an error occured -+ */ -+int android_recorder_close(MediaRecorderWrapper *mr) -+{ -+ REPORT_FUNCTION(); ++enum video_source { ++ VIDEO_SOURCE_DEFAULT = 0, ++ VIDEO_SOURCE_CAMERA = 1, ++ VIDEO_SOURCE_GRALLOC_BUFFER = 2, + -+ if (mr == NULL) { -+ ALOGE("mr must not be NULL"); -+ return android::BAD_VALUE; -+ } ++ VIDEO_SOURCE_LIST_END // must be last - used to validate audio source type ++}; + -+ return mr->close(); -+} ++// Please update media/java/android/media/MediaRecorder.java if the following is updated. ++enum output_format { ++ OUTPUT_FORMAT_DEFAULT = 0, ++ OUTPUT_FORMAT_THREE_GPP = 1, ++ OUTPUT_FORMAT_MPEG_4 = 2, + -+/*! -+ * \brief android_recorder_release releases the MediaRecorder resources -+ * This deletes the MediaRecorder instance. So don't use the instance after calling this function. -+ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() -+ * \return negative value if an error occured -+ */ -+int android_recorder_release(MediaRecorderWrapper *mr) -+{ -+ REPORT_FUNCTION(); + -+ if (mr == NULL) { -+ ALOGE("mr must not be NULL"); -+ return android::BAD_VALUE; -+ } ++ OUTPUT_FORMAT_AUDIO_ONLY_START = 3, // Used in validating the output format. Should be the ++ // at the start of the audio only output formats. + -+ return mr->release(); -+} ---- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_recorder_observer.cpp -@@ -0,0 +1,127 @@ -+/* -+ * Copyright (C) 2014 Canonical Ltd -+ * -+ * 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. -+ * -+ * Authored by: Ricardo Mendoza -+ */ ++ /* These are audio only file formats */ ++ OUTPUT_FORMAT_RAW_AMR = 3, //to be backward compatible ++ OUTPUT_FORMAT_AMR_NB = 3, ++ OUTPUT_FORMAT_AMR_WB = 4, ++ OUTPUT_FORMAT_AAC_ADIF = 5, ++ OUTPUT_FORMAT_AAC_ADTS = 6, + -+// Uncomment to enabe verbose debug output -+//#define LOG_NDEBUG 0 ++ /* Stream over a socket, limited to a single stream */ ++ OUTPUT_FORMAT_RTP_AVP = 7, + -+#undef LOG_TAG -+#define LOG_TAG "MediaRecorderObserver" ++ /* H.264/AAC data encapsulated in MPEG2/TS */ ++ OUTPUT_FORMAT_MPEG2TS = 8, + -+#include "media_recorder_observer.h" ++ OUTPUT_FORMAT_LIST_END // must be last - used to validate format type ++}; + -+#include -+#include ++enum audio_encoder { ++ AUDIO_ENCODER_DEFAULT = 0, ++ AUDIO_ENCODER_AMR_NB = 1, ++ AUDIO_ENCODER_AMR_WB = 2, ++ AUDIO_ENCODER_AAC = 3, ++ AUDIO_ENCODER_HE_AAC = 4, ++ AUDIO_ENCODER_AAC_ELD = 5, + -+#include -+#include ++ AUDIO_ENCODER_LIST_END // must be the last - used to validate the audio encoder type ++}; + -+#include ++enum video_encoder { ++ VIDEO_ENCODER_DEFAULT = 0, ++ VIDEO_ENCODER_H263 = 1, ++ VIDEO_ENCODER_H264 = 2, ++ VIDEO_ENCODER_MPEG_4_SP = 3, + -+#include ++ VIDEO_ENCODER_LIST_END // must be the last - used to validate the video encoder type ++}; + -+#include -+#include -+#include ++/* ++ * The state machine of the media_recorder. ++ */ ++enum media_recorder_states { ++ // Error state. ++ MEDIA_RECORDER_ERROR = 0, + -+namespace android { ++ // Recorder was just created. ++ MEDIA_RECORDER_IDLE = 1 << 0, + -+IMPLEMENT_META_INTERFACE(MediaRecorderObserver, "android.media.IMediaRecorderObserver"); ++ // Recorder has been initialized. ++ MEDIA_RECORDER_INITIALIZED = 1 << 1, + -+status_t BnMediaRecorderObserver::onTransact( -+ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) -+{ -+ switch (code) { -+ case RECORDING_STARTED: { -+ CHECK_INTERFACE(IMediaRecorderObserver, data, reply); -+ recordingStarted(); ++ // Configuration of the recorder has been completed. ++ MEDIA_RECORDER_DATASOURCE_CONFIGURED = 1 << 2, + -+ return NO_ERROR; -+ } break; -+ case RECORDING_STOPPED: { -+ CHECK_INTERFACE(IMediaRecorderObserver, data, reply); -+ recordingStopped(); ++ // Recorder is ready to start. ++ MEDIA_RECORDER_PREPARED = 1 << 3, + -+ return NO_ERROR; -+ } break; -+ default: -+ return BBinder::onTransact(code, data, reply, flags); -+ } -+} ++ // Recording is in progress. ++ MEDIA_RECORDER_RECORDING = 1 << 4, ++}; + -+MediaRecorderObserver::MediaRecorderObserver() -+{ -+ defaultServiceManager()->addService( -+ String16(IMediaRecorderObserver::exported_service_name()), this); -+ -+ ProcessState::self()->startThreadPool(); -+} -+ -+void MediaRecorderObserver::recordingStarted() -+{ -+ if (media_recording_started != nullptr) -+ media_recording_started(true, cb_context); -+} -+ -+void MediaRecorderObserver::recordingStopped() -+{ -+ if (media_recording_started != nullptr) -+ media_recording_started(false, cb_context); -+} -+ -+void MediaRecorderObserver::setRecordingSignalCb(media_recording_started_cb cb, void *context) -+{ -+ if (cb != NULL) { -+ cb_context = context; -+ media_recording_started = cb; -+ } -+} ++// The "msg" code passed to the listener in notify. ++enum media_recorder_event_type { ++ MEDIA_RECORDER_EVENT_LIST_START = 1, ++ MEDIA_RECORDER_EVENT_ERROR = 1, ++ MEDIA_RECORDER_EVENT_INFO = 2, ++ MEDIA_RECORDER_EVENT_LIST_END = 99, + ++ // Track related event types ++ MEDIA_RECORDER_TRACK_EVENT_LIST_START = 100, ++ MEDIA_RECORDER_TRACK_EVENT_ERROR = 100, ++ MEDIA_RECORDER_TRACK_EVENT_INFO = 101, ++ MEDIA_RECORDER_TRACK_EVENT_LIST_END = 1000, +}; + -+// C API -+ -+struct MediaRecorderObserver { -+ MediaRecorderObserver(android::MediaRecorderObserver *observer) -+ : impl(observer) -+ { -+ } ++/* ++ * The (part of) "what" code passed to the listener in notify. ++ * When the error or info type is track specific, the what has ++ * the following layout: ++ * the left-most 16-bit is meant for error or info type. ++ * the right-most 4-bit is meant for track id. ++ * the rest is reserved. ++ * ++ * | track id | reserved | error or info type | ++ * 31 28 16 0 ++ * ++ */ ++enum media_recorder_error_type { ++ MEDIA_RECORDER_ERROR_UNKNOWN = 1, + -+ android::MediaRecorderObserver* impl; ++ // Track related error type ++ MEDIA_RECORDER_TRACK_ERROR_LIST_START = 100, ++ MEDIA_RECORDER_TRACK_ERROR_GENERAL = 100, ++ MEDIA_RECORDER_ERROR_VIDEO_NO_SYNC_FRAME = 200, ++ MEDIA_RECORDER_TRACK_ERROR_LIST_END = 1000, +}; + -+MediaRecorderObserver* android_media_recorder_observer_new() -+{ -+ MediaRecorderObserver *p = new MediaRecorderObserver(new android::MediaRecorderObserver); -+ -+ if (p == NULL) { -+ ALOGE("Failed to create new MediaRecorderObserver instance."); -+ return NULL; -+ } ++// The codes are distributed as follow: ++// 0xx: Reserved ++// 8xx: General info/warning ++// ++enum media_recorder_info_type { ++ MEDIA_RECORDER_INFO_UNKNOWN = 1, + -+ return p; -+} ++ MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800, ++ MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801, + -+void android_media_recorder_observer_set_cb(MediaRecorderObserver *observer, media_recording_started_cb cb, void *context) -+{ -+ if (observer == NULL) -+ return; ++ // All track related informtional events start here ++ MEDIA_RECORDER_TRACK_INFO_LIST_START = 1000, ++ MEDIA_RECORDER_TRACK_INFO_COMPLETION_STATUS = 1000, ++ MEDIA_RECORDER_TRACK_INFO_PROGRESS_IN_TIME = 1001, ++ MEDIA_RECORDER_TRACK_INFO_TYPE = 1002, ++ MEDIA_RECORDER_TRACK_INFO_DURATION_MS = 1003, + -+ auto p = observer->impl; ++ // The time to measure the max chunk duration ++ MEDIA_RECORDER_TRACK_INFO_MAX_CHUNK_DUR_MS = 1004, + -+ p->setRecordingSignalCb(cb, context); -+} ---- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/media_recorder_observer.h -@@ -0,0 +1,97 @@ -+/* -+ * Copyright (C) 2014 Canonical Ltd -+ * -+ * 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. -+ * -+ * Authored by: Ricardo Mendoza -+ */ ++ MEDIA_RECORDER_TRACK_INFO_ENCODED_FRAMES = 1005, + -+#ifndef MEDIA_RECORDER_OBSERVER_H_ -+#define MEDIA_RECORDER_OBSERVER_H_ ++ // The time to measure how well the audio and video ++ // track data is interleaved. ++ MEDIA_RECORDER_TRACK_INTER_CHUNK_TIME_MS = 1006, + -+#include -+#include ++ // The time to measure system response. Note that ++ // the delay does not include the intentional delay ++ // we use to eliminate the recording sound. ++ MEDIA_RECORDER_TRACK_INFO_INITIAL_DELAY_MS = 1007, + -+#include ++ // The time used to compensate for initial A/V sync. ++ MEDIA_RECORDER_TRACK_INFO_START_OFFSET_MS = 1008, + -+namespace android { ++ // Total number of bytes of the media data. ++ MEDIA_RECORDER_TRACK_INFO_DATA_KBYTES = 1009, + -+enum { -+ RECORDING_STARTED = IBinder::FIRST_CALL_TRANSACTION, -+ RECORDING_STOPPED, ++ MEDIA_RECORDER_TRACK_INFO_LIST_END = 2000, +}; + -+class IMediaRecorderObserver: public IInterface -+{ -+public: -+ DECLARE_META_INTERFACE(MediaRecorderObserver); -+ -+ static const char* exported_service_name() { return "android.media.IMediaRecorderObserver"; } -+ -+ virtual void recordingStarted(void) = 0; -+ virtual void recordingStopped(void) = 0; -+}; ++class MediaPlayerService; + -+class BnMediaRecorderObserver: public BnInterface ++// ---------------------------------------------------------------------------- ++// ref-counted object for callbacks ++class MediaRecorderListener: virtual public RefBase +{ +public: -+ virtual status_t onTransact( uint32_t code, -+ const Parcel& data, -+ Parcel* reply, -+ uint32_t flags = 0); ++ virtual void notify(int msg, int ext1, int ext2) = 0; ++ virtual void readAudio() = 0; +}; + -+class BpMediaRecorderObserver: public BpInterface ++class MediaRecorder : public BnMediaRecorderClient, ++ public virtual IMediaDeathNotifier +{ +public: -+ BpMediaRecorderObserver(const sp& impl) -+ : BpInterface(impl) -+ { -+ } -+ -+ virtual void recordingStarted() -+ { -+ Parcel data, reply; -+ data.writeInterfaceToken(IMediaRecorderObserver::getInterfaceDescriptor()); -+ remote()->transact(RECORDING_STARTED, data, &reply); -+ return; -+ } ++ MediaRecorder(); ++ ~MediaRecorder(); + -+ virtual void recordingStopped() -+ { -+ Parcel data, reply; -+ data.writeInterfaceToken(IMediaRecorderObserver::getInterfaceDescriptor()); -+ remote()->transact(RECORDING_STOPPED, data, &reply); -+ return; -+ } -+}; ++ void died(); ++ status_t initCheck(); ++ status_t setCamera(const sp& camera, const sp& proxy); ++ status_t setPreviewSurface(const sp& surface); ++ status_t setVideoSource(int vs); ++ status_t setAudioSource(int as); ++ status_t setOutputFormat(int of); ++ status_t setVideoEncoder(int ve); ++ status_t setAudioEncoder(int ae); ++#if ANDROID_VERSION_MAJOR<=5 ++ status_t setOutputFile(const char* path); ++#endif ++ status_t setOutputFile(int fd, int64_t offset, int64_t length); ++ status_t setVideoSize(int width, int height); ++ status_t setVideoFrameRate(int frames_per_second); ++ status_t setParameters(const String8& params); ++ status_t setListener(const sp& listener); ++ status_t setClientName(const String16& clientName); ++ status_t prepare(); ++ status_t getMaxAmplitude(int* max); ++ status_t start(); ++ status_t stop(); ++ status_t reset(); ++ status_t init(); ++ status_t close(); ++ status_t release(); ++ void notify(int msg, int ext1, int ext2); ++ void readAudio(); ++ sp querySurfaceMediaSourceFromMediaServer(); + -+class MediaRecorderObserver : public BnMediaRecorderObserver -+{ -+public: -+ MediaRecorderObserver(); -+ ~MediaRecorderObserver() = default; ++private: ++ void doCleanUp(); ++ status_t doReset(); + -+ virtual void recordingStarted(void); -+ virtual void recordingStopped(void); ++ sp mMediaRecorder; ++ sp mListener; ++ sp mMediaRecorderFactory; + -+ virtual void setRecordingSignalCb(media_recording_started_cb cb, void *context); ++ // Reference to IGraphicBufferProducer ++ // for encoding GL Frames. That is useful only when the ++ // video source is set to VIDEO_SOURCE_GRALLOC_BUFFER ++ sp mSurfaceMediaSource; + -+private: -+ media_recording_started_cb media_recording_started; -+ void *cb_context; ++ media_recorder_states mCurrentState; ++ bool mIsAudioSourceSet; ++ bool mIsVideoSourceSet; ++ bool mIsAudioEncoderSet; ++ bool mIsVideoEncoderSet; ++ bool mIsOutputFileSet; ++ Mutex mLock; ++ Mutex mNotifyLock; ++ Mutex mReadAudioLock; +}; + -+}; // namespace android ++}; // namespace android + -+#endif ++#endif // ANDROID_MEDIARECORDER_H --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/surface_texture_client_hybris.cpp -@@ -0,0 +1,451 @@ ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_recorder_client.cpp +@@ -0,0 +1,365 @@ +/* -+ * Copyright (C) 2013 Canonical Ltd ++ * Copyright (C) 2013-2014 Canonical Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. @@ -8226,444 +8736,590 @@ + * Authored by: Jim Hodapp + */ + -+// Uncomment to enable verbose debug output ++#include "media_recorder_client.h" ++ ++#include ++#include ++ +#define LOG_NDEBUG 0 ++#define LOG_TAG "MediaRecorderClient" + -+#undef LOG_TAG -+#define LOG_TAG "SurfaceTextureClientHybris" ++#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__) + -+#include -+#include "surface_texture_client_hybris_priv.h" -+#include "decoding_service_priv.h" ++using namespace android; + -+#include -+#include -+#include -+#include -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+#include -+#endif -+#include -+#include ++MediaRecorderClient::MediaRecorderClient() ++{ ++ REPORT_FUNCTION(); + -+#include -+#include ++ sp service_manager = defaultServiceManager(); ++ sp service = service_manager->getService( ++ String16(IMediaRecorderObserver::exported_service_name())); + -+#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__); ++ media_recorder_observer = new BpMediaRecorderObserver(service); + -+using namespace android; ++#if ANDROID_VERSION_MAJOR>=6 ++ // TODO: do we need to get valid package here? ++ const String16 opPackageName("ubuntu"); ++ recorder = new android::StagefrightRecorder(opPackageName); ++#else ++ recorder = new android::StagefrightRecorder; ++#endif ++} + -+// ----- Begin _SurfaceTextureClientHybris API ----- // ++MediaRecorderClient::~MediaRecorderClient() ++{ ++ REPORT_FUNCTION(); ++ release(); ++} + -+static inline _SurfaceTextureClientHybris *get_internal_stch(SurfaceTextureClientHybris stc, const char * func) ++status_t MediaRecorderClient::setCamera(const sp& camera, ++ const sp& proxy) +{ -+ if (stc == NULL) -+ { -+ ALOGE("stc must not be NULL (%s)", func); -+ return NULL; ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; + } ++ return recorder->setCamera(camera, proxy); ++} + -+ _SurfaceTextureClientHybris *s = static_cast<_SurfaceTextureClientHybris*>(stc); -+ assert(s->refcount >= 1); ++status_t MediaRecorderClient::setPreviewSurface(const android::sp& surface) ++{ ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; ++ } ++ return recorder->setPreviewSurface(surface); ++} + -+ return s; ++status_t MediaRecorderClient::setVideoSource(int vs) ++{ ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; ++ } ++ return recorder->setVideoSource((android::video_source)vs); +} + -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+_SurfaceTextureClientHybris::_SurfaceTextureClientHybris() -+ : refcount(1), -+ ready(false) ++status_t MediaRecorderClient::setAudioSource(int as) +{ -+ REPORT_FUNCTION() ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; ++ } ++ return recorder->setAudioSource((audio_source_t)as); +} -+#endif + -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR>=4 -+_SurfaceTextureClientHybris::_SurfaceTextureClientHybris(const sp &bq) -+ : Surface::Surface(bq, true), -+ refcount(1), -+ ready(false) ++status_t MediaRecorderClient::setOutputFormat(int of) +{ -+ REPORT_FUNCTION() ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; ++ } ++ return recorder->setOutputFormat((android::output_format)of); +} + -+_SurfaceTextureClientHybris::_SurfaceTextureClientHybris(const sp &st) -+ : Surface::Surface(st, true), -+ refcount(1), -+ ready(false) ++status_t MediaRecorderClient::setVideoEncoder(int ve) +{ -+ REPORT_FUNCTION() ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; ++ } ++ return recorder->setVideoEncoder((android::video_encoder)ve); +} -+#endif + -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+_SurfaceTextureClientHybris::_SurfaceTextureClientHybris(const _SurfaceTextureClientHybris &stch) -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+ : SurfaceTextureClient::SurfaceTextureClient(), -+#else -+ : Surface::Surface(new BufferQueue(), true), -+#endif -+ refcount(stch.refcount), -+ ready(false) ++status_t MediaRecorderClient::setAudioEncoder(int ae) +{ -+ REPORT_FUNCTION() ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; ++ } ++ return recorder->setAudioEncoder((android::audio_encoder)ae); +} + -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+_SurfaceTextureClientHybris::_SurfaceTextureClientHybris(const sp &st) -+ : SurfaceTextureClient::SurfaceTextureClient(st), ++#if ANDROID_VERSION_MAJOR<=5 ++status_t MediaRecorderClient::setOutputFile(const char* path) ++{ ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; ++ } ++ return recorder->setOutputFile(path); ++} +#else -+_SurfaceTextureClientHybris::_SurfaceTextureClientHybris(const sp &st) -+ : Surface::Surface(st, false), -+#endif -+ refcount(1), -+ ready(false) ++status_t MediaRecorderClient::setInputSurface(const sp& surface) +{ -+ REPORT_FUNCTION() ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; ++ } ++ return recorder->setInputSurface(surface); +} +#endif + -+_SurfaceTextureClientHybris::_SurfaceTextureClientHybris(const android::sp &st, -+ bool producerIsControlledByApp) -+ : Surface::Surface(st, producerIsControlledByApp), -+ refcount(1), -+ ready(false) ++status_t MediaRecorderClient::setOutputFile(int fd, int64_t offset, int64_t length) +{ -+ REPORT_FUNCTION() ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; ++ } ++ return recorder->setOutputFile(fd, offset, length); +} + -+_SurfaceTextureClientHybris::~_SurfaceTextureClientHybris() ++status_t MediaRecorderClient::setVideoSize(int width, int height) +{ -+ REPORT_FUNCTION() -+ -+ ready = false; ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; ++ } ++ return recorder->setVideoSize(width, height); +} + -+bool _SurfaceTextureClientHybris::isReady() const ++status_t MediaRecorderClient::setVideoFrameRate(int frames_per_second) +{ -+ return ready; ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; ++ } ++ return recorder->setVideoFrameRate(frames_per_second); +} + -+void _SurfaceTextureClientHybris::setReady(bool ready) ++status_t MediaRecorderClient::setParameters(const android::String8& params) +{ -+ this->ready = ready; ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; ++ } ++ return recorder->setParameters(params); +} + -+int _SurfaceTextureClientHybris::dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd) ++status_t MediaRecorderClient::setListener(const android::sp& listener) +{ -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+ return SurfaceTextureClient::dequeueBuffer(buffer, fenceFd); -+#else -+ return Surface::dequeueBuffer(buffer, fenceFd); -+#endif ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; ++ } ++ return recorder->setListener(listener); +} + -+int _SurfaceTextureClientHybris::queueBuffer(ANativeWindowBuffer* buffer, int fenceFd) ++status_t MediaRecorderClient::setClientName(const android::String16& clientName) +{ -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+ return SurfaceTextureClient::queueBuffer(buffer, fenceFd); -+#else -+ return Surface::queueBuffer(buffer, fenceFd); -+#endif ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; ++ } ++ return recorder->setClientName(clientName); +} + -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+void _SurfaceTextureClientHybris::setISurfaceTexture(const sp& surface_texture) -+{ -+ SurfaceTextureClient::setISurfaceTexture(surface_texture); -+#else -+void _SurfaceTextureClientHybris::setISurfaceTexture(const sp& surface_texture) ++status_t MediaRecorderClient::prepare() +{ -+ // We don't need to set up the IGraphicBufferProducer as stc needs it when created -+#endif -+ -+ // Ready for rendering -+ ready = true; ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; ++ } ++ return recorder->prepare(); +} + -+void _SurfaceTextureClientHybris::setHardwareRendering(bool do_hardware_rendering) ++status_t MediaRecorderClient::getMaxAmplitude(int* max) +{ -+ hardware_rendering = do_hardware_rendering; ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; ++ } ++ return recorder->getMaxAmplitude(max); +} + -+bool _SurfaceTextureClientHybris::hardwareRendering() ++status_t MediaRecorderClient::start() +{ -+ return hardware_rendering; -+} -+ -+// ----- End _SurfaceTextureClientHybris API ----- // -+ -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+static inline void set_surface(_SurfaceTextureClientHybris *stch, const sp &surface_texture) -+#else -+static inline void set_surface(_SurfaceTextureClientHybris *stch, const sp &surface_texture) -+#endif -+{ -+ REPORT_FUNCTION() ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; ++ } + -+ if (stch == NULL) -+ return; ++ if (media_recorder_observer != NULL) ++ media_recorder_observer->recordingStarted(); + -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+ stch->setISurfaceTexture(surface_texture->getBufferQueue()); -+#else -+ stch->setISurfaceTexture(stch->getIGraphicBufferProducer()); -+#endif ++ return recorder->start(); +} + -+SurfaceTextureClientHybris surface_texture_client_create_by_id(unsigned int texture_id) ++status_t MediaRecorderClient::stop() +{ -+ REPORT_FUNCTION() -+ -+ if (texture_id == 0) -+ { -+ ALOGE("Cannot create new SurfaceTextureClientHybris, texture id must be > 0."); -+ return NULL; ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; + } + -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 -+ // Use a new native buffer allocator vs the default one, which means it'll use the proper one -+ // that will allow rendering to work with Mir -+ sp native_alloc(new NativeBufferAlloc()); -+ -+ sp buffer_queue(new BufferQueue(false, NULL, native_alloc)); -+ _SurfaceTextureClientHybris *stch(new _SurfaceTextureClientHybris); -+#else -+ sp buffer_queue(new BufferQueue(NULL)); -+ _SurfaceTextureClientHybris *stch(new _SurfaceTextureClientHybris(buffer_queue)); -+#endif -+ -+ ALOGD("stch: %p (%s)", stch, __PRETTY_FUNCTION__); -+ -+ if (stch->surface_texture != NULL) -+ stch->surface_texture.clear(); -+ -+ const bool allow_synchronous_mode = true; -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+ stch->surface_texture = new SurfaceTexture(texture_id, allow_synchronous_mode, GL_TEXTURE_EXTERNAL_OES, true, buffer_queue); -+ set_surface(stch, stch->surface_texture); -+#else -+ stch->surface_texture = new GLConsumer(buffer_queue, texture_id, GL_TEXTURE_EXTERNAL_OES, true, true); -+#endif -+ set_surface(stch, stch->surface_texture); ++ if (media_recorder_observer != NULL) ++ media_recorder_observer->recordingStopped(); + -+ return stch; ++ return recorder->stop(); +} + -+SurfaceTextureClientHybris surface_texture_client_create_by_igbp(IGBPWrapperHybris wrapper) ++#ifdef BOARD_HAS_MEDIA_RECORDER_PAUSE ++status_t MediaRecorderClient::pause() +{ -+ if (wrapper == NULL) -+ { -+ ALOGE("Cannot create new SurfaceTextureClientHybris, wrapper must not be NULL."); -+ return NULL; ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; + } ++ return recorder->pause(); + -+ IGBPWrapper *igbp = static_cast(wrapper); -+ // The producer should be the same BufferQueue as what the client is using but over Binder -+ // Allow the app to control the producer side BufferQueue -+ _SurfaceTextureClientHybris *stch(new _SurfaceTextureClientHybris(igbp->producer, true)); -+ // Ready for rendering -+ stch->setReady(); -+ return stch; +} ++#endif + -+GLConsumerWrapperHybris gl_consumer_create_by_id_with_igbc(unsigned int texture_id, IGBCWrapperHybris wrapper) ++#ifdef BOARD_HAS_MEDIA_RECORDER_RESUME ++status_t MediaRecorderClient::resume() +{ -+ REPORT_FUNCTION() -+ -+ if (texture_id == 0) -+ { -+ ALOGE("Cannot create new SurfaceTextureClientHybris, texture id must be > 0."); -+ return NULL; -+ } -+ -+ if (wrapper == NULL) -+ { -+ ALOGE("Cannot create new GLConsumerHybris, wrapper must not be NULL."); -+ return NULL; ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; + } -+ -+ IGBCWrapper *igbc = static_cast(wrapper); -+ // Use a fence guard and consumer is controlled by app: -+ sp<_GLConsumerHybris> gl_consumer = new _GLConsumerHybris(igbc->consumer, texture_id, GL_TEXTURE_EXTERNAL_OES, true, true); -+ GLConsumerWrapper *glc_wrapper = new GLConsumerWrapper(gl_consumer); -+ -+ return glc_wrapper; ++ return recorder->resume(); +} ++#endif + -+int gl_consumer_set_frame_available_cb(GLConsumerWrapperHybris wrapper, FrameAvailableCbHybris cb, void *context) ++status_t MediaRecorderClient::reset() +{ -+ REPORT_FUNCTION() -+ -+ if (wrapper == NULL) -+ { -+ ALOGE("Cannot set GLConsumerWrapperHybris, wrapper must not be NULL"); -+ return BAD_VALUE; -+ } -+ if (cb == NULL) -+ { -+ ALOGE("Cannot set FrameAvailableCbHybris, cb must not be NULL"); -+ return BAD_VALUE; ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; + } -+ -+ GLConsumerWrapper *glc_wrapper = static_cast(wrapper); -+ sp<_GLConsumerHybris> glc_hybris = static_cast<_GLConsumerHybris*>(glc_wrapper->consumer.get()); -+ glc_hybris->createFrameAvailableListener(cb, wrapper, context); -+ -+ return OK; ++ return recorder->reset(); +} + -+void gl_consumer_get_transformation_matrix(GLConsumerWrapperHybris wrapper, float *matrix) ++status_t MediaRecorderClient::init() +{ -+ REPORT_FUNCTION() -+ -+ if (wrapper == NULL) -+ { -+ ALOGE("Cannot set GLConsumerWrapperHybris, wrapper must not be NULL"); -+ return; ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; + } -+ -+ GLConsumerWrapper *glc_wrapper = static_cast(wrapper); -+ sp<_GLConsumerHybris> glc_hybris = static_cast<_GLConsumerHybris*>(glc_wrapper->consumer.get()); -+ glc_hybris->getTransformMatrix(static_cast(matrix)); ++ return recorder->init(); +} + -+void gl_consumer_update_texture(GLConsumerWrapperHybris wrapper) ++status_t MediaRecorderClient::close() +{ -+ REPORT_FUNCTION() -+ -+ if (wrapper == NULL) -+ { -+ ALOGE("Cannot set GLConsumerWrapperHybris, wrapper must not be NULL"); -+ return; ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder must not be NULL"); ++ return NO_INIT; + } -+ -+ GLConsumerWrapper *glc_wrapper = static_cast(wrapper); -+ sp<_GLConsumerHybris> glc_hybris = static_cast<_GLConsumerHybris*>(glc_wrapper->consumer.get()); -+ glc_hybris->updateTexImage(); ++ return recorder->close(); +} + -+uint8_t surface_texture_client_is_ready_for_rendering(SurfaceTextureClientHybris stc) ++status_t MediaRecorderClient::release() +{ -+ REPORT_FUNCTION() -+ -+ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); -+ if (s == NULL) -+ return false; -+ -+ return static_cast(s->isReady()); ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder != NULL) { ++ delete recorder; ++ recorder = NULL; ++ } ++ return NO_ERROR; +} + -+uint8_t surface_texture_client_hardware_rendering(SurfaceTextureClientHybris stc) ++status_t MediaRecorderClient::dump(int fd, const Vector& args) const +{ -+ REPORT_FUNCTION() -+ -+ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); -+ if (s == NULL) -+ return false; -+ -+ return s->hardwareRendering(); ++ REPORT_FUNCTION(); ++ if (recorder != NULL) { ++ return recorder->dump(fd, args); ++ } ++ return android::OK; +} + -+void surface_texture_client_set_hardware_rendering(SurfaceTextureClientHybris stc, uint8_t hardware_rendering) ++sp MediaRecorderClient::querySurfaceMediaSource() +{ -+ REPORT_FUNCTION() -+ -+ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); -+ if (s == NULL) -+ return; -+ -+ s->setHardwareRendering(static_cast(hardware_rendering)); ++ REPORT_FUNCTION(); ++ Mutex::Autolock lock(recorder_lock); ++ if (recorder == NULL) { ++ ALOGE("recorder is not initialized"); ++ return NULL; ++ } ++ return recorder->querySurfaceMediaSource(); +} +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_recorder_client.h +@@ -0,0 +1,88 @@ ++/* ++ * Copyright (C) 2013-2014 Canonical Ltd ++ * ++ * 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. ++ * ++ * Authored by: Jim Hodapp ++ */ + -+void surface_texture_client_get_transformation_matrix(SurfaceTextureClientHybris stc, float *matrix) -+{ -+ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); -+ if (s == NULL) -+ return; ++#ifndef MEDIA_RECORDER_CLIENT_H_ ++#define MEDIA_RECORDER_CLIENT_H_ + -+ s->surface_texture->getTransformMatrix(static_cast(matrix)); -+} ++#include ++#include + -+void surface_texture_client_update_texture(SurfaceTextureClientHybris stc) -+{ -+ REPORT_FUNCTION() ++#include "media_recorder_observer.h" + -+ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); -+ if (s == NULL) -+ return; ++#include + -+ s->surface_texture->updateTexImage(); -+} ++namespace android { + -+void surface_texture_client_destroy(SurfaceTextureClientHybris stc) ++class MediaRecorderBase; ++class Mutex; ++class BpMediaRecorderObserver; ++ ++/*! ++ * \brief The MediaRecorderClient struct wraps the service side of the MediaRecorder class ++ */ ++struct MediaRecorderClient : public BnMediaRecorder +{ -+ REPORT_FUNCTION() ++public: ++ MediaRecorderClient(); ++ virtual ~MediaRecorderClient(); + -+ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); -+ if (s == NULL) -+ { -+ ALOGE("s == NULL, cannot destroy SurfaceTextureClientHybris instance"); -+ return; -+ } ++ virtual status_t setCamera(const sp& camera, ++ const sp& proxy); ++ virtual status_t setPreviewSurface(const sp& surface); ++ virtual status_t setVideoSource(int vs); ++ virtual status_t setAudioSource(int as); ++ virtual status_t setOutputFormat(int of); ++ virtual status_t setVideoEncoder(int ve); ++ virtual status_t setAudioEncoder(int ae); ++#if ANDROID_VERSION_MAJOR<=5 ++ virtual status_t setOutputFile(const char* path); ++#else ++ virtual status_t setInputSurface(const sp& surface); ++#endif ++ virtual status_t setOutputFile(int fd, int64_t offset, int64_t length); ++ virtual status_t setVideoSize(int width, int height); ++ virtual status_t setVideoFrameRate(int frames_per_second); ++ virtual status_t setParameters(const String8& params); ++ virtual status_t setListener(const sp& listener); ++ virtual status_t setClientName(const String16& clientName); ++ virtual status_t prepare(); ++ virtual status_t getMaxAmplitude(int* max); ++ virtual status_t start(); ++ virtual status_t stop(); ++#ifdef BOARD_HAS_MEDIA_RECORDER_PAUSE ++ virtual status_t pause(); ++#endif ++#ifdef BOARD_HAS_MEDIA_RECORDER_RESUME ++ virtual status_t resume(); ++#endif ++ virtual status_t reset(); ++ virtual status_t init(); ++ virtual status_t close(); ++ virtual status_t release(); ++ virtual status_t dump(int fd, const Vector& args) const; ++ virtual sp querySurfaceMediaSource(); + -+ s->refcount = 0; ++private: ++ sp media_recorder_observer; ++ MediaRecorderBase *recorder; ++ Mutex recorder_lock; ++}; + -+ delete s; +} + -+void surface_texture_client_ref(SurfaceTextureClientHybris stc) -+{ -+ REPORT_FUNCTION() ++#endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_recorder_factory.cpp +@@ -0,0 +1,138 @@ ++/* ++ * Copyright (C) 2014 Canonical Ltd ++ * ++ * 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. ++ * ++ * Authored by: Jim Hodapp ++ */ + -+ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); -+ if (s == NULL) -+ return; ++//#define LOG_NDEBUG 0 ++#undef LOG_TAG ++#define LOG_TAG "MediaRecorderFactory" + -+ s->refcount++; -+} ++#include "media_recorder_factory.h" ++#include "media_recorder_client.h" ++#include + -+void surface_texture_client_unref(SurfaceTextureClientHybris stc) ++#include ++#include ++#include ++ ++#include ++#include ++ ++#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__) ++ ++namespace android { ++ ++enum { ++ CREATE_MEDIA_RECORDER = IBinder::FIRST_CALL_TRANSACTION, ++}; ++ ++class BpMediaRecorderFactory: public BpInterface +{ -+ REPORT_FUNCTION() ++public: ++ BpMediaRecorderFactory(const sp& impl) ++ : BpInterface(impl) ++ { ++ } + -+ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); -+ if (s == NULL) ++ virtual sp createMediaRecorder() + { -+ ALOGE("s == NULL, cannot unref SurfaceTextureClientHybris instance"); -+ return; ++ Parcel data, reply; ++ data.writeInterfaceToken(IMediaRecorderFactory::getInterfaceDescriptor()); ++ remote()->transact(CREATE_MEDIA_RECORDER, data, &reply); ++ return interface_cast(reply.readStrongBinder()); + } ++}; + -+ if (s->refcount > 1) -+ s->refcount--; -+ else -+ surface_texture_client_destroy (stc); ++// ---------------------------------------------------------------------------- ++ ++IMPLEMENT_META_INTERFACE(MediaRecorderFactory, "android.media.IMediaRecorderFactory"); ++ ++// ---------------------------------------------------------------------- ++ ++status_t BnMediaRecorderFactory::onTransact( ++ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) ++{ ++ switch (code) { ++ case CREATE_MEDIA_RECORDER: { ++ CHECK_INTERFACE(IMediaRecorderFactory, data, reply); ++ sp recorder = createMediaRecorder(); ++#if ANDROID_VERSION_MAJOR>=6 ++ reply->writeStrongBinder(IInterface::asBinder(recorder)); ++#else ++ reply->writeStrongBinder(recorder->asBinder()); ++#endif ++ ++ return NO_ERROR; ++ } break; ++ default: ++ return BBinder::onTransact(code, data, reply, flags); ++ } +} + -+void surface_texture_client_set_surface_texture(SurfaceTextureClientHybris stc, EGLNativeWindowType native_window) ++// ---------------------------------------------------------------------------- ++ ++sp MediaRecorderFactory::media_recorder_factory; ++Mutex MediaRecorderFactory::s_lock; ++ ++MediaRecorderFactory::MediaRecorderFactory() +{ -+ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); -+ if (s == NULL) -+ return; ++ REPORT_FUNCTION(); ++} + -+ if (native_window == NULL) ++MediaRecorderFactory::~MediaRecorderFactory() ++{ ++ REPORT_FUNCTION(); ++} ++ ++/*! ++ * \brief Creates and adds the MediaRecorderFactory service to the default Binder ServiceManager ++ */ ++void MediaRecorderFactory::instantiate() ++{ ++ defaultServiceManager()->addService( ++ String16(IMediaRecorderFactory::exported_service_name()), factory_instance()); ++ ALOGV("Added Binder service '%s' to ServiceManager", IMediaRecorderFactory::exported_service_name()); ++} ++ ++/*! ++ * \brief Creates a new MediaRecorderClient instance over Binder ++ * \return A new MediaRecorderClient instance ++ */ ++sp MediaRecorderFactory::createMediaRecorder() ++{ ++ REPORT_FUNCTION(); ++ sp recorder = new MediaRecorderClient(); ++ return recorder; ++} ++ ++/*! ++ * \brief Get a reference to the MediaRecorderFactory singleton instance ++ * \return The MediaRecorderFactory singleton instance ++ */ ++sp& MediaRecorderFactory::factory_instance() ++{ ++ REPORT_FUNCTION(); ++ Mutex::Autolock _l(s_lock); ++ if (media_recorder_factory == NULL) + { -+ ALOGE("native_window must not be NULL"); -+ return; ++ ALOGD("Creating new static instance of MediaRecorderFactory"); ++ media_recorder_factory = new MediaRecorderFactory(); + } + -+ sp surface = static_cast(native_window); -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+ s->setISurfaceTexture(surface->getSurfaceTexture()); -+#else -+ s->setISurfaceTexture(surface->getIGraphicBufferProducer()); -+#endif ++ return media_recorder_factory; +} ++ ++} // namespace android --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/compat/media/surface_texture_client_hybris_priv.h -@@ -0,0 +1,134 @@ ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_recorder_factory.h +@@ -0,0 +1,72 @@ +/* -+ * Copyright (C) 2013 Canonical Ltd ++ * Copyright (C) 2014 Canonical Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. @@ -8680,1001 +9336,4978 @@ + * Authored by: Jim Hodapp + */ + -+#ifndef SURFACE_TEXTURE_CLIENT_HYBRIS_PRIV_H -+#define SURFACE_TEXTURE_CLIENT_HYBRIS_PRIV_H ++#ifndef MEDIA_RECORDER_FACTORY_H_ ++#define MEDIA_RECORDER_FACTORY_H_ + -+#include "hybris/media/surface_texture_client_hybris.h" ++#include + -+#include -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+#include -+#else -+#include -+#endif ++#include ++#include + -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+struct _SurfaceTextureClientHybris : public android::SurfaceTextureClient -+#else -+struct _SurfaceTextureClientHybris : public android::Surface -+#endif -+{ -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+ _SurfaceTextureClientHybris(); -+#endif -+ _SurfaceTextureClientHybris(const _SurfaceTextureClientHybris &stch); -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+ _SurfaceTextureClientHybris(const android::sp &st); -+#else -+ _SurfaceTextureClientHybris(const android::sp &st); -+ _SurfaceTextureClientHybris(const android::sp &st, -+ bool producerIsControlledByApp); -+ _SurfaceTextureClientHybris(const android::sp &bq); -+#endif -+ ~_SurfaceTextureClientHybris(); ++namespace android { + -+ /** Has a texture id or EGLNativeWindowType been passed in, meaning rendering will function? **/ -+ bool isReady() const; -+ void setReady(bool ready = true); ++class Mutex; + ++class IMediaRecorderFactory: public IInterface ++{ +public: -+ int dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd); -+ int queueBuffer(ANativeWindowBuffer* buffer, int fenceFd); -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+ void setISurfaceTexture(const android::sp& surface_texture); -+#else -+ void setISurfaceTexture(const android::sp& surface_texture); -+#endif -+ void setHardwareRendering(bool do_hardware_rendering); -+ bool hardwareRendering(); ++ DECLARE_META_INTERFACE(MediaRecorderFactory); + -+ unsigned int refcount; -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 -+ android::sp surface_texture; -+#else -+ android::sp surface_texture; -+#endif ++ static const char* exported_service_name() { return "android.media.IMediaRecorderFactory"; } ++ ++ virtual sp createMediaRecorder() = 0; ++}; ++ ++// ---------------------------------------------------------------------------- ++ ++class BnMediaRecorderFactory: public BnInterface ++{ ++public: ++ virtual status_t onTransact( uint32_t code, ++ const Parcel& data, ++ Parcel* reply, ++ uint32_t flags = 0); ++}; ++ ++// ---------------------------------------------------------------------------- ++ ++class MediaRecorderFactory : public BnMediaRecorderFactory ++{ ++public: ++ MediaRecorderFactory(); ++ virtual ~MediaRecorderFactory(); ++ ++ static void instantiate(); + ++ virtual sp createMediaRecorder(); +private: -+ bool ready; -+ bool hardware_rendering; ++ static sp& factory_instance(); ++ ++ static sp media_recorder_factory; ++ static Mutex s_lock; +}; + -+namespace android { ++} + -+class _GLConsumerHybris : public GLConsumer ++#endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_recorder_layer.cpp +@@ -0,0 +1,506 @@ ++/* ++ * Copyright (C) 2013-2014 Canonical Ltd ++ * ++ * 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. ++ * ++ * Authored by: Jim Hodapp ++ * Guenter Schwann ++ * Ricardo Salveti de Araujo ++ */ ++ ++#define LOG_NDEBUG 0 ++#undef LOG_TAG ++#define LOG_TAG "MediaRecorderCompatibilityLayer" ++ ++#include "media_recorder.h" ++ ++#include ++#include ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__) ++ ++using namespace android; ++ ++/*! ++ * \brief The MediaRecorderListenerWrapper class is used to listen to camera events ++ * from the MediaRecorder instance ++ */ ++class MediaRecorderListenerWrapper : public android::MediaRecorderListener +{ -+ class FrameAvailableListener : public GLConsumer::FrameAvailableListener ++public: ++ MediaRecorderListenerWrapper() ++ : error_cb(NULL), ++ error_context(NULL), ++ read_audio_cb(NULL), ++ read_audio_context(NULL) ++{ ++} ++ ++ void notify(int msg, int ext1, int ext2) + { -+ public: -+ FrameAvailableListener() -+ : frame_available_cb(NULL), -+ glc_wrapper(NULL), -+ context(NULL) -+ { -+ } ++ ALOGV("\tmsg: %d, ext1: %d, ext2: %d \n", msg, ext1, ext2); + -+ virtual void onFrameAvailable() -+ { -+ if (frame_available_cb != NULL) -+ frame_available_cb(glc_wrapper, context); -+ else -+ ALOGE("Failed to call, frame_available_cb is NULL"); ++ switch (msg) { ++ case android::MEDIA_RECORDER_EVENT_ERROR: ++ ALOGV("\tMEDIA_RECORDER_EVENT_ERROR msg\n"); ++ // TODO: Extend this cb to include the error message ++ if (error_cb != NULL) ++ error_cb(error_context); ++ else ++ ALOGE("Failed to signal error to app layer, callback not set."); ++ break; ++ default: ++ ALOGV("\tUnknown notification\n"); + } ++ } + -+ void setFrameAvailableCbHybris(FrameAvailableCbHybris cb, GLConsumerWrapperHybris wrapper, void *context) -+ { -+ frame_available_cb = cb; -+ glc_wrapper = wrapper; -+ this->context = context; ++ void readAudio() ++ { ++ REPORT_FUNCTION(); ++ if (read_audio_cb != NULL) { ++ read_audio_cb(read_audio_context); + } ++ else ++ ALOGW("Failed to call read_audio_cb since it's NULL"); ++ } + -+ private: -+ FrameAvailableCbHybris frame_available_cb; -+ GLConsumerWrapperHybris glc_wrapper; -+ void *context; -+ }; ++ void setErrorCb(on_recorder_msg_error cb, void *context) ++ { ++ REPORT_FUNCTION(); ++ error_cb = cb; ++ error_context = context; ++ } ++ ++ void setReadAudioCb(on_recorder_read_audio cb, void *context) ++ { ++ REPORT_FUNCTION(); ++ read_audio_cb = cb; ++ read_audio_context = context; ++ } ++ ++private: ++ on_recorder_msg_error error_cb; ++ void *error_context; ++ on_recorder_read_audio read_audio_cb; ++ void *read_audio_context; ++}; + ++/*! ++ * \brief The MediaRecorderWrapper struct wraps the MediaRecorder class ++ */ ++struct MediaRecorderWrapper : public android::MediaRecorder ++{ +public: -+ _GLConsumerHybris(const sp& bq, -+ uint32_t tex, uint32_t textureTarget = TEXTURE_EXTERNAL, -+ bool useFenceSync = true, bool isControlledByApp = false) -+ : GLConsumer(bq, tex, textureTarget, useFenceSync, isControlledByApp) ++ MediaRecorderWrapper() ++ : MediaRecorder(), ++ media_recorder_listener(new MediaRecorderListenerWrapper()) ++{ ++} ++ ++ ~MediaRecorderWrapper() + { ++ reset(); + } + -+ void createFrameAvailableListener(FrameAvailableCbHybris cb, GLConsumerWrapperHybris wrapper, void *context) ++ void init() + { -+ frame_available_listener = new _GLConsumerHybris::FrameAvailableListener(); -+ frame_available_listener->setFrameAvailableCbHybris(cb, wrapper, context); -+ setFrameAvailableListener(frame_available_listener); ++ setListener(media_recorder_listener); ++ } ++ ++ void setErrorCb(on_recorder_msg_error cb, void *context) ++ { ++ REPORT_FUNCTION(); ++ ++ assert(media_recorder_listener != NULL); ++ media_recorder_listener->setErrorCb(cb, context); ++ } ++ ++ void setAudioReadCb(on_recorder_read_audio cb, void *context) ++ { ++ REPORT_FUNCTION(); ++ ++ assert(media_recorder_listener != NULL); ++ media_recorder_listener->setReadAudioCb(cb, context); + } + +private: -+ sp<_GLConsumerHybris::FrameAvailableListener> frame_available_listener; ++ android::sp media_recorder_listener; +}; + -+}; // namespace android ++/*! ++ * \brief android_recorder_set_error_cb ++ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() ++ * \param cb The callback function to be called when a recording error occurs ++ * \param user context to pass through to the error handler ++ */ ++void android_recorder_set_error_cb(MediaRecorderWrapper *mr, on_recorder_msg_error cb, ++ void *context) ++{ ++ REPORT_FUNCTION(); + -+#endif ---- libhybris-0.1.0+git20131207+e452e83.orig/compat/ui/Android.mk -+++ libhybris-0.1.0+git20131207+e452e83/compat/ui/Android.mk -@@ -1,5 +1,6 @@ - LOCAL_PATH:= $(call my-dir) - include $(CLEAR_VARS) -+include $(LOCAL_PATH)/../Android.common.mk - - HYBRIS_PATH := $(LOCAL_PATH)/../../hybris - ---- libhybris-0.1.0+git20131207+e452e83.orig/compat/ui/ui_compatibility_layer.cpp -+++ libhybris-0.1.0+git20131207+e452e83/compat/ui/ui_compatibility_layer.cpp -@@ -126,6 +126,7 @@ void* graphic_buffer_get_native_buffer(s - return buffer->self->getNativeBuffer(); - } - -+#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 - void graphic_buffer_set_index(struct graphic_buffer *buffer, int index) - { - return buffer->self->setIndex(index); -@@ -135,6 +136,7 @@ int graphic_buffer_get_index(struct grap - { - return buffer->self->getIndex(); - } -+#endif - - int graphic_buffer_init_check(struct graphic_buffer *buffer) - { ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/Makefile.am -+++ libhybris-0.1.0+git20131207+e452e83/hybris/Makefile.am -@@ -4,7 +4,7 @@ if HAS_ANDROID_4_2_0 - SUBDIRS += libsync - endif - --SUBDIRS += egl glesv1 glesv2 ui sf input camera -+SUBDIRS += egl glesv1 glesv2 ui sf input camera media wifi - if HAS_LIBNFC_NXP_HEADERS - SUBDIRS += libnfc_nxp libnfc_ndef_nxp - endif ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/camera/camera.c -+++ libhybris-0.1.0+git20131207+e452e83/hybris/camera/camera.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (C) 2013 Canonical Ltd -+ * Copyright (C) 2013 - 2014 Canonical Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. -@@ -53,6 +53,8 @@ HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, - struct CameraControl*, AutoFocusMode); - HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_set_picture_size, - struct CameraControl*, int, int); -+HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_set_thumbnail_size, -+ struct CameraControl*, int, int); - HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_set_preview_size, - struct CameraControl*, int, int); - HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, android_camera_set_display_orientation, -@@ -69,8 +71,12 @@ HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, - struct CameraControl*, int); - HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, android_camera_set_rotation, - struct CameraControl*, int); -+HYBRIS_IMPLEMENT_VOID_FUNCTION6(camera, android_camera_set_location, -+ struct CameraControl*, const float*, const float*, const float*, int, const char*); - HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_set_video_size, - struct CameraControl*, int, int); -+HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, android_camera_set_jpeg_quality, -+ struct CameraControl*, int); - - // Getters - HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, android_camera_get_effect_mode, -@@ -87,6 +93,8 @@ HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, - struct CameraControl*, int*); - HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_get_picture_size, - struct CameraControl*, int*, int*); -+HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_get_thumbnail_size, -+ struct CameraControl*, int*, int*); - HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_get_preview_size, - struct CameraControl*, int*, int*); - HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_get_preview_fps_range, -@@ -97,14 +105,22 @@ HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, - struct CameraControl*, float*); - HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_get_video_size, - struct CameraControl*, int*, int*); -+HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, android_camera_get_jpeg_quality, -+ struct CameraControl*, int*); - - // Enumerators - HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_enumerate_supported_picture_sizes, - struct CameraControl*, size_callback, void*); -+HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_enumerate_supported_thumbnail_sizes, -+ struct CameraControl*, size_callback, void*); - HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_enumerate_supported_preview_sizes, - struct CameraControl*, size_callback, void*); - HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_enumerate_supported_video_sizes, - struct CameraControl*, size_callback, void*); -+HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_enumerate_supported_scene_modes, -+ struct CameraControl*, scene_mode_callback, void*); -+HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_enumerate_supported_flash_modes, -+ struct CameraControl*, flash_mode_callback, void*); - - HYBRIS_IMPLEMENT_VOID_FUNCTION1(camera, android_camera_update_preview_texture, struct CameraControl*); - ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/common/Makefile.am -+++ libhybris-0.1.0+git20131207+e452e83/hybris/common/Makefile.am -@@ -19,7 +19,8 @@ libhybris_common_la_SOURCES = \ - hooks_shm.c \ - strlcpy.c \ - dlfcn.c \ -- logging.c -+ logging.c \ -+ sysconf.c - libhybris_common_la_CFLAGS = \ - -I$(top_srcdir)/include \ - -I$(top_srcdir)/common ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/common/hooks.c -+++ libhybris-0.1.0+git20131207+e452e83/hybris/common/hooks.c -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -42,6 +43,10 @@ - #include - #include - -+#include -+#include -+#include -+ - #include - #include - #include -@@ -64,8 +69,12 @@ static int locale_inited = 0; - - #define ANDROID_MUTEX_SHARED_MASK 0x2000 - #define ANDROID_COND_SHARED_MASK 0x0001 -+#define ANDROID_COND_COUNTER_INCREMENT 0x0002 -+#define ANDROID_COND_COUNTER_MASK (~ANDROID_COND_SHARED_MASK) - #define ANDROID_RWLOCKATTR_SHARED_MASK 0x0010 - -+#define ANDROID_COND_IS_SHARED(c) (((c)->value & ANDROID_COND_SHARED_MASK) != 0) -+ - /* For the static initializer types */ - #define ANDROID_PTHREAD_MUTEX_INITIALIZER 0 - #define ANDROID_PTHREAD_RECURSIVE_MUTEX_INITIALIZER 0x4000 -@@ -87,6 +96,11 @@ struct _hook { - void *func; - }; - -+/* pthread cond struct as done in Android */ -+typedef struct { -+ int volatile value; -+} android_cond_t; -+ - /* Helpers */ - static int hybris_check_android_shared_mutex(unsigned int mutex_addr) - { -@@ -109,9 +123,59 @@ static int hybris_check_android_shared_c - (cond_addr & ANDROID_COND_SHARED_MASK)) - return 1; - -+ /* In case android is setting up cond_addr with a negative value, -+ * used for error control */ -+ if (cond_addr > HYBRIS_SHM_MASK_TOP) -+ return 1; -+ - return 0; - } - -+/* Based on Android's Bionic pthread implementation. -+ * This is just needed when we have a shared cond with Android */ -+static int __android_pthread_cond_pulse(android_cond_t *cond, int counter) -+{ -+ long flags; -+ int fret; -+ -+ if (cond == NULL) -+ return EINVAL; -+ -+ flags = (cond->value & ~ANDROID_COND_COUNTER_MASK); -+ for (;;) { -+ long oldval = cond->value; -+ long newval = 0; -+ /* In our case all we need to do is make sure the negative value -+ * is under our range, which is the last 0xF from SHM_MASK */ -+ if (oldval < -12) -+ newval = ((oldval + ANDROID_COND_COUNTER_INCREMENT) & -+ ANDROID_COND_COUNTER_MASK) | flags; -+ else -+ newval = ((oldval - ANDROID_COND_COUNTER_INCREMENT) & -+ ANDROID_COND_COUNTER_MASK) | flags; -+ if (__sync_bool_compare_and_swap(&cond->value, oldval, newval)) -+ break; ++ if (mr == NULL) { ++ ALOGE("mr must not be NULL"); ++ return; + } + -+ int pshared = cond->value & ANDROID_COND_SHARED_MASK; -+ fret = syscall(SYS_futex , &cond->value, -+ pshared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE, counter, -+ NULL, NULL, NULL); -+ LOGD("futex based pthread_cond_*, value %d, counter %d, ret %d", -+ cond->value, counter, fret); -+ return 0; ++ mr->setErrorCb(cb, context); +} + -+int android_pthread_cond_broadcast(android_cond_t *cond) ++void android_recorder_set_audio_read_cb(MediaRecorderWrapper *mr, on_recorder_read_audio cb, ++ void *context) +{ -+ return __android_pthread_cond_pulse(cond, INT_MAX); -+} ++ REPORT_FUNCTION(); + -+int android_pthread_cond_signal(android_cond_t *cond) -+{ -+ return __android_pthread_cond_pulse(cond, 1); -+} ++ if (mr == NULL) { ++ ALOGE("mr must not be NULL"); ++ return; ++ } + - static void hybris_set_mutex_attr(unsigned int android_value, pthread_mutexattr_t *attr) - { - /* Init already sets as PTHREAD_MUTEX_NORMAL */ -@@ -577,8 +641,8 @@ static int my_pthread_cond_broadcast(pth - { - unsigned int value = (*(unsigned int *) cond); - if (hybris_check_android_shared_cond(value)) { -- LOGD("shared condition with Android, not broadcasting."); -- return 0; -+ LOGD("Shared condition with Android, broadcasting with futex."); -+ return android_pthread_cond_broadcast((android_cond_t *) cond); - } - - pthread_cond_t *realcond = (pthread_cond_t *) value; -@@ -598,8 +662,8 @@ static int my_pthread_cond_signal(pthrea - unsigned int value = (*(unsigned int *) cond); - - if (hybris_check_android_shared_cond(value)) { -- LOGD("Shared condition with Android, not signaling."); -- return 0; -+ LOGD("Shared condition with Android, broadcasting with futex."); -+ return android_pthread_cond_signal((android_cond_t *) cond); - } - - pthread_cond_t *realcond = (pthread_cond_t *) value; -@@ -1175,38 +1239,43 @@ static int my_setlinebuf(FILE *fp) - return 0; - } - --long my_sysconf(int name) -+static inline void swap(void **a, void **b) - { -- /* -- * bionic has different values for the values below. -- * TODO: compare the values between glibc and bionic and complete the mapping -- */ -- switch (name) { -- case 0x27: -- return sysconf(_SC_PAGESIZE); -- case 0x28: -- return sysconf(_SC_PAGE_SIZE); -- case 0x60: -- return sysconf(_SC_NPROCESSORS_CONF); -- case 0x61: -- return sysconf(_SC_NPROCESSORS_ONLN); -- default: -- break; -- } -- -- -- long rv = sysconf(name); -- --#ifdef DEBUG -- if (rv == -1) { -- printf("sysconf failed for %li\n", name); -- exit(-1); -- } --#endif -+ void *tmp = *a; -+ *a = *b; -+ *b = tmp; ++ mr->setAudioReadCb(cb, context); +} + -+static int my_getaddrinfo(const char *hostname, const char *servname, -+ const struct addrinfo *hints, struct addrinfo **res) ++/*! ++ * \brief android_media_new_recorder creates a new MediaRecorder ++ * \return New MediaRecorder object, or NULL if the object could not be created. ++ */ ++MediaRecorderWrapper *android_media_new_recorder() +{ -+ // make a local copy of hints -+ struct addrinfo *fixed_hints = (struct addrinfo*)malloc(sizeof(struct addrinfo)); -+ memcpy(fixed_hints, hints, sizeof(struct addrinfo)); -+ // fix bionic -> glibc missmatch -+ swap((void**)&(fixed_hints->ai_canonname), (void**)&(fixed_hints->ai_addr)); -+ // do glibc getaddrinfo -+ int result = getaddrinfo(hostname, servname, fixed_hints, res); -+ // release the copy of hints -+ free(fixed_hints); -+ // fix bionic <- glibc missmatch -+ struct addrinfo *it = *res; -+ while(NULL != it) -+ { -+ swap((void**)&(it->ai_canonname), (void**)&(it->ai_addr)); -+ it = it->ai_next; ++ REPORT_FUNCTION(); ++ ++ MediaRecorderWrapper *mr = new MediaRecorderWrapper; ++ if (mr == NULL) { ++ ALOGE("Failed to create new MediaRecorder instance."); ++ return NULL; + } -+ return result; -+} - -- return rv; -+static void my_freeaddrinfo(struct addrinfo *__ai) -+{ -+ swap((void**)&(__ai->ai_canonname), (void**)&(__ai->ai_addr)); -+ freeaddrinfo(__ai); - } - -+extern long my_sysconf(int name); + - FP_ATTRIB static double my_strtod(const char *nptr, char **endptr) - { - if (locale_inited == 0) -@@ -1217,6 +1286,56 @@ FP_ATTRIB static double my_strtod(const - return strtod_l(nptr, endptr, hybris_locale); - } - -+static int __my_system_property_read(const void *pi, char *name, char *value) -+{ -+ return property_get(name, value, NULL); ++ return mr; +} + -+static int __my_system_property_get(const char *name, char *value) ++/*! ++ * \brief android_recorder_initCheck ++ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() ++ * \return negative value if an error occured ++ */ ++int android_recorder_initCheck(MediaRecorderWrapper *mr) +{ -+ return property_get(name, value, NULL); -+} ++ REPORT_FUNCTION(); + -+static int __my_system_property_foreach(void (*propfn)(const void *pi, void *cookie), void *cookie) -+{ -+ return 0; -+} ++ if (mr == NULL) { ++ ALOGE("mr must not be NULL"); ++ return android::BAD_VALUE; ++ } + -+static const void *__my_system_property_find(const char *name) -+{ -+ return NULL; ++ return mr->initCheck(); +} + -+static unsigned int __my_system_property_serial(const void *pi) ++/*! ++ * \brief android_recorder_setCamera sets the camera object for recording videos from the camera ++ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() ++ * \param control Wrapper for the camera (see camera in hybris) ++ * \return negative value if an error occured ++ */ ++int android_recorder_setCamera(MediaRecorderWrapper *mr, CameraControl* control) +{ -+ return 0; -+} ++ REPORT_FUNCTION(); + -+static int __my_system_property_wait(const void *pi) -+{ -+ return 0; -+} ++ if (mr == NULL) { ++ ALOGE("mr must not be NULL"); ++ return android::BAD_VALUE; ++ } ++ if (control == NULL) { ++ ALOGE("control must not be NULL"); ++ return android::BAD_VALUE; ++ } + -+static int __my_system_property_update(void *pi, const char *value, unsigned int len) ++ mr->init(); ++ ++ return mr->setCamera(control->camera->remote(), control->camera->getRecordingProxy()); ++} ++ ++/*! ++ * \brief android_recorder_setVideoSource sets the video source. ++ * If no video source is set, only audio is recorded. ++ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() ++ * \param vs The video source. It's either a camera or a gralloc buffer ++ * \return negative value if an error occured ++ */ ++int android_recorder_setVideoSource(MediaRecorderWrapper *mr, VideoSource vs) +{ -+ return 0; ++ REPORT_FUNCTION(); ++ ++ if (mr == NULL) { ++ ALOGE("mr must not be NULL"); ++ return android::BAD_VALUE; ++ } ++ ++ return mr->setVideoSource(static_cast(vs)); +} + -+static int __my_system_property_add(const char *name, unsigned int namelen, const char *value, unsigned int valuelen) ++/*! ++ * \brief android_recorder_setAudioSource ++ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() ++ * \param as The audio source. ++ * \return negative value if an error occured ++ */ ++int android_recorder_setAudioSource(MediaRecorderWrapper *mr, AudioSource as) +{ -+ return 0; ++ REPORT_FUNCTION(); ++ ++ if (mr == NULL) { ++ ALOGE("mr must not be NULL"); ++ return android::BAD_VALUE; ++ } ++ ++ return mr->setAudioSource(static_cast(as)); +} + -+static unsigned int __my_system_property_wait_any(unsigned int serial) ++/*! ++ * \brief android_recorder_setOutputFormat ++ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() ++ * \param of The output file container format ++ * \return negative value if an error occured ++ */ ++int android_recorder_setOutputFormat(MediaRecorderWrapper *mr, OutputFormat of) +{ -+ return 0; ++ REPORT_FUNCTION(); ++ ++ if (mr == NULL) { ++ ALOGE("mr must not be NULL"); ++ return android::BAD_VALUE; ++ } ++ ++ return mr->setOutputFormat(static_cast(of)); +} + -+static const void *__my_system_property_find_nth(unsigned n) ++/*! ++ * \brief android_recorder_setVideoEncoder ++ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() ++ * \param ve The video encoder sets the codec type for encoding/recording video ++ * \return negative value if an error occured ++ */ ++int android_recorder_setVideoEncoder(MediaRecorderWrapper *mr, VideoEncoder ve) +{ -+ return NULL; ++ REPORT_FUNCTION(); ++ ++ if (mr == NULL) { ++ ALOGE("mr must not be NULL"); ++ return android::BAD_VALUE; ++ } ++ ++ return mr->setVideoEncoder(static_cast(ve)); +} + - extern int __cxa_atexit(void (*)(void*), void*, void*); - - static struct _hook hooks[] = { -@@ -1307,7 +1426,7 @@ static struct _hook hooks[] = { - {"pthread_mutex_lock_timeout_np", my_pthread_mutex_lock_timeout_np}, - {"pthread_mutexattr_init", pthread_mutexattr_init}, - {"pthread_mutexattr_destroy", pthread_mutexattr_destroy}, -- {"pthread_mutexattr_getttype", pthread_mutexattr_gettype}, -+ {"pthread_mutexattr_gettype", pthread_mutexattr_gettype}, - {"pthread_mutexattr_settype", pthread_mutexattr_settype}, - {"pthread_mutexattr_getpshared", pthread_mutexattr_getpshared}, - {"pthread_mutexattr_setpshared", my_pthread_mutexattr_setpshared}, -@@ -1347,7 +1466,7 @@ static struct _hook hooks[] = { - {"pthread_attr_setguardsize", my_pthread_attr_setguardsize}, - {"pthread_attr_getguardsize", my_pthread_attr_getguardsize}, - {"pthread_attr_setscope", my_pthread_attr_setscope}, -- {"pthread_attr_setscope", my_pthread_attr_getscope}, -+ {"pthread_attr_getscope", my_pthread_attr_getscope}, - {"pthread_getattr_np", my_pthread_getattr_np}, - {"pthread_rwlockattr_init", my_pthread_rwlockattr_init}, - {"pthread_rwlockattr_destroy", my_pthread_rwlockattr_destroy}, -@@ -1422,7 +1541,8 @@ static struct _hook hooks[] = { - {"__errno", __errno_location}, - {"__set_errno", my_set_errno}, - /* net specifics, to avoid __res_get_state */ -- {"getaddrinfo", getaddrinfo}, -+ {"getaddrinfo", my_getaddrinfo}, -+ {"freeaddrinfo", my_freeaddrinfo}, - {"gethostbyaddr", gethostbyaddr}, - {"gethostbyname", gethostbyname}, - {"gethostbyname2", gethostbyname2}, -@@ -1449,21 +1569,43 @@ static struct _hook hooks[] = { - /* grp.h */ - {"getgrgid", getgrgid}, - {"__cxa_atexit", __cxa_atexit}, -- {NULL, NULL}, -+ {"__system_property_read", __my_system_property_read}, -+ {"__system_property_get", __my_system_property_get}, -+ {"__system_property_set", property_set}, -+ {"__system_property_foreach", __my_system_property_foreach}, -+ {"__system_property_find", __my_system_property_find}, -+ {"__system_property_serial", __my_system_property_serial}, -+ {"__system_property_wait", __my_system_property_wait}, -+ {"__system_property_update", __my_system_property_update}, -+ {"__system_property_add", __my_system_property_add}, -+ {"__system_property_wait_any", __my_system_property_wait_any}, -+ {"__system_property_find_nth", __my_system_property_find_nth}, - }; - -+static int hook_cmp(const void *a, const void *b) ++/*! ++ * \brief android_recorder_setAudioEncoder ++ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() ++ * \param ae The audio encoder sets the codec type for encoding/recording audio ++ * \return negative value if an error occured ++ */ ++int android_recorder_setAudioEncoder(MediaRecorderWrapper *mr, AudioEncoder ae) +{ -+ return strcmp(((struct _hook*)a)->name, ((struct _hook*)b)->name); ++ REPORT_FUNCTION(); ++ ++ if (mr == NULL) { ++ ALOGE("mr must not be NULL"); ++ return android::BAD_VALUE; ++ } ++ ++ return mr->setAudioEncoder(static_cast(ae)); +} + - void *get_hooked_symbol(char *sym) - { -- struct _hook *ptr = &hooks[0]; - static int counter = -1; -+ static int sorted = 0; -+ const int nhooks = sizeof(hooks) / sizeof(hooks[0]); -+ void *found = NULL; -+ struct _hook key; - -- while (ptr->name != NULL) -+ if (!sorted) - { -- if (strcmp(sym, ptr->name) == 0){ -- return ptr->func; -- } -- ptr++; -+ qsort(hooks, nhooks, sizeof(hooks[0]), hook_cmp); -+ sorted = 1; - } ++/*! ++ * \brief android_recorder_setOutputFile sets the output file to the given file descriptor ++ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() ++ * \param fd File descriptor of an open file, that the stream can be written to ++ * \return negative value if an error occured ++ */ ++int android_recorder_setOutputFile(MediaRecorderWrapper *mr, int fd) ++{ ++ REPORT_FUNCTION(); + -+ key.name = sym; -+ found = bsearch(&key, hooks, nhooks, sizeof(hooks[0]), hook_cmp); -+ if (found != NULL) -+ return ((struct _hook*)found)->func; ++ if (mr == NULL) { ++ ALOGE("mr must not be NULL"); ++ return android::BAD_VALUE; ++ } + - if (strstr(sym, "pthread") != NULL) - { - /* safe */ ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/common/hooks_shm.c -+++ libhybris-0.1.0+git20131207+e452e83/hybris/common/hooks_shm.c -@@ -123,7 +123,9 @@ static void _hybris_shm_init() - else { - LOGD("Creating a new shared memory segment."); - -- _hybris_shm_fd = shm_open(HYBRIS_SHM_PATH, O_RDWR | O_CREAT, 0660); -+ mode_t pumask = umask(0); -+ _hybris_shm_fd = shm_open(HYBRIS_SHM_PATH, O_RDWR | O_CREAT, 0666); -+ umask(pumask); - if (_hybris_shm_fd >= 0) { - ftruncate( _hybris_shm_fd, size_to_map ); - /* Map the memory object */ -@@ -171,11 +173,12 @@ static void _hybris_shm_extend_region() - - /* - * Determine if the pointer that has been extracted by hybris is -- * pointing to an address in the shared memory -+ * pointing to an address in the shared memory. - */ - int hybris_is_pointer_in_shm(void *ptr) - { -- if ((unsigned int)ptr >= HYBRIS_SHM_MASK) -+ if (((unsigned int) ptr >= HYBRIS_SHM_MASK) && -+ ((unsigned int) ptr <= HYBRIS_SHM_MASK_TOP)) - return 1; - - return 0; ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/common/hooks_shm.h -+++ libhybris-0.1.0+git20131207+e452e83/hybris/common/hooks_shm.h -@@ -20,6 +20,9 @@ - - #include - -+/* Leave space to workaround the issue that Android might pass negative int values */ -+#define HYBRIS_SHM_MASK_TOP 0xFFFFFFF0UL ++ return mr->setOutputFile(fd, 0, 0); ++} + - typedef unsigned int hybris_shm_pointer_t; - - /* ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/common/jb/Makefile.am -+++ libhybris-0.1.0+git20131207+e452e83/hybris/common/jb/Makefile.am -@@ -17,6 +17,7 @@ libandroid_linker_la_SOURCES = \ - libandroid_linker_la_CFLAGS = \ - -I$(top_srcdir)/include \ - -I$(top_srcdir)/common \ -+ -D_GNU_SOURCE \ - -DLINKER_TEXT_BASE=0xB0000100 \ - -DLINKER_AREA_SIZE=0x01000000 \ - -DDEFAULT_HYBRIS_LD_LIBRARY_PATH="\"@DEFAULT_HYBRIS_LD_LIBRARY_PATH@\"" \ ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/common/jb/dlfcn.c -+++ libhybris-0.1.0+git20131207+e452e83/hybris/common/jb/dlfcn.c -@@ -43,7 +43,7 @@ static const char *dl_errors[] = { - #define likely(expr) __builtin_expect (expr, 1) - #define unlikely(expr) __builtin_expect (expr, 0) - --static pthread_mutex_t dl_lock = PTHREAD_MUTEX_INITIALIZER; -+static pthread_mutex_t dl_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; - - static void set_dlerror(int err) - { -@@ -78,7 +78,7 @@ const char *android_dlerror(void) - void *android_dlsym(void *handle, const char *symbol) - { - soinfo *found; -- Elf32_Sym *sym; -+ Elf_Sym *sym; - unsigned bind; - - pthread_mutex_lock(&dl_lock); -@@ -142,7 +142,7 @@ int android_dladdr(const void *addr, Dl_ - info->dli_fbase = (void*)si->base; - - /* Determine if any symbol in the library contains the specified address */ -- Elf32_Sym *sym = find_containing_symbol(addr, si); -+ Elf_Sym *sym = find_containing_symbol(addr, si); - - if(sym != NULL) { - info->dli_sname = si->strtab + sym->st_name; -@@ -165,11 +165,13 @@ int android_dlclose(void *handle) - return 0; - } - -+int android_dl_iterate_phdr(int (*cb)(struct dl_phdr_info *info, size_t size, void *data),void *data); ++/*! ++ * \brief android_recorder_setVideoSize ++ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() ++ * \param width output width for the video to record ++ * \param height output height for the video to record ++ * \return negative value if an error occured ++ */ ++int android_recorder_setVideoSize(MediaRecorderWrapper *mr, int width, int height) ++{ ++ REPORT_FUNCTION(); + - #if defined(ANDROID_ARM_LINKER) - // 0000000 00011111 111112 22222222 2333333 333344444444445555555 - // 0123456 78901234 567890 12345678 9012345 678901234567890123456 - #define ANDROID_LIBDL_STRTAB \ -- "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_unwind_find_exidx\0" -+ "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_iterate_phdr\0dl_unwind_find_exidx\0" - - _Unwind_Ptr android_dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount); - -@@ -179,8 +181,6 @@ _Unwind_Ptr android_dl_unwind_find_exidx - #define ANDROID_LIBDL_STRTAB \ - "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_iterate_phdr\0" - --int android_dl_iterate_phdr(int (*cb)(struct dl_phdr_info *info, size_t size, void *data),void *data); -- - #elif defined(ANDROID_SH_LINKER) - // 0000000 00011111 111112 22222222 2333333 3333444444444455 - // 0123456 78901234 567890 12345678 9012345 6789012345678901 -@@ -192,7 +192,7 @@ int android_dl_iterate_phdr(int (*cb)(st - #endif - - --static Elf32_Sym libdl_symtab[] = { -+static Elf_Sym libdl_symtab[] = { - // total length of libdl_info.strtab, including trailing 0 - // This is actually the the STH_UNDEF entry. Technically, it's - // supposed to have st_name == 0, but instead, it points to an index -@@ -200,45 +200,38 @@ static Elf32_Sym libdl_symtab[] = { - { st_name: sizeof(ANDROID_LIBDL_STRTAB) - 1, - }, - { st_name: 0, // starting index of the name in libdl_info.strtab -- st_value: (Elf32_Addr) &android_dlopen, -+ st_value: (Elf_Addr) &android_dlopen, - st_info: STB_GLOBAL << 4, - st_shndx: 1, - }, - { st_name: 7, -- st_value: (Elf32_Addr) &android_dlclose, -+ st_value: (Elf_Addr) &android_dlclose, - st_info: STB_GLOBAL << 4, - st_shndx: 1, - }, - { st_name: 15, -- st_value: (Elf32_Addr) &android_dlsym, -+ st_value: (Elf_Addr) &android_dlsym, - st_info: STB_GLOBAL << 4, - st_shndx: 1, - }, - { st_name: 21, -- st_value: (Elf32_Addr) &android_dlerror, -+ st_value: (Elf_Addr) &android_dlerror, - st_info: STB_GLOBAL << 4, - st_shndx: 1, - }, - { st_name: 29, -- st_value: (Elf32_Addr) &android_dladdr, -+ st_value: (Elf_Addr) &android_dladdr, - st_info: STB_GLOBAL << 4, - st_shndx: 1, - }, --#ifdef ANDROID_ARM_LINKER - { st_name: 36, -- st_value: (Elf32_Addr) &android_dl_unwind_find_exidx, -+ st_value: (Elf_Addr) &android_dl_iterate_phdr, - st_info: STB_GLOBAL << 4, - st_shndx: 1, - }, --#elif defined(ANDROID_X86_LINKER) -- { st_name: 36, -- st_value: (Elf32_Addr) &android_dl_iterate_phdr, -- st_info: STB_GLOBAL << 4, -- st_shndx: 1, -- }, --#elif defined(ANDROID_SH_LINKER) -- { st_name: 36, -- st_value: (Elf32_Addr) &android_dl_iterate_phdr, -+#ifdef ANDROID_ARM_LINKER -+ { st_name: 52, -+ st_value: (Elf_Addr) &android_dl_unwind_find_exidx, - st_info: STB_GLOBAL << 4, - st_shndx: 1, - }, -@@ -265,7 +258,11 @@ static Elf32_Sym libdl_symtab[] = { - * stubbing them out in libdl. - */ - static unsigned libdl_buckets[1] = { 1 }; -+#ifdef ANDROID_ARM_LINKER -+static unsigned libdl_chains[8] = { 0, 2, 3, 4, 5, 6, 7, 0 }; -+#else - static unsigned libdl_chains[7] = { 0, 2, 3, 4, 5, 6, 0 }; -+#endif - - soinfo libdl_info = { - name: "libdl.so", -@@ -274,8 +271,8 @@ soinfo libdl_info = { - strtab: ANDROID_LIBDL_STRTAB, - symtab: libdl_symtab, - -- nbucket: 1, -- nchain: 7, -+ nbucket: sizeof(libdl_buckets)/sizeof(unsigned), -+ nchain: sizeof(libdl_chains)/sizeof(unsigned), - bucket: libdl_buckets, - chain: libdl_chains, - }; ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/common/jb/linker.c -+++ libhybris-0.1.0+git20131207+e452e83/hybris/common/jb/linker.c -@@ -357,7 +357,8 @@ _Unwind_Ptr android_dl_unwind_find_exidx - *pcount = 0; - return NULL; - } --#elif defined(ANDROID_X86_LINKER) -+#endif ++ if (mr == NULL) { ++ ALOGE("mr must not be NULL"); ++ return android::BAD_VALUE; ++ } + - /* Here, we only have to provide a callback to iterate across all the - * loaded libraries. gcc_eh does the rest. */ - int -@@ -379,12 +380,11 @@ android_dl_iterate_phdr(int (*cb)(struct - } - return rv; - } --#endif - --static Elf32_Sym *_elf_lookup(soinfo *si, unsigned hash, const char *name) -+static Elf_Sym *_elf_lookup(soinfo *si, unsigned hash, const char *name) - { -- Elf32_Sym *s; -- Elf32_Sym *symtab = si->symtab; -+ Elf_Sym *s; -+ Elf_Sym *symtab = si->symtab; - const char *strtab = si->strtab; - unsigned n; - -@@ -426,11 +426,11 @@ static unsigned elfhash(const char *_nam - return h; - } - --static Elf32_Sym * -+static Elf_Sym * - _do_lookup(soinfo *si, const char *name, unsigned *base) - { - unsigned elf_hash = elfhash(name); -- Elf32_Sym *s; -+ Elf_Sym *s; - unsigned *d; - soinfo *lsi = si; - int i; -@@ -502,17 +502,17 @@ done: - /* This is used by dl_sym(). It performs symbol lookup only within the - specified soinfo object and not in any of its dependencies. - */ --Elf32_Sym *lookup_in_library(soinfo *si, const char *name) -+Elf_Sym *lookup_in_library(soinfo *si, const char *name) - { - return _elf_lookup(si, elfhash(name), name); - } - - /* This is used by dl_sym(). It performs a global symbol lookup. - */ --Elf32_Sym *lookup(const char *name, soinfo **found, soinfo *start) -+Elf_Sym *lookup(const char *name, soinfo **found, soinfo *start) - { - unsigned elf_hash = elfhash(name); -- Elf32_Sym *s = NULL; -+ Elf_Sym *s = NULL; - soinfo *si; - - if(start == NULL) { -@@ -553,7 +553,7 @@ soinfo *find_containing_library(const vo - return NULL; - } - --Elf32_Sym *find_containing_symbol(const void *addr, soinfo *si) -+Elf_Sym *find_containing_symbol(const void *addr, soinfo *si) - { - unsigned int i; - unsigned soaddr = (unsigned)addr - si->base; -@@ -561,7 +561,7 @@ Elf32_Sym *find_containing_symbol(const - /* Search the library's symbol table for any defined symbol which - * contains this address */ - for(i=0; inchain; i++) { -- Elf32_Sym *sym = &si->symtab[i]; -+ Elf_Sym *sym = &si->symtab[i]; - - if(sym->st_shndx != SHN_UNDEF && - soaddr >= sym->st_value && -@@ -576,7 +576,7 @@ Elf32_Sym *find_containing_symbol(const - #if 0 - static void dump(soinfo *si) - { -- Elf32_Sym *s = si->symtab; -+ Elf_Sym *s = si->symtab; - unsigned n; - - for(n = 0; n < si->nchain; n++) { -@@ -705,7 +705,7 @@ is_prelinked(int fd, const char *name) - static int - verify_elf_object(void *base, const char *name) - { -- Elf32_Ehdr *hdr = (Elf32_Ehdr *) base; -+ Elf_Ehdr *hdr = (Elf_Ehdr *) base; - - if (hdr->e_ident[EI_MAG0] != ELFMAG0) return -1; - if (hdr->e_ident[EI_MAG1] != ELFMAG1) return -1; -@@ -750,8 +750,8 @@ get_lib_extents(int fd, const char *name - unsigned min_vaddr = 0xffffffff; - unsigned max_vaddr = 0; - unsigned char *_hdr = (unsigned char *)__hdr; -- Elf32_Ehdr *ehdr = (Elf32_Ehdr *)_hdr; -- Elf32_Phdr *phdr; -+ Elf_Ehdr *ehdr = (Elf_Ehdr *)_hdr; -+ Elf_Phdr *phdr; - int cnt; - - TRACE("[ %5d Computing extents for '%s'. ]\n", pid, name); -@@ -770,7 +770,7 @@ get_lib_extents(int fd, const char *name - TRACE("[ %5d - Non-prelinked library '%s' found. ]\n", pid, name); - } - -- phdr = (Elf32_Phdr *)(_hdr + ehdr->e_phoff); -+ phdr = (Elf_Phdr *)(_hdr + ehdr->e_phoff); - - /* find the min/max p_vaddrs from all the PT_LOAD segments so we can - * get the range. */ -@@ -885,12 +885,12 @@ err: - static int - load_segments(int fd, void *header, soinfo *si) - { -- Elf32_Ehdr *ehdr = (Elf32_Ehdr *)header; -- Elf32_Phdr *phdr = (Elf32_Phdr *)((unsigned char *)header + ehdr->e_phoff); -- Elf32_Addr base = (Elf32_Addr) si->base; -+ Elf_Ehdr *ehdr = (Elf_Ehdr *)header; -+ Elf_Phdr *phdr = (Elf_Phdr *)((unsigned char *)header + ehdr->e_phoff); -+ Elf_Addr base = (Elf_Addr) si->base; - int cnt; - unsigned len; -- Elf32_Addr tmp; -+ Elf_Addr tmp; - unsigned char *pbase; - unsigned char *extra_base; - unsigned extra_len; -@@ -956,7 +956,7 @@ load_segments(int fd, void *header, soin - * | | - * _+---------------------+ page boundary - */ -- tmp = (Elf32_Addr)(((unsigned)pbase + len + PAGE_SIZE - 1) & -+ tmp = (Elf_Addr)(((unsigned)pbase + len + PAGE_SIZE - 1) & - (~PAGE_MASK)); - if (tmp < (base + phdr->p_vaddr + phdr->p_memsz)) { - extra_len = base + phdr->p_vaddr + phdr->p_memsz - tmp; -@@ -1020,7 +1020,7 @@ load_segments(int fd, void *header, soin - phdr->p_vaddr, phdr->p_memsz); - goto fail; - } -- si->gnu_relro_start = (Elf32_Addr) (base + phdr->p_vaddr); -+ si->gnu_relro_start = (Elf_Addr) (base + phdr->p_vaddr); - si->gnu_relro_len = (unsigned) phdr->p_memsz; - } else { - #ifdef ANDROID_ARM_LINKER -@@ -1067,11 +1067,11 @@ fail: - */ - #if 0 - static unsigned --get_wr_offset(int fd, const char *name, Elf32_Ehdr *ehdr) -+get_wr_offset(int fd, const char *name, Elf_Ehdr *ehdr) - { -- Elf32_Shdr *shdr_start; -- Elf32_Shdr *shdr; -- int shdr_sz = ehdr->e_shnum * sizeof(Elf32_Shdr); -+ Elf_Shdr *shdr_start; -+ Elf_Shdr *shdr; -+ int shdr_sz = ehdr->e_shnum * sizeof(Elf_Shdr); - int cnt; - unsigned wr_offset = 0xffffffff; - -@@ -1104,7 +1104,7 @@ load_library(const char *name) - unsigned req_base; - const char *bname; - soinfo *si = NULL; -- Elf32_Ehdr *hdr; -+ Elf_Ehdr *hdr; - - if(fd == -1) { - DL_ERR("Library '%s' not found", name); -@@ -1161,8 +1161,8 @@ load_library(const char *name) - - /* this might not be right. Technically, we don't even need this info - * once we go through 'load_segments'. */ -- hdr = (Elf32_Ehdr *)si->base; -- si->phdr = (Elf32_Phdr *)((unsigned char *)si->base + hdr->e_phoff); -+ hdr = (Elf_Ehdr *)si->base; -+ si->phdr = (Elf_Phdr *)((unsigned char *)si->base + hdr->e_phoff); - si->phnum = hdr->e_phnum; - /**/ - -@@ -1261,7 +1261,7 @@ unsigned unload_library(soinfo *si) - * in link_image. This is needed to undo the DT_NEEDED hack below. - */ - if ((si->gnu_relro_start != 0) && (si->gnu_relro_len != 0)) { -- Elf32_Addr start = (si->gnu_relro_start & ~PAGE_MASK); -+ Elf_Addr start = (si->gnu_relro_start & ~PAGE_MASK); - unsigned len = (si->gnu_relro_start - start) + si->gnu_relro_len; - if (mprotect((void *) start, len, PROT_READ | PROT_WRITE) < 0) - DL_ERR("%5d %s: could not undo GNU_RELRO protections. " -@@ -1304,16 +1304,16 @@ unsigned unload_library(soinfo *si) - } - - /* TODO: don't use unsigned for addrs below. It works, but is not -- * ideal. They should probably be either uint32_t, Elf32_Addr, or unsigned -+ * ideal. They should probably be either uint32_t, Elf_Addr, or unsigned - * long. - */ --static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count) -+static int reloc_library(soinfo *si, Elf_Rel *rel, unsigned count) - { -- Elf32_Sym *symtab = si->symtab; -+ Elf_Sym *symtab = si->symtab; - const char *strtab = si->strtab; -- Elf32_Sym *s; -+ Elf_Sym *s; - unsigned base; -- Elf32_Rel *start = rel; -+ Elf_Rel *start = rel; - unsigned idx; - - for (idx = 0; idx < count; ++idx) { -@@ -1712,7 +1712,7 @@ static int nullify_closed_stdio (void) - static int link_image(soinfo *si, unsigned wr_offset) - { - unsigned *d; -- Elf32_Phdr *phdr = si->phdr; -+ Elf_Phdr *phdr = si->phdr; - int phnum = si->phnum; - - INFO("[ %5d linking %s ]\n", pid, si->name); -@@ -1795,7 +1795,7 @@ static int link_image(soinfo *si, unsign - phdr->p_vaddr, phdr->p_memsz); - goto fail; - } ++ return mr->setVideoSize(width, height); ++} ++ ++/*! ++ * \brief android_recorder_setVideoFrameRate ++ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() ++ * \param frames_per_second How many frames per second to record at (e.g. 720p is typically 30) ++ * \return negative value if an error occured ++ */ ++int android_recorder_setVideoFrameRate(MediaRecorderWrapper *mr, int frames_per_second) ++{ ++ REPORT_FUNCTION(); ++ ++ if (mr == NULL) { ++ ALOGE("mr must not be NULL"); ++ return android::BAD_VALUE; ++ } ++ ++ return mr->setVideoFrameRate(frames_per_second); ++} ++ ++/*! ++ * \brief android_recorder_setParameters sets a parameter. Even those without ++ * explicit function. ++ * For possible parameter pairs look for examples in StagefrightRecorder::setParameter() ++ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() ++ * \param parameters list of parameters. format is "parameter1=value;parameter2=value" ++ * \return negative value if an error occured ++ */ ++int android_recorder_setParameters(MediaRecorderWrapper *mr, const char *parameters) ++{ ++ REPORT_FUNCTION(); ++ ++ if (mr == NULL) { ++ ALOGE("mr must not be NULL"); ++ return android::BAD_VALUE; ++ } ++ ++ android::String8 params(parameters); ++ return mr->setParameters(params); ++} ++ ++/*! ++ * \brief android_recorder_start starts the recording. ++ * The MediaRecorder has to be in state "prepared" (call android_recorder_prepare() first) ++ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() ++ * \return negative value if an error occured ++ */ ++int android_recorder_start(MediaRecorderWrapper *mr) ++{ ++ REPORT_FUNCTION(); ++ ++ if (mr == NULL) { ++ ALOGE("mr must not be NULL"); ++ return android::BAD_VALUE; ++ } ++ ++ return mr->start(); ++} ++ ++/*! ++ * \brief android_recorder_stop Stops a running recording. ++ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() ++ * \return negative value if an error occured ++ */ ++int android_recorder_stop(MediaRecorderWrapper *mr) ++{ ++ REPORT_FUNCTION(); ++ ++ if (mr == NULL) { ++ ALOGE("mr must not be NULL"); ++ return android::BAD_VALUE; ++ } ++ ++ return mr->stop(); ++} ++ ++/*! ++ * \brief android_recorder_prepare put the MediaRecorder into state "prepare" ++ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() ++ * \return negative value if an error occured ++ */ ++int android_recorder_prepare(MediaRecorderWrapper *mr) ++{ ++ REPORT_FUNCTION(); ++ ++ if (mr == NULL) { ++ ALOGE("mr must not be NULL"); ++ return android::BAD_VALUE; ++ } ++ ++ return mr->prepare(); ++} ++ ++/*! ++ * \brief android_recorder_reset resets the MediaRecorder ++ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() ++ * \return negative value if an error occured ++ */ ++int android_recorder_reset(MediaRecorderWrapper *mr) ++{ ++ REPORT_FUNCTION(); ++ ++ if (mr == NULL) { ++ ALOGE("mr must not be NULL"); ++ return android::BAD_VALUE; ++ } ++ ++ return mr->reset(); ++} ++ ++/*! ++ * \brief android_recorder_close closes the MediaRecorder ++ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() ++ * \return negative value if an error occured ++ */ ++int android_recorder_close(MediaRecorderWrapper *mr) ++{ ++ REPORT_FUNCTION(); ++ ++ if (mr == NULL) { ++ ALOGE("mr must not be NULL"); ++ return android::BAD_VALUE; ++ } ++ ++ return mr->close(); ++} ++ ++/*! ++ * \brief android_recorder_release releases the MediaRecorder resources ++ * This deletes the MediaRecorder instance. So don't use the instance after calling this function. ++ * \param mr A MediaRecorder instance, created by calling android_media_new_recorder() ++ * \return negative value if an error occured ++ */ ++int android_recorder_release(MediaRecorderWrapper *mr) ++{ ++ REPORT_FUNCTION(); ++ ++ if (mr == NULL) { ++ ALOGE("mr must not be NULL"); ++ return android::BAD_VALUE; ++ } ++ ++ return mr->release(); ++} +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_recorder_observer.cpp +@@ -0,0 +1,127 @@ ++/* ++ * Copyright (C) 2014 Canonical Ltd ++ * ++ * 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. ++ * ++ * Authored by: Ricardo Mendoza ++ */ ++ ++// Uncomment to enabe verbose debug output ++//#define LOG_NDEBUG 0 ++ ++#undef LOG_TAG ++#define LOG_TAG "MediaRecorderObserver" ++ ++#include "media_recorder_observer.h" ++ ++#include ++#include ++ ++#include ++#include ++ ++#include ++ ++#include ++ ++#include ++#include ++#include ++ ++namespace android { ++ ++IMPLEMENT_META_INTERFACE(MediaRecorderObserver, "android.media.IMediaRecorderObserver"); ++ ++status_t BnMediaRecorderObserver::onTransact( ++ uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) ++{ ++ switch (code) { ++ case RECORDING_STARTED: { ++ CHECK_INTERFACE(IMediaRecorderObserver, data, reply); ++ recordingStarted(); ++ ++ return NO_ERROR; ++ } break; ++ case RECORDING_STOPPED: { ++ CHECK_INTERFACE(IMediaRecorderObserver, data, reply); ++ recordingStopped(); ++ ++ return NO_ERROR; ++ } break; ++ default: ++ return BBinder::onTransact(code, data, reply, flags); ++ } ++} ++ ++MediaRecorderObserver::MediaRecorderObserver() ++{ ++ defaultServiceManager()->addService( ++ String16(IMediaRecorderObserver::exported_service_name()), this); ++ ++ ProcessState::self()->startThreadPool(); ++} ++ ++void MediaRecorderObserver::recordingStarted() ++{ ++ if (media_recording_started != nullptr) ++ media_recording_started(true, cb_context); ++} ++ ++void MediaRecorderObserver::recordingStopped() ++{ ++ if (media_recording_started != nullptr) ++ media_recording_started(false, cb_context); ++} ++ ++void MediaRecorderObserver::setRecordingSignalCb(media_recording_started_cb cb, void *context) ++{ ++ if (cb != NULL) { ++ cb_context = context; ++ media_recording_started = cb; ++ } ++} ++ ++}; ++ ++// C API ++ ++struct MediaRecorderObserver { ++ MediaRecorderObserver(android::MediaRecorderObserver *observer) ++ : impl(observer) ++ { ++ } ++ ++ android::MediaRecorderObserver* impl; ++}; ++ ++MediaRecorderObserver* android_media_recorder_observer_new() ++{ ++ MediaRecorderObserver *p = new MediaRecorderObserver(new android::MediaRecorderObserver); ++ ++ if (p == NULL) { ++ ALOGE("Failed to create new MediaRecorderObserver instance."); ++ return NULL; ++ } ++ ++ return p; ++} ++ ++void android_media_recorder_observer_set_cb(MediaRecorderObserver *observer, media_recording_started_cb cb, void *context) ++{ ++ if (observer == NULL) ++ return; ++ ++ auto p = observer->impl; ++ ++ p->setRecordingSignalCb(cb, context); ++} +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/media_recorder_observer.h +@@ -0,0 +1,97 @@ ++/* ++ * Copyright (C) 2014 Canonical Ltd ++ * ++ * 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. ++ * ++ * Authored by: Ricardo Mendoza ++ */ ++ ++#ifndef MEDIA_RECORDER_OBSERVER_H_ ++#define MEDIA_RECORDER_OBSERVER_H_ ++ ++#include ++#include ++ ++#include ++ ++namespace android { ++ ++enum { ++ RECORDING_STARTED = IBinder::FIRST_CALL_TRANSACTION, ++ RECORDING_STOPPED, ++}; ++ ++class IMediaRecorderObserver: public IInterface ++{ ++public: ++ DECLARE_META_INTERFACE(MediaRecorderObserver); ++ ++ static const char* exported_service_name() { return "android.media.IMediaRecorderObserver"; } ++ ++ virtual void recordingStarted(void) = 0; ++ virtual void recordingStopped(void) = 0; ++}; ++ ++class BnMediaRecorderObserver: public BnInterface ++{ ++public: ++ virtual status_t onTransact( uint32_t code, ++ const Parcel& data, ++ Parcel* reply, ++ uint32_t flags = 0); ++}; ++ ++class BpMediaRecorderObserver: public BpInterface ++{ ++public: ++ BpMediaRecorderObserver(const sp& impl) ++ : BpInterface(impl) ++ { ++ } ++ ++ virtual void recordingStarted() ++ { ++ Parcel data, reply; ++ data.writeInterfaceToken(IMediaRecorderObserver::getInterfaceDescriptor()); ++ remote()->transact(RECORDING_STARTED, data, &reply); ++ return; ++ } ++ ++ virtual void recordingStopped() ++ { ++ Parcel data, reply; ++ data.writeInterfaceToken(IMediaRecorderObserver::getInterfaceDescriptor()); ++ remote()->transact(RECORDING_STOPPED, data, &reply); ++ return; ++ } ++}; ++ ++class MediaRecorderObserver : public BnMediaRecorderObserver ++{ ++public: ++ MediaRecorderObserver(); ++ ~MediaRecorderObserver() = default; ++ ++ virtual void recordingStarted(void); ++ virtual void recordingStopped(void); ++ ++ virtual void setRecordingSignalCb(media_recording_started_cb cb, void *context); ++ ++private: ++ media_recording_started_cb media_recording_started; ++ void *cb_context; ++}; ++ ++}; // namespace android ++ ++#endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/surface_texture_client_hybris.cpp +@@ -0,0 +1,466 @@ ++/* ++ * Copyright (C) 2013 Canonical Ltd ++ * ++ * 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. ++ * ++ * Authored by: Jim Hodapp ++ */ ++ ++// Uncomment to enable verbose debug output ++#define LOG_NDEBUG 0 ++ ++#undef LOG_TAG ++#define LOG_TAG "SurfaceTextureClientHybris" ++ ++#include ++#include "surface_texture_client_hybris_priv.h" ++#include "decoding_service_priv.h" ++ ++#include ++#include ++#include ++#include ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++#include ++#endif ++#include ++#include ++ ++#include ++#include ++ ++#define REPORT_FUNCTION() ALOGV("%s \n", __PRETTY_FUNCTION__); ++ ++using namespace android; ++ ++// ----- Begin _SurfaceTextureClientHybris API ----- // ++ ++static inline _SurfaceTextureClientHybris *get_internal_stch(SurfaceTextureClientHybris stc, const char * func) ++{ ++ if (stc == NULL) ++ { ++ ALOGE("stc must not be NULL (%s)", func); ++ return NULL; ++ } ++ ++ _SurfaceTextureClientHybris *s = static_cast<_SurfaceTextureClientHybris*>(stc); ++ assert(s->refcount >= 1); ++ ++ return s; ++} ++ ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++_SurfaceTextureClientHybris::_SurfaceTextureClientHybris() ++ : refcount(1), ++ ready(false) ++{ ++ REPORT_FUNCTION() ++} ++#endif ++ ++#if ANDROID_VERSION_MAJOR>=5 ++_SurfaceTextureClientHybris::_SurfaceTextureClientHybris(const sp &st) ++ : Surface::Surface(st, true), ++ refcount(1), ++ ready(false) ++{ ++ REPORT_FUNCTION() ++} ++#elif ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR>=4 ++_SurfaceTextureClientHybris::_SurfaceTextureClientHybris(const sp &bq) ++ : Surface::Surface(bq, true), ++ refcount(1), ++ ready(false) ++{ ++ REPORT_FUNCTION() ++} ++ ++_SurfaceTextureClientHybris::_SurfaceTextureClientHybris(const sp &st) ++ : Surface::Surface(st, true), ++ refcount(1), ++ ready(false) ++{ ++ REPORT_FUNCTION() ++} ++#endif ++ ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++_SurfaceTextureClientHybris::_SurfaceTextureClientHybris(const _SurfaceTextureClientHybris &stch) ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++ : SurfaceTextureClient::SurfaceTextureClient(), ++#else ++ : Surface::Surface(new BufferQueue(), true), ++#endif ++ refcount(stch.refcount), ++ ready(false) ++{ ++ REPORT_FUNCTION() ++} ++ ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++_SurfaceTextureClientHybris::_SurfaceTextureClientHybris(const sp &st) ++ : SurfaceTextureClient::SurfaceTextureClient(st), ++#else ++_SurfaceTextureClientHybris::_SurfaceTextureClientHybris(const sp &st) ++ : Surface::Surface(st, false), ++#endif ++ refcount(1), ++ ready(false) ++{ ++ REPORT_FUNCTION() ++} ++#endif ++ ++_SurfaceTextureClientHybris::_SurfaceTextureClientHybris(const android::sp &st, ++ bool producerIsControlledByApp) ++ : Surface::Surface(st, producerIsControlledByApp), ++ refcount(1), ++ ready(false) ++{ ++ REPORT_FUNCTION() ++} ++ ++_SurfaceTextureClientHybris::~_SurfaceTextureClientHybris() ++{ ++ REPORT_FUNCTION() ++ ++ ready = false; ++} ++ ++bool _SurfaceTextureClientHybris::isReady() const ++{ ++ return ready; ++} ++ ++void _SurfaceTextureClientHybris::setReady(bool ready) ++{ ++ this->ready = ready; ++} ++ ++int _SurfaceTextureClientHybris::dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd) ++{ ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++ return SurfaceTextureClient::dequeueBuffer(buffer, fenceFd); ++#else ++ return Surface::dequeueBuffer(buffer, fenceFd); ++#endif ++} ++ ++int _SurfaceTextureClientHybris::queueBuffer(ANativeWindowBuffer* buffer, int fenceFd) ++{ ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++ return SurfaceTextureClient::queueBuffer(buffer, fenceFd); ++#else ++ return Surface::queueBuffer(buffer, fenceFd); ++#endif ++} ++ ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++void _SurfaceTextureClientHybris::setISurfaceTexture(const sp& surface_texture) ++{ ++ SurfaceTextureClient::setISurfaceTexture(surface_texture); ++#else ++void _SurfaceTextureClientHybris::setISurfaceTexture(const sp& surface_texture) ++{ ++ // We don't need to set up the IGraphicBufferProducer as stc needs it when created ++#endif ++ ++ // Ready for rendering ++ ready = true; ++} ++ ++void _SurfaceTextureClientHybris::setHardwareRendering(bool do_hardware_rendering) ++{ ++ hardware_rendering = do_hardware_rendering; ++} ++ ++bool _SurfaceTextureClientHybris::hardwareRendering() ++{ ++ return hardware_rendering; ++} ++ ++// ----- End _SurfaceTextureClientHybris API ----- // ++ ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++static inline void set_surface(_SurfaceTextureClientHybris *stch, const sp &surface_texture) ++#else ++static inline void set_surface(_SurfaceTextureClientHybris *stch, const sp &surface_texture) ++#endif ++{ ++ REPORT_FUNCTION() ++ ++ if (stch == NULL) ++ return; ++ ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++ stch->setISurfaceTexture(surface_texture->getBufferQueue()); ++#else ++ stch->setISurfaceTexture(stch->getIGraphicBufferProducer()); ++#endif ++} ++ ++SurfaceTextureClientHybris surface_texture_client_create_by_id(unsigned int texture_id) ++{ ++ REPORT_FUNCTION() ++ ++ if (texture_id == 0) ++ { ++ ALOGE("Cannot create new SurfaceTextureClientHybris, texture id must be > 0."); ++ return NULL; ++ } ++#if ANDROID_VERSION_MAJOR>=5 ++ sp producer; ++ sp consumer; ++ BufferQueue::createBufferQueue(&producer, &consumer); ++ ++ _SurfaceTextureClientHybris *stch(new _SurfaceTextureClientHybris(producer)); ++#elif ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 ++ // Use a new native buffer allocator vs the default one, which means it'll use the proper one ++ // that will allow rendering to work with Mir ++ sp native_alloc(new NativeBufferAlloc()); ++ ++ sp buffer_queue(new BufferQueue(false, NULL, native_alloc)); ++ _SurfaceTextureClientHybris *stch(new _SurfaceTextureClientHybris); ++#else ++ sp buffer_queue(new BufferQueue(NULL)); ++ _SurfaceTextureClientHybris *stch(new _SurfaceTextureClientHybris(buffer_queue)); ++#endif ++ ++ ALOGD("stch: %p (%s)", stch, __PRETTY_FUNCTION__); ++ ++ if (stch->surface_texture != NULL) ++ stch->surface_texture.clear(); ++ ++ const bool allow_synchronous_mode = true; ++#if ANDROID_VERSION_MAJOR>=5 ++ stch->surface_texture = new GLConsumer(consumer, texture_id, GL_TEXTURE_EXTERNAL_OES, true, true); ++#elif ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++ stch->surface_texture = new SurfaceTexture(texture_id, allow_synchronous_mode, GL_TEXTURE_EXTERNAL_OES, true, buffer_queue); ++ set_surface(stch, stch->surface_texture); ++#else ++ stch->surface_texture = new GLConsumer(buffer_queue, texture_id, GL_TEXTURE_EXTERNAL_OES, true, true); ++#endif ++ set_surface(stch, stch->surface_texture); ++ ++ return stch; ++} ++ ++SurfaceTextureClientHybris surface_texture_client_create_by_igbp(IGBPWrapperHybris wrapper) ++{ ++ if (wrapper == NULL) ++ { ++ ALOGE("Cannot create new SurfaceTextureClientHybris, wrapper must not be NULL."); ++ return NULL; ++ } ++ ++ IGBPWrapper *igbp = static_cast(wrapper); ++ // The producer should be the same BufferQueue as what the client is using but over Binder ++ // Allow the app to control the producer side BufferQueue ++ _SurfaceTextureClientHybris *stch(new _SurfaceTextureClientHybris(igbp->producer, true)); ++ // Ready for rendering ++ stch->setReady(); ++ return stch; ++} ++ ++GLConsumerWrapperHybris gl_consumer_create_by_id_with_igbc(unsigned int texture_id, IGBCWrapperHybris wrapper) ++{ ++ REPORT_FUNCTION() ++ ++ if (texture_id == 0) ++ { ++ ALOGE("Cannot create new SurfaceTextureClientHybris, texture id must be > 0."); ++ return NULL; ++ } ++ ++ if (wrapper == NULL) ++ { ++ ALOGE("Cannot create new GLConsumerHybris, wrapper must not be NULL."); ++ return NULL; ++ } ++ ++ IGBCWrapper *igbc = static_cast(wrapper); ++ // Use a fence guard and consumer is controlled by app: ++ sp<_GLConsumerHybris> gl_consumer = new _GLConsumerHybris(igbc->consumer, texture_id, GL_TEXTURE_EXTERNAL_OES, true, true); ++ GLConsumerWrapper *glc_wrapper = new GLConsumerWrapper(gl_consumer); ++ ++ return glc_wrapper; ++} ++ ++int gl_consumer_set_frame_available_cb(GLConsumerWrapperHybris wrapper, FrameAvailableCbHybris cb, void *context) ++{ ++ REPORT_FUNCTION() ++ ++ if (wrapper == NULL) ++ { ++ ALOGE("Cannot set GLConsumerWrapperHybris, wrapper must not be NULL"); ++ return BAD_VALUE; ++ } ++ if (cb == NULL) ++ { ++ ALOGE("Cannot set FrameAvailableCbHybris, cb must not be NULL"); ++ return BAD_VALUE; ++ } ++ ++ GLConsumerWrapper *glc_wrapper = static_cast(wrapper); ++ sp<_GLConsumerHybris> glc_hybris = static_cast<_GLConsumerHybris*>(glc_wrapper->consumer.get()); ++ glc_hybris->createFrameAvailableListener(cb, wrapper, context); ++ ++ return OK; ++} ++ ++void gl_consumer_get_transformation_matrix(GLConsumerWrapperHybris wrapper, float *matrix) ++{ ++ REPORT_FUNCTION() ++ ++ if (wrapper == NULL) ++ { ++ ALOGE("Cannot set GLConsumerWrapperHybris, wrapper must not be NULL"); ++ return; ++ } ++ ++ GLConsumerWrapper *glc_wrapper = static_cast(wrapper); ++ sp<_GLConsumerHybris> glc_hybris = static_cast<_GLConsumerHybris*>(glc_wrapper->consumer.get()); ++ glc_hybris->getTransformMatrix(static_cast(matrix)); ++} ++ ++void gl_consumer_update_texture(GLConsumerWrapperHybris wrapper) ++{ ++ REPORT_FUNCTION() ++ ++ if (wrapper == NULL) ++ { ++ ALOGE("Cannot set GLConsumerWrapperHybris, wrapper must not be NULL"); ++ return; ++ } ++ ++ GLConsumerWrapper *glc_wrapper = static_cast(wrapper); ++ sp<_GLConsumerHybris> glc_hybris = static_cast<_GLConsumerHybris*>(glc_wrapper->consumer.get()); ++ glc_hybris->updateTexImage(); ++} ++ ++uint8_t surface_texture_client_is_ready_for_rendering(SurfaceTextureClientHybris stc) ++{ ++ REPORT_FUNCTION() ++ ++ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); ++ if (s == NULL) ++ return false; ++ ++ return static_cast(s->isReady()); ++} ++ ++uint8_t surface_texture_client_hardware_rendering(SurfaceTextureClientHybris stc) ++{ ++ REPORT_FUNCTION() ++ ++ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); ++ if (s == NULL) ++ return false; ++ ++ return s->hardwareRendering(); ++} ++ ++void surface_texture_client_set_hardware_rendering(SurfaceTextureClientHybris stc, uint8_t hardware_rendering) ++{ ++ REPORT_FUNCTION() ++ ++ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); ++ if (s == NULL) ++ return; ++ ++ s->setHardwareRendering(static_cast(hardware_rendering)); ++} ++ ++void surface_texture_client_get_transformation_matrix(SurfaceTextureClientHybris stc, float *matrix) ++{ ++ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); ++ if (s == NULL) ++ return; ++ ++ s->surface_texture->getTransformMatrix(static_cast(matrix)); ++} ++ ++void surface_texture_client_update_texture(SurfaceTextureClientHybris stc) ++{ ++ REPORT_FUNCTION() ++ ++ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); ++ if (s == NULL) ++ return; ++ ++ s->surface_texture->updateTexImage(); ++} ++ ++void surface_texture_client_destroy(SurfaceTextureClientHybris stc) ++{ ++ REPORT_FUNCTION() ++ ++ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); ++ if (s == NULL) ++ { ++ ALOGE("s == NULL, cannot destroy SurfaceTextureClientHybris instance"); ++ return; ++ } ++ ++ s->refcount = 0; ++ ++ delete s; ++} ++ ++void surface_texture_client_ref(SurfaceTextureClientHybris stc) ++{ ++ REPORT_FUNCTION() ++ ++ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); ++ if (s == NULL) ++ return; ++ ++ s->refcount++; ++} ++ ++void surface_texture_client_unref(SurfaceTextureClientHybris stc) ++{ ++ REPORT_FUNCTION() ++ ++ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); ++ if (s == NULL) ++ { ++ ALOGE("s == NULL, cannot unref SurfaceTextureClientHybris instance"); ++ return; ++ } ++ ++ if (s->refcount > 1) ++ s->refcount--; ++ else ++ surface_texture_client_destroy (stc); ++} ++ ++void surface_texture_client_set_surface_texture(SurfaceTextureClientHybris stc, EGLNativeWindowType native_window) ++{ ++ _SurfaceTextureClientHybris *s = get_internal_stch(stc, __PRETTY_FUNCTION__); ++ if (s == NULL) ++ return; ++ ++ if (native_window == NULL) ++ { ++ ALOGE("native_window must not be NULL"); ++ return; ++ } ++ ++ sp surface = static_cast(native_window); ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++ s->setISurfaceTexture(surface->getSurfaceTexture()); ++#else ++ s->setISurfaceTexture(surface->getIGraphicBufferProducer()); ++#endif ++} +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/compat/media/surface_texture_client_hybris_priv.h +@@ -0,0 +1,138 @@ ++/* ++ * Copyright (C) 2013 Canonical Ltd ++ * ++ * 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. ++ * ++ * Authored by: Jim Hodapp ++ */ ++ ++#ifndef SURFACE_TEXTURE_CLIENT_HYBRIS_PRIV_H ++#define SURFACE_TEXTURE_CLIENT_HYBRIS_PRIV_H ++ ++#include "hybris/media/surface_texture_client_hybris.h" ++ ++#include ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++#include ++#else ++#include ++#endif ++ ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++struct _SurfaceTextureClientHybris : public android::SurfaceTextureClient ++#else ++struct _SurfaceTextureClientHybris : public android::Surface ++#endif ++{ ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++ _SurfaceTextureClientHybris(); ++#endif ++ _SurfaceTextureClientHybris(const _SurfaceTextureClientHybris &stch); ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++ _SurfaceTextureClientHybris(const android::sp &st); ++#else ++ _SurfaceTextureClientHybris(const android::sp &st); ++ _SurfaceTextureClientHybris(const android::sp &st, ++ bool producerIsControlledByApp); ++ _SurfaceTextureClientHybris(const android::sp &bq); ++#endif ++ ~_SurfaceTextureClientHybris(); ++ ++ /** Has a texture id or EGLNativeWindowType been passed in, meaning rendering will function? **/ ++ bool isReady() const; ++ void setReady(bool ready = true); ++ ++public: ++ int dequeueBuffer(ANativeWindowBuffer** buffer, int* fenceFd); ++ int queueBuffer(ANativeWindowBuffer* buffer, int fenceFd); ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++ void setISurfaceTexture(const android::sp& surface_texture); ++#else ++ void setISurfaceTexture(const android::sp& surface_texture); ++#endif ++ void setHardwareRendering(bool do_hardware_rendering); ++ bool hardwareRendering(); ++ ++ unsigned int refcount; ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=2 ++ android::sp surface_texture; ++#else ++ android::sp surface_texture; ++#endif ++ ++private: ++ bool ready; ++ bool hardware_rendering; ++}; ++ ++namespace android { ++ ++class _GLConsumerHybris : public GLConsumer ++{ ++ class FrameAvailableListener : public GLConsumer::FrameAvailableListener ++ { ++ public: ++ FrameAvailableListener() ++ : frame_available_cb(NULL), ++ glc_wrapper(NULL), ++ context(NULL) ++ { ++ } ++ ++#if ANDROID_VERSION_MAJOR==5 && ANDROID_VERSION_MINOR>=1 || ANDROID_VERSION_MAJOR>=6 ++ virtual void onFrameAvailable(const android::BufferItem& item) ++#else ++ virtual void onFrameAvailable() ++#endif ++ { ++ if (frame_available_cb != NULL) ++ frame_available_cb(glc_wrapper, context); ++ else ++ ALOGE("Failed to call, frame_available_cb is NULL"); ++ } ++ ++ void setFrameAvailableCbHybris(FrameAvailableCbHybris cb, GLConsumerWrapperHybris wrapper, void *context) ++ { ++ frame_available_cb = cb; ++ glc_wrapper = wrapper; ++ this->context = context; ++ } ++ ++ private: ++ FrameAvailableCbHybris frame_available_cb; ++ GLConsumerWrapperHybris glc_wrapper; ++ void *context; ++ }; ++ ++public: ++ _GLConsumerHybris(const sp& bq, ++ uint32_t tex, uint32_t textureTarget = TEXTURE_EXTERNAL, ++ bool useFenceSync = true, bool isControlledByApp = false) ++ : GLConsumer(bq, tex, textureTarget, useFenceSync, isControlledByApp) ++ { ++ } ++ ++ void createFrameAvailableListener(FrameAvailableCbHybris cb, GLConsumerWrapperHybris wrapper, void *context) ++ { ++ frame_available_listener = new _GLConsumerHybris::FrameAvailableListener(); ++ frame_available_listener->setFrameAvailableCbHybris(cb, wrapper, context); ++ setFrameAvailableListener(frame_available_listener); ++ } ++ ++private: ++ sp<_GLConsumerHybris::FrameAvailableListener> frame_available_listener; ++}; ++ ++}; // namespace android ++ ++#endif +--- libhybris-0.1.0+git20151016+6d424c9.orig/compat/surface_flinger/Android.mk ++++ libhybris-0.1.0+git20151016+6d424c9/compat/surface_flinger/Android.mk +@@ -1,5 +1,6 @@ + LOCAL_PATH := $(call my-dir) + include $(CLEAR_VARS) ++include $(LOCAL_PATH)/../Android.common.mk + + HYBRIS_PATH := $(LOCAL_PATH)/../../hybris + +@@ -8,6 +9,9 @@ LOCAL_SRC_FILES:= \ + + LOCAL_MODULE:= libsf_compat_layer + LOCAL_MODULE_TAGS := optional ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif + + LOCAL_C_INCLUDES := \ + $(HYBRIS_PATH)/include +@@ -30,6 +34,9 @@ LOCAL_SRC_FILES:= \ + + LOCAL_MODULE:= direct_sf_test + LOCAL_MODULE_TAGS := optional ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif + + LOCAL_C_INCLUDES := \ + $(HYBRIS_PATH)/include +--- libhybris-0.1.0+git20151016+6d424c9.orig/compat/surface_flinger/surface_flinger_compatibility_layer.cpp ++++ libhybris-0.1.0+git20151016+6d424c9/compat/surface_flinger/surface_flinger_compatibility_layer.cpp +@@ -28,6 +28,9 @@ + #include + #include + #include ++#if ANDROID_VERSION_MAJOR>=5 ++ #include ++#endif + + #include + #include +@@ -80,7 +83,11 @@ void sf_blank(size_t display_id) + return; + } + ++#if ANDROID_VERSION_MAJOR<=4 + android::SurfaceComposerClient::blankDisplay(display); ++#elif ANDROID_VERSION_MAJOR>=5 ++ android::SurfaceComposerClient::setDisplayPowerMode(display, HWC_POWER_MODE_OFF); ++#endif + } + + void sf_unblank(size_t display_id) +@@ -98,7 +105,11 @@ void sf_unblank(size_t display_id) + return; + } + ++#if ANDROID_VERSION_MAJOR<=4 + android::SurfaceComposerClient::unblankDisplay(display); ++#elif ANDROID_VERSION_MAJOR>=5 ++ android::SurfaceComposerClient::setDisplayPowerMode(display, HWC_POWER_MODE_NORMAL); ++#endif + } + + size_t sf_get_display_width(size_t display_id) +--- libhybris-0.1.0+git20151016+6d424c9.orig/compat/ui/Android.mk ++++ libhybris-0.1.0+git20151016+6d424c9/compat/ui/Android.mk +@@ -1,5 +1,6 @@ + LOCAL_PATH:= $(call my-dir) + include $(CLEAR_VARS) ++include $(LOCAL_PATH)/../Android.common.mk + + HYBRIS_PATH := $(LOCAL_PATH)/../../hybris + +@@ -8,6 +9,9 @@ LOCAL_SRC_FILES:= \ + + LOCAL_MODULE:= libui_compat_layer + LOCAL_MODULE_TAGS := optional ++ifneq ($(strip $(BOARD_HAS_64_BIT_MEDIA_SERVICE)),true) ++ LOCAL_32_BIT_ONLY := true ++endif + + LOCAL_C_INCLUDES := \ + $(HYBRIS_PATH)/include \ +--- libhybris-0.1.0+git20151016+6d424c9.orig/compat/ui/ui_compatibility_layer.cpp ++++ libhybris-0.1.0+git20151016+6d424c9/compat/ui/ui_compatibility_layer.cpp +@@ -126,6 +126,7 @@ void* graphic_buffer_get_native_buffer(s + return buffer->self->getNativeBuffer(); + } + ++#if ANDROID_VERSION_MAJOR==4 && ANDROID_VERSION_MINOR<=3 + void graphic_buffer_set_index(struct graphic_buffer *buffer, int index) + { + return buffer->self->setIndex(index); +@@ -135,6 +136,7 @@ int graphic_buffer_get_index(struct grap + { + return buffer->self->getIndex(); + } ++#endif + + int graphic_buffer_init_check(struct graphic_buffer *buffer) + { +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/Makefile.am ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/Makefile.am +@@ -6,7 +6,7 @@ endif + if HAS_ANDROID_5_0_0 + SUBDIRS += libsync + endif +-SUBDIRS += egl glesv1 glesv2 ui sf input camera vibrator ++SUBDIRS += egl glesv1 glesv2 ui sf input camera vibrator media wifi + + if HAS_LIBNFC_NXP_HEADERS + SUBDIRS += libnfc_nxp libnfc_ndef_nxp +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/README ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/README +@@ -0,0 +1,12 @@ ++libhybris ++========= ++ ++Hybris is a solution that commits hybris, by allowing us to use bionic ++-based HW adaptations in glibc systems. ++ ++ ++Supported Architectures ++----------------------- ++ ++Libhybris currently only supports 32 bit ARM and x86 systems. 64 bit ++system are not yet supported. +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/camera/camera.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/camera/camera.c +@@ -1,5 +1,5 @@ + /* +- * Copyright (C) 2013 Canonical Ltd ++ * Copyright (C) 2013 - 2014 Canonical Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. +@@ -26,13 +26,16 @@ + #include + #include + +-#define COMPAT_LIBRARY_PATH "/system/lib/libcamera_compat_layer.so" ++#define COMPAT_LIBRARY_PATH "libcamera_compat_layer.so" + + HYBRIS_LIBRARY_INITIALIZE(camera, COMPAT_LIBRARY_PATH); + + HYBRIS_IMPLEMENT_FUNCTION0(camera, int, android_camera_get_number_of_devices); ++HYBRIS_IMPLEMENT_FUNCTION3(camera, int, android_camera_get_device_info, int32_t, int*, int*); + HYBRIS_IMPLEMENT_FUNCTION2(camera, struct CameraControl*, android_camera_connect_to, + CameraType, struct CameraControlListener*); ++HYBRIS_IMPLEMENT_FUNCTION2(camera, struct CameraControl*, android_camera_connect_by_id, ++ int32_t, struct CameraControlListener*); + HYBRIS_IMPLEMENT_VOID_FUNCTION1(camera, android_camera_disconnect, + struct CameraControl*); + HYBRIS_IMPLEMENT_FUNCTION1(camera, int, android_camera_lock, struct CameraControl*); +@@ -52,8 +55,12 @@ HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, + struct CameraControl*, SceneMode); + HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, android_camera_set_auto_focus_mode, + struct CameraControl*, AutoFocusMode); ++HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, android_camera_set_preview_format, ++ struct CameraControl*, CameraPixelFormat); + HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_set_picture_size, + struct CameraControl*, int, int); ++HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_set_thumbnail_size, ++ struct CameraControl*, int, int); + HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_set_preview_size, + struct CameraControl*, int, int); + HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, android_camera_set_display_orientation, +@@ -66,12 +73,20 @@ HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, + struct CameraControl*, FocusRegion*); + HYBRIS_IMPLEMENT_VOID_FUNCTION1(camera, android_camera_reset_focus_region, + struct CameraControl*); ++HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, android_camera_set_metering_region, ++ struct CameraControl*, MeteringRegion*); ++HYBRIS_IMPLEMENT_VOID_FUNCTION1(camera, android_camera_reset_metering_region, ++ struct CameraControl*); + HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, android_camera_set_preview_fps, + struct CameraControl*, int); + HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, android_camera_set_rotation, + struct CameraControl*, int); ++HYBRIS_IMPLEMENT_VOID_FUNCTION6(camera, android_camera_set_location, ++ struct CameraControl*, const float*, const float*, const float*, int, const char*); + HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_set_video_size, + struct CameraControl*, int, int); ++HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, android_camera_set_jpeg_quality, ++ struct CameraControl*, int); + + // Getters + HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, android_camera_get_effect_mode, +@@ -88,6 +103,8 @@ HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, + struct CameraControl*, int*); + HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_get_picture_size, + struct CameraControl*, int*, int*); ++HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_get_thumbnail_size, ++ struct CameraControl*, int*, int*); + HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_get_preview_size, + struct CameraControl*, int*, int*); + HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_get_preview_fps_range, +@@ -98,14 +115,22 @@ HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, + struct CameraControl*, float*); + HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_get_video_size, + struct CameraControl*, int*, int*); ++HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, android_camera_get_jpeg_quality, ++ struct CameraControl*, int*); + + // Enumerators + HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_enumerate_supported_picture_sizes, + struct CameraControl*, size_callback, void*); ++HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_enumerate_supported_thumbnail_sizes, ++ struct CameraControl*, size_callback, void*); + HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_enumerate_supported_preview_sizes, + struct CameraControl*, size_callback, void*); + HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_enumerate_supported_video_sizes, + struct CameraControl*, size_callback, void*); ++HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_enumerate_supported_scene_modes, ++ struct CameraControl*, scene_mode_callback, void*); ++HYBRIS_IMPLEMENT_VOID_FUNCTION3(camera, android_camera_enumerate_supported_flash_modes, ++ struct CameraControl*, flash_mode_callback, void*); + + HYBRIS_IMPLEMENT_VOID_FUNCTION1(camera, android_camera_update_preview_texture, struct CameraControl*); + +@@ -118,3 +143,6 @@ HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, + HYBRIS_IMPLEMENT_VOID_FUNCTION2(camera, android_camera_set_zoom, struct CameraControl*, int32_t); + HYBRIS_IMPLEMENT_VOID_FUNCTION1(camera, android_camera_stop_zoom, struct CameraControl*); + HYBRIS_IMPLEMENT_VOID_FUNCTION1(camera, android_camera_take_snapshot, struct CameraControl*); ++ ++HYBRIS_IMPLEMENT_FUNCTION2(camera, int, android_camera_set_preview_callback_mode, ++ struct CameraControl*, PreviewCallbackMode); +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/Makefile.am ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/Makefile.am +@@ -1,44 +1,51 @@ + lib_LTLIBRARIES = \ + libhybris-common.la + +-# JB linker works fine for ICS +-if HAS_ANDROID_4_0_0 +-SUBDIRS = jb +-libhybris_common_la_LIBADD= jb/libandroid-linker.la +-else +-if HAS_ANDROID_5_0_0 +-SUBDIRS = jb +-libhybris_common_la_LIBADD= jb/libandroid-linker.la +-else +-if HAS_ANDROID_2_3_0 +-SUBDIRS = gingerbread +-libhybris_common_la_LIBADD= gingerbread/libandroid-linker.la +-else +-$(error No Android Version is defined) +-endif ++SUBDIRS = ++ ++if !WANT_ARCH_ARM64 ++SUBDIRS += jb + endif ++ ++if WANT_EXPERIMENTAL ++SUBDIRS += mm + endif + + libhybris_common_la_SOURCES = \ + hooks.c \ + hooks_shm.c \ + strlcpy.c \ +- dlfcn.c \ ++ strlcat.c \ + logging.c \ + sysconf.c +-libhybris_common_la_CFLAGS = \ ++libhybris_common_la_CPPFLAGS = \ + -I$(top_srcdir)/include \ + $(ANDROID_HEADERS_CFLAGS) \ +- -I$(top_srcdir)/common ++ -I$(top_srcdir)/common \ ++ -DLINKER_PLUGIN_DIR=\"$(libdir)/libhybris/linker\" + if WANT_TRACE +-libhybris_common_la_CFLAGS += -DDEBUG ++libhybris_common_la_CPPFLAGS += -DDEBUG + endif + if WANT_DEBUG +-libhybris_common_la_CFLAGS += -ggdb -O0 ++libhybris_common_la_CPPFLAGS += -ggdb -O0 ++endif ++if WANT_MALI_QUIRKS ++libhybris_common_la_CPPFLAGS += -DMALI_QUIRKS ++endif ++if WANT_UBUNTU_LINKER_OVERRIDES ++libhybris_common_la_CPPFLAGS += -DUBUNTU_LINKER_OVERRIDES ++endif ++if !WANT_ARCH_ARM64 ++libhybris_common_la_CPPFLAGS += -DWANT_LINKER_JB ++endif ++if WANT_EXPERIMENTAL ++libhybris_common_la_CPPFLAGS += -DWANT_LINKER_MM + endif + libhybris_common_la_LDFLAGS = \ + -ldl \ + -lrt \ + -pthread \ ++ -lc \ ++ -lstdc++ \ + $(top_builddir)/properties/libandroid-properties.la \ + -version-info "$(LT_CURRENT)":"$(LT_REVISION)":"$(LT_AGE)" +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/hooks.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/hooks.c +@@ -27,6 +27,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -39,22 +40,47 @@ + #include + #include + #include ++#include ++#include ++#include ++#include ++#include ++#include + + #include + #include + #include + ++#include ++#include ++#include ++ + #include + #include + #include + #include + #include + #include ++#include ++ ++#include ++#include ++#include + + #include ++#include + + static locale_t hybris_locale; + static int locale_inited = 0; ++static hybris_hook_cb hook_callback = NULL; ++ ++static void (*_android_linker_init)(int sdk_version, void* (*get_hooked_symbol)(const char*, const char*)) = NULL; ++static void* (*_android_dlopen)(const char *filename, int flags) = NULL; ++static void* (*_android_dlsym)(void *handle, const char *symbol) = NULL; ++static void* (*_android_dladdr)(void *addr, Dl_info *info) = NULL; ++static int (*_android_dlclose)(void *handle) = NULL; ++static const char* (*_android_dlerror)(void) = NULL; ++ + /* TODO: + * - Check if the int arguments at attr_set/get match the ones at Android + * - Check how to deal with memory leaks (specially with static initializers) +@@ -68,8 +94,12 @@ static int locale_inited = 0; + + #define ANDROID_MUTEX_SHARED_MASK 0x2000 + #define ANDROID_COND_SHARED_MASK 0x0001 ++#define ANDROID_COND_COUNTER_INCREMENT 0x0002 ++#define ANDROID_COND_COUNTER_MASK (~ANDROID_COND_SHARED_MASK) + #define ANDROID_RWLOCKATTR_SHARED_MASK 0x0010 + ++#define ANDROID_COND_IS_SHARED(c) (((c)->value & ANDROID_COND_SHARED_MASK) != 0) ++ + /* For the static initializer types */ + #define ANDROID_PTHREAD_MUTEX_INITIALIZER 0 + #define ANDROID_PTHREAD_RECURSIVE_MUTEX_INITIALIZER 0x4000 +@@ -77,10 +107,21 @@ static int locale_inited = 0; + #define ANDROID_PTHREAD_COND_INITIALIZER 0 + #define ANDROID_PTHREAD_RWLOCK_INITIALIZER 0 + ++#define MALI_HIST_DUMP_THREAD_NAME "mali-hist-dump" ++ + /* Debug */ + #include "logging.h" + #define LOGD(message, ...) HYBRIS_DEBUG_LOG(HOOKS, message, ##__VA_ARGS__) + ++#ifdef DEBUG ++#define TRACE_HOOK(message, ...) \ ++ if (hybris_should_trace(NULL, NULL)) { \ ++ HYBRIS_DEBUG_LOG(HOOKS, message, ##__VA_ARGS__); \ ++ } ++#else ++#define TRACE_HOOK(message, ...) ++#endif ++ + /* we have a value p: + * - if p <= ANDROID_TOP_ADDR_VALUE_MUTEX then it is an android mutex, not one we processed + * - if p > VMALLOC_END, then the pointer is not a result of malloc ==> it is an shm offset +@@ -91,6 +132,11 @@ struct _hook { + void *func; + }; + ++/* pthread cond struct as done in Android */ ++typedef struct { ++ int volatile value; ++} android_cond_t; ++ + /* Helpers */ + static int hybris_check_android_shared_mutex(unsigned int mutex_addr) + { +@@ -113,9 +159,59 @@ static int hybris_check_android_shared_c + (cond_addr & ANDROID_COND_SHARED_MASK)) + return 1; + ++ /* In case android is setting up cond_addr with a negative value, ++ * used for error control */ ++ if (cond_addr > HYBRIS_SHM_MASK_TOP) ++ return 1; ++ ++ return 0; ++} ++ ++/* Based on Android's Bionic pthread implementation. ++ * This is just needed when we have a shared cond with Android */ ++static int __android_pthread_cond_pulse(android_cond_t *cond, int counter) ++{ ++ long flags; ++ int fret; ++ ++ if (cond == NULL) ++ return EINVAL; ++ ++ flags = (cond->value & ~ANDROID_COND_COUNTER_MASK); ++ for (;;) { ++ long oldval = cond->value; ++ long newval = 0; ++ /* In our case all we need to do is make sure the negative value ++ * is under our range, which is the last 0xF from SHM_MASK */ ++ if (oldval < -12) ++ newval = ((oldval + ANDROID_COND_COUNTER_INCREMENT) & ++ ANDROID_COND_COUNTER_MASK) | flags; ++ else ++ newval = ((oldval - ANDROID_COND_COUNTER_INCREMENT) & ++ ANDROID_COND_COUNTER_MASK) | flags; ++ if (__sync_bool_compare_and_swap(&cond->value, oldval, newval)) ++ break; ++ } ++ ++ int pshared = cond->value & ANDROID_COND_SHARED_MASK; ++ fret = syscall(SYS_futex , &cond->value, ++ pshared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE, counter, ++ NULL, NULL, NULL); ++ LOGD("futex based pthread_cond_*, value %d, counter %d, ret %d", ++ cond->value, counter, fret); + return 0; + } + ++int android_pthread_cond_broadcast(android_cond_t *cond) ++{ ++ return __android_pthread_cond_pulse(cond, INT_MAX); ++} ++ ++int android_pthread_cond_signal(android_cond_t *cond) ++{ ++ return __android_pthread_cond_pulse(cond, 1); ++} ++ + static void hybris_set_mutex_attr(unsigned int android_value, pthread_mutexattr_t *attr) + { + /* Init already sets as PTHREAD_MUTEX_NORMAL */ +@@ -159,25 +255,49 @@ static pthread_rwlock_t* hybris_alloc_in + * utils, such as malloc, memcpy + * + * Useful to handle hacks such as the one applied for Nvidia, and to +- * avoid crashes. ++ * avoid crashes. Also we need to hook all memory allocation related ++ * ones to make sure all are using the same allocator implementation. + * + * */ + +-static void *my_malloc(size_t size) ++static void *_hybris_hook_malloc(size_t size) ++{ ++ TRACE_HOOK("size %u", size); ++ ++ void *res = malloc(size); ++ ++ TRACE_HOOK("res %p", res); ++ ++ return res; ++} ++ ++static size_t _hybris_hook_malloc_usable_size (void *ptr) + { +- return malloc(size); ++ TRACE_HOOK("ptr %p", ptr); ++ ++ return malloc_usable_size(ptr); + } + +-static void *my_memcpy(void *dst, const void *src, size_t len) ++static void *_hybris_hook_memcpy(void *dst, const void *src, size_t len) + { ++ TRACE_HOOK("dst %p src %p len %u", dst, src, len); ++ + if (src == NULL || dst == NULL) + return NULL; + + return memcpy(dst, src, len); + } + +-static size_t my_strlen(const char *s) ++static int _hybris_hook_memcmp(const void *s1, const void *s2, size_t n) ++{ ++ TRACE_HOOK("s1 %p '%s' s2 %p '%s' n %u", s1, (char*) s1, s2, (char*) s2, n); ++ ++ return memcmp(s1, s2, n); ++} ++ ++static size_t _hybris_hook_strlen(const char *s) + { ++ TRACE_HOOK("s '%s'", s); + + if (s == NULL) + return -1; +@@ -185,9 +305,11 @@ static size_t my_strlen(const char *s) + return strlen(s); + } + +-static pid_t my_gettid( void ) ++static pid_t _hybris_hook_gettid(void) + { +- return syscall( __NR_gettid ); ++ TRACE_HOOK(""); ++ ++ return syscall(__NR_gettid); + } + + /* +@@ -198,17 +320,43 @@ static pid_t my_gettid( void ) + * + * */ + +-static int my_pthread_create(pthread_t *thread, const pthread_attr_t *__attr, ++static int _hybris_hook_pthread_create(pthread_t *thread, const pthread_attr_t *__attr, + void *(*start_routine)(void*), void *arg) + { + pthread_attr_t *realattr = NULL; + ++ TRACE_HOOK("thread %p attr %p", thread, __attr); ++ + if (__attr != NULL) + realattr = (pthread_attr_t *) *(unsigned int *) __attr; + + return pthread_create(thread, realattr, start_routine, arg); + } + ++static int _hybris_hook_pthread_kill(pthread_t thread, int sig) ++{ ++ TRACE_HOOK("thread %llu sig %d", (unsigned long long) thread, sig); ++ ++ if (thread == 0) ++ return ESRCH; ++ ++ return pthread_kill(thread, sig); ++} ++ ++static int _hybris_hook_pthread_setspecific(pthread_key_t key, const void *ptr) ++{ ++ TRACE_HOOK("key %d ptr %d", key, ptr); ++ ++ return pthread_setspecific(key, ptr); ++} ++ ++static void* _hybris_hook_pthread_getspecific(pthread_key_t key) ++{ ++ TRACE_HOOK("key %d", key); ++ ++ return pthread_getspecific(key); ++} ++ + /* + * pthread_attr_* functions + * +@@ -217,124 +365,177 @@ static int my_pthread_create(pthread_t * + * + * */ + +-static int my_pthread_attr_init(pthread_attr_t *__attr) ++static int _hybris_hook_pthread_attr_init(pthread_attr_t *__attr) + { + pthread_attr_t *realattr; + ++ TRACE_HOOK("attr %p", __attr); ++ + realattr = malloc(sizeof(pthread_attr_t)); + *((unsigned int *)__attr) = (unsigned int) realattr; + + return pthread_attr_init(realattr); + } + +-static int my_pthread_attr_destroy(pthread_attr_t *__attr) ++static int _hybris_hook_pthread_attr_destroy(pthread_attr_t *__attr) + { + int ret; + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; + ++ TRACE_HOOK("attr %p", __attr); ++ + ret = pthread_attr_destroy(realattr); +- /* We need to release the memory allocated at my_pthread_attr_init ++ /* We need to release the memory allocated at _hybris_hook_pthread_attr_init + * Possible side effects if destroy is called without our init */ + free(realattr); + + return ret; + } + +-static int my_pthread_attr_setdetachstate(pthread_attr_t *__attr, int state) ++static int _hybris_hook_pthread_attr_setdetachstate(pthread_attr_t *__attr, int state) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; ++ ++ TRACE_HOOK("attr %p state %d", __attr, state); ++ + return pthread_attr_setdetachstate(realattr, state); + } + +-static int my_pthread_attr_getdetachstate(pthread_attr_t const *__attr, int *state) ++static int _hybris_hook_pthread_attr_getdetachstate(pthread_attr_t const *__attr, int *state) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; ++ ++ TRACE_HOOK("attr %p state %p", __attr, state); ++ + return pthread_attr_getdetachstate(realattr, state); + } + +-static int my_pthread_attr_setschedpolicy(pthread_attr_t *__attr, int policy) ++static int _hybris_hook_pthread_attr_setschedpolicy(pthread_attr_t *__attr, int policy) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; ++ ++ TRACE_HOOK("attr %p policy %d", __attr, policy); ++ + return pthread_attr_setschedpolicy(realattr, policy); + } + +-static int my_pthread_attr_getschedpolicy(pthread_attr_t const *__attr, int *policy) ++static int _hybris_hook_pthread_attr_getschedpolicy(pthread_attr_t const *__attr, int *policy) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; ++ ++ TRACE_HOOK("attr %p policy %p", __attr, policy); ++ + return pthread_attr_getschedpolicy(realattr, policy); + } + +-static int my_pthread_attr_setschedparam(pthread_attr_t *__attr, struct sched_param const *param) ++static int _hybris_hook_pthread_attr_setschedparam(pthread_attr_t *__attr, struct sched_param const *param) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; ++ ++ TRACE_HOOK("attr %p param %p", __attr, param); ++ + return pthread_attr_setschedparam(realattr, param); + } + +-static int my_pthread_attr_getschedparam(pthread_attr_t const *__attr, struct sched_param *param) ++static int _hybris_hook_pthread_attr_getschedparam(pthread_attr_t const *__attr, struct sched_param *param) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; ++ ++ TRACE_HOOK("attr %p param %p", __attr, param); ++ + return pthread_attr_getschedparam(realattr, param); + } + +-static int my_pthread_attr_setstacksize(pthread_attr_t *__attr, size_t stack_size) ++static int _hybris_hook_pthread_attr_setstacksize(pthread_attr_t *__attr, size_t stack_size) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; ++ ++ TRACE_HOOK("attr %p stack size %u", __attr, stack_size); ++ + return pthread_attr_setstacksize(realattr, stack_size); + } + +-static int my_pthread_attr_getstacksize(pthread_attr_t const *__attr, size_t *stack_size) ++static int _hybris_hook_pthread_attr_getstacksize(pthread_attr_t const *__attr, size_t *stack_size) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; ++ ++ TRACE_HOOK("attr %p stack size %p", __attr, stack_size); ++ + return pthread_attr_getstacksize(realattr, stack_size); + } + +-static int my_pthread_attr_setstackaddr(pthread_attr_t *__attr, void *stack_addr) ++static int _hybris_hook_pthread_attr_setstackaddr(pthread_attr_t *__attr, void *stack_addr) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; ++ ++ TRACE_HOOK("attr %p stack addr %p", __attr, stack_addr); ++ + return pthread_attr_setstackaddr(realattr, stack_addr); + } + +-static int my_pthread_attr_getstackaddr(pthread_attr_t const *__attr, void **stack_addr) ++static int _hybris_hook_pthread_attr_getstackaddr(pthread_attr_t const *__attr, void **stack_addr) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; ++ ++ TRACE_HOOK("attr %p stack addr %p", __attr, stack_addr); ++ + return pthread_attr_getstackaddr(realattr, stack_addr); + } + +-static int my_pthread_attr_setstack(pthread_attr_t *__attr, void *stack_base, size_t stack_size) ++static int _hybris_hook_pthread_attr_setstack(pthread_attr_t *__attr, void *stack_base, size_t stack_size) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; ++ ++ TRACE_HOOK("attr %p stack base %p stack size %u", __attr, ++ stack_base, stack_size); ++ + return pthread_attr_setstack(realattr, stack_base, stack_size); + } + +-static int my_pthread_attr_getstack(pthread_attr_t const *__attr, void **stack_base, size_t *stack_size) ++static int _hybris_hook_pthread_attr_getstack(pthread_attr_t const *__attr, void **stack_base, size_t *stack_size) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; ++ ++ TRACE_HOOK("attr %p stack base %p stack size %p", __attr, ++ stack_base, stack_size); ++ + return pthread_attr_getstack(realattr, stack_base, stack_size); + } + +-static int my_pthread_attr_setguardsize(pthread_attr_t *__attr, size_t guard_size) ++static int _hybris_hook_pthread_attr_setguardsize(pthread_attr_t *__attr, size_t guard_size) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; ++ ++ TRACE_HOOK("attr %p guard size %u", __attr, guard_size); ++ + return pthread_attr_setguardsize(realattr, guard_size); + } + +-static int my_pthread_attr_getguardsize(pthread_attr_t const *__attr, size_t *guard_size) ++static int _hybris_hook_pthread_attr_getguardsize(pthread_attr_t const *__attr, size_t *guard_size) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; ++ ++ TRACE_HOOK("attr %p guard size %p", __attr, guard_size); ++ + return pthread_attr_getguardsize(realattr, guard_size); + } + +-static int my_pthread_attr_setscope(pthread_attr_t *__attr, int scope) ++static int _hybris_hook_pthread_attr_setscope(pthread_attr_t *__attr, int scope) + { + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; ++ ++ TRACE_HOOK("attr %p scope %d", __attr, scope); ++ + return pthread_attr_setscope(realattr, scope); + } + +-static int my_pthread_attr_getscope(pthread_attr_t const *__attr) ++static int _hybris_hook_pthread_attr_getscope(pthread_attr_t const *__attr) + { + int scope; + pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr; + ++ TRACE_HOOK("attr %p", __attr); ++ + /* Android doesn't have the scope attribute because it always + * returns PTHREAD_SCOPE_SYSTEM */ + pthread_attr_getscope(realattr, &scope); +@@ -342,10 +543,12 @@ static int my_pthread_attr_getscope(pthr + return scope; + } + +-static int my_pthread_getattr_np(pthread_t thid, pthread_attr_t *__attr) ++static int _hybris_hook_pthread_getattr_np(pthread_t thid, pthread_attr_t *__attr) + { + pthread_attr_t *realattr; + ++ TRACE_HOOK("attr %p", __attr); ++ + realattr = malloc(sizeof(pthread_attr_t)); + *((unsigned int *)__attr) = (unsigned int) realattr; + +@@ -360,11 +563,13 @@ static int my_pthread_getattr_np(pthread + * + * */ + +-static int my_pthread_mutex_init(pthread_mutex_t *__mutex, ++static int _hybris_hook_pthread_mutex_init(pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutexattr) + { + pthread_mutex_t *realmutex = NULL; + ++ TRACE_HOOK("mutex %p attr %p", __mutex, __mutexattr); ++ + int pshared = 0; + if (__mutexattr) + pthread_mutexattr_getpshared(__mutexattr, &pshared); +@@ -388,10 +593,12 @@ static int my_pthread_mutex_init(pthread + return pthread_mutex_init(realmutex, __mutexattr); + } + +-static int my_pthread_mutex_destroy(pthread_mutex_t *__mutex) ++static int _hybris_hook_pthread_mutex_destroy(pthread_mutex_t *__mutex) + { + int ret; + ++ TRACE_HOOK("mutex %p", __mutex); ++ + if (!__mutex) + return EINVAL; + +@@ -414,8 +621,10 @@ static int my_pthread_mutex_destroy(pthr + return ret; + } + +-static int my_pthread_mutex_lock(pthread_mutex_t *__mutex) ++static int _hybris_hook_pthread_mutex_lock(pthread_mutex_t *__mutex) + { ++ TRACE_HOOK("mutex %p", __mutex); ++ + if (!__mutex) { + LOGD("Null mutex lock, not locking."); + return 0; +@@ -432,6 +641,7 @@ static int my_pthread_mutex_lock(pthread + realmutex = (pthread_mutex_t *)hybris_get_shmpointer((hybris_shm_pointer_t)value); + + if (value <= ANDROID_TOP_ADDR_VALUE_MUTEX) { ++ TRACE("value %p <= ANDROID_TOP_ADDR_VALUE_MUTEX 0x%x", value, ANDROID_TOP_ADDR_VALUE_MUTEX); + realmutex = hybris_alloc_init_mutex(value); + *((unsigned int *)__mutex) = (unsigned int) realmutex; + } +@@ -439,10 +649,12 @@ static int my_pthread_mutex_lock(pthread + return pthread_mutex_lock(realmutex); + } + +-static int my_pthread_mutex_trylock(pthread_mutex_t *__mutex) ++static int _hybris_hook_pthread_mutex_trylock(pthread_mutex_t *__mutex) + { + unsigned int value = (*(unsigned int *) __mutex); + ++ TRACE_HOOK("mutex %p", __mutex); ++ + if (hybris_check_android_shared_mutex(value)) { + LOGD("Shared mutex with Android, not try locking."); + return 0; +@@ -460,8 +672,10 @@ static int my_pthread_mutex_trylock(pthr + return pthread_mutex_trylock(realmutex); + } + +-static int my_pthread_mutex_unlock(pthread_mutex_t *__mutex) ++static int _hybris_hook_pthread_mutex_unlock(pthread_mutex_t *__mutex) + { ++ TRACE_HOOK("mutex %p", __mutex); ++ + if (!__mutex) { + LOGD("Null mutex lock, not unlocking."); + return 0; +@@ -486,12 +700,14 @@ static int my_pthread_mutex_unlock(pthre + return pthread_mutex_unlock(realmutex); + } + +-static int my_pthread_mutex_lock_timeout_np(pthread_mutex_t *__mutex, unsigned __msecs) ++static int _hybris_hook_pthread_mutex_lock_timeout_np(pthread_mutex_t *__mutex, unsigned __msecs) + { + struct timespec tv; + pthread_mutex_t *realmutex; + unsigned int value = (*(unsigned int *) __mutex); + ++ TRACE_HOOK("mutex %p msecs %u", __mutex, __msecs); ++ + if (hybris_check_android_shared_mutex(value)) { + LOGD("Shared mutex with Android, not lock timeout np."); + return 0; +@@ -515,9 +731,36 @@ static int my_pthread_mutex_lock_timeout + return pthread_mutex_timedlock(realmutex, &tv); + } + +-static int my_pthread_mutexattr_setpshared(pthread_mutexattr_t *__attr, ++static int _hybris_hook_pthread_mutex_timedlock(pthread_mutex_t *__mutex, ++ const struct timespec *__abs_timeout) ++{ ++ TRACE_HOOK("mutex %p abs timeout %p", __mutex, __abs_timeout); ++ ++ if (!__mutex) { ++ LOGD("Null mutex lock, not unlocking."); ++ return 0; ++ } ++ ++ unsigned int value = (*(unsigned int *) __mutex); ++ if (hybris_check_android_shared_mutex(value)) { ++ LOGD("Shared mutex with Android, not lock timeout np."); ++ return 0; ++ } ++ ++ pthread_mutex_t *realmutex = (pthread_mutex_t *) value; ++ if (value <= ANDROID_TOP_ADDR_VALUE_MUTEX) { ++ realmutex = hybris_alloc_init_mutex(value); ++ *((int *)__mutex) = (int) realmutex; ++ } ++ ++ return pthread_mutex_timedlock(realmutex, __abs_timeout); ++} ++ ++static int _hybris_hook_pthread_mutexattr_setpshared(pthread_mutexattr_t *__attr, + int pshared) + { ++ TRACE_HOOK("attr %p pshared %d", __attr, pshared); ++ + return pthread_mutexattr_setpshared(__attr, pshared); + } + +@@ -529,11 +772,13 @@ static int my_pthread_mutexattr_setpshar + * + * */ + +-static int my_pthread_cond_init(pthread_cond_t *cond, ++static int _hybris_hook_pthread_cond_init(pthread_cond_t *cond, + const pthread_condattr_t *attr) + { + pthread_cond_t *realcond = NULL; + ++ TRACE_HOOK("cond %p attr %p", cond, attr); ++ + int pshared = 0; + + if (attr) +@@ -558,11 +803,13 @@ static int my_pthread_cond_init(pthread_ + return pthread_cond_init(realcond, attr); + } + +-static int my_pthread_cond_destroy(pthread_cond_t *cond) ++static int _hybris_hook_pthread_cond_destroy(pthread_cond_t *cond) + { + int ret; + pthread_cond_t *realcond = (pthread_cond_t *) *(unsigned int *) cond; + ++ TRACE_HOOK("cond %p", cond); ++ + if (!realcond) { + return EINVAL; + } +@@ -581,12 +828,15 @@ static int my_pthread_cond_destroy(pthre + return ret; + } + +-static int my_pthread_cond_broadcast(pthread_cond_t *cond) ++static int _hybris_hook_pthread_cond_broadcast(pthread_cond_t *cond) + { + unsigned int value = (*(unsigned int *) cond); ++ ++ TRACE_HOOK("cond %p", cond); ++ + if (hybris_check_android_shared_cond(value)) { +- LOGD("shared condition with Android, not broadcasting."); +- return 0; ++ LOGD("Shared condition with Android, broadcasting with futex."); ++ return android_pthread_cond_broadcast((android_cond_t *) cond); + } + + pthread_cond_t *realcond = (pthread_cond_t *) value; +@@ -601,13 +851,15 @@ static int my_pthread_cond_broadcast(pth + return pthread_cond_broadcast(realcond); + } + +-static int my_pthread_cond_signal(pthread_cond_t *cond) ++static int _hybris_hook_pthread_cond_signal(pthread_cond_t *cond) + { + unsigned int value = (*(unsigned int *) cond); + ++ TRACE_HOOK("cond %p", cond); ++ + if (hybris_check_android_shared_cond(value)) { +- LOGD("Shared condition with Android, not signaling."); +- return 0; ++ LOGD("Shared condition with Android, broadcasting with futex."); ++ return android_pthread_cond_signal((android_cond_t *) cond); + } + + pthread_cond_t *realcond = (pthread_cond_t *) value; +@@ -622,12 +874,14 @@ static int my_pthread_cond_signal(pthrea + return pthread_cond_signal(realcond); + } + +-static int my_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) ++static int _hybris_hook_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) + { + /* Both cond and mutex can be statically initialized, check for both */ + unsigned int cvalue = (*(unsigned int *) cond); + unsigned int mvalue = (*(unsigned int *) mutex); + ++ TRACE_HOOK("cond %p mutex %p", cond, mutex); ++ + if (hybris_check_android_shared_cond(cvalue) || + hybris_check_android_shared_mutex(mvalue)) { + LOGD("Shared condition/mutex with Android, not waiting."); +@@ -655,13 +909,15 @@ static int my_pthread_cond_wait(pthread_ + return pthread_cond_wait(realcond, realmutex); + } + +-static int my_pthread_cond_timedwait(pthread_cond_t *cond, ++static int _hybris_hook_pthread_cond_timedwait(pthread_cond_t *cond, + pthread_mutex_t *mutex, const struct timespec *abstime) + { + /* Both cond and mutex can be statically initialized, check for both */ + unsigned int cvalue = (*(unsigned int *) cond); + unsigned int mvalue = (*(unsigned int *) mutex); + ++ TRACE_HOOK("cond %p mutex %p abstime %p", cond, mutex, abstime); ++ + if (hybris_check_android_shared_cond(cvalue) || + hybris_check_android_shared_mutex(mvalue)) { + LOGD("Shared condition/mutex with Android, not waiting."); +@@ -689,13 +945,15 @@ static int my_pthread_cond_timedwait(pth + return pthread_cond_timedwait(realcond, realmutex, abstime); + } + +-static int my_pthread_cond_timedwait_relative_np(pthread_cond_t *cond, ++static int _hybris_hook_pthread_cond_timedwait_relative_np(pthread_cond_t *cond, + pthread_mutex_t *mutex, const struct timespec *reltime) + { + /* Both cond and mutex can be statically initialized, check for both */ + unsigned int cvalue = (*(unsigned int *) cond); + unsigned int mvalue = (*(unsigned int *) mutex); + ++ TRACE_HOOK("cond %p mutex %p reltime %p", cond, mutex, reltime); ++ + if (hybris_check_android_shared_cond(cvalue) || + hybris_check_android_shared_mutex(mvalue)) { + LOGD("Shared condition/mutex with Android, not waiting."); +@@ -731,6 +989,30 @@ static int my_pthread_cond_timedwait_rel + return pthread_cond_timedwait(realcond, realmutex, &tv); + } + ++int _hybris_hook_pthread_setname_np(pthread_t thread, const char *name) ++{ ++ TRACE_HOOK("thread %llu name %s", (unsigned long long) thread, name); ++ ++#ifdef MALI_QUIRKS ++ if (strcmp(name, MALI_HIST_DUMP_THREAD_NAME) == 0) { ++ HYBRIS_DEBUG_LOG(HOOKS, "%s: Found mali-hist-dump thread, killing it ...", ++ __FUNCTION__); ++ ++ if (thread != pthread_self()) { ++ HYBRIS_DEBUG_LOG(HOOKS, "%s: -> Failed, as calling thread is not mali-hist-dump itself", ++ __FUNCTION__); ++ return; ++ } ++ ++ pthread_exit((void*) thread); ++ ++ return; ++ } ++#endif ++ ++ return pthread_setname_np(thread, name); ++} ++ + /* + * pthread_rwlockattr_* functions + * +@@ -739,41 +1021,69 @@ static int my_pthread_cond_timedwait_rel + * + * */ + +-static int my_pthread_rwlockattr_init(pthread_rwlockattr_t *__attr) ++static int _hybris_hook_pthread_rwlockattr_init(pthread_rwlockattr_t *__attr) + { + pthread_rwlockattr_t *realattr; + ++ TRACE_HOOK("attr %p", __attr); ++ + realattr = malloc(sizeof(pthread_rwlockattr_t)); + *((unsigned int *)__attr) = (unsigned int) realattr; + + return pthread_rwlockattr_init(realattr); + } + +-static int my_pthread_rwlockattr_destroy(pthread_rwlockattr_t *__attr) ++static int _hybris_hook_pthread_rwlockattr_destroy(pthread_rwlockattr_t *__attr) + { + int ret; + pthread_rwlockattr_t *realattr = (pthread_rwlockattr_t *) *(unsigned int *) __attr; + ++ TRACE_HOOK("attr %p", __attr); ++ + ret = pthread_rwlockattr_destroy(realattr); + free(realattr); + + return ret; + } + +-static int my_pthread_rwlockattr_setpshared(pthread_rwlockattr_t *__attr, ++static int _hybris_hook_pthread_rwlockattr_setpshared(pthread_rwlockattr_t *__attr, + int pshared) + { + pthread_rwlockattr_t *realattr = (pthread_rwlockattr_t *) *(unsigned int *) __attr; ++ ++ TRACE_HOOK("attr %p pshared %d", __attr, pshared); ++ + return pthread_rwlockattr_setpshared(realattr, pshared); + } + +-static int my_pthread_rwlockattr_getpshared(pthread_rwlockattr_t *__attr, ++static int _hybris_hook_pthread_rwlockattr_getpshared(pthread_rwlockattr_t *__attr, + int *pshared) + { + pthread_rwlockattr_t *realattr = (pthread_rwlockattr_t *) *(unsigned int *) __attr; ++ ++ TRACE_HOOK("attr %p pshared %p", __attr, pshared); ++ + return pthread_rwlockattr_getpshared(realattr, pshared); + } + ++int _hybris_hook_pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *attr, int pref) ++{ ++ pthread_rwlockattr_t *realattr = (pthread_rwlockattr_t *) *(unsigned int *) attr; ++ ++ TRACE_HOOK("attr %p pref %i", attr, pref); ++ ++ return pthread_rwlockattr_setkind_np(realattr, pref); ++} ++ ++int _hybris_hook_pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *attr, int *pref) ++{ ++ pthread_rwlockattr_t *realattr = (pthread_rwlockattr_t *) *(unsigned int *) attr; ++ ++ TRACE_HOOK("attr %p pref %p", attr, pref); ++ ++ return pthread_rwlockattr_getkind_np(realattr, pref); ++} ++ + /* + * pthread_rwlock_* functions + * +@@ -782,13 +1092,15 @@ static int my_pthread_rwlockattr_getpsha + * + * */ + +-static int my_pthread_rwlock_init(pthread_rwlock_t *__rwlock, ++static int _hybris_hook_pthread_rwlock_init(pthread_rwlock_t *__rwlock, + __const pthread_rwlockattr_t *__attr) + { + pthread_rwlock_t *realrwlock = NULL; + pthread_rwlockattr_t *realattr = NULL; + int pshared = 0; + ++ TRACE_HOOK("rwlock %p attr %p", __rwlock, __attr); ++ + if (__attr != NULL) + realattr = (pthread_rwlockattr_t *) *(unsigned int *) __attr; + +@@ -814,11 +1126,13 @@ static int my_pthread_rwlock_init(pthrea + return pthread_rwlock_init(realrwlock, realattr); + } + +-static int my_pthread_rwlock_destroy(pthread_rwlock_t *__rwlock) ++static int _hybris_hook_pthread_rwlock_destroy(pthread_rwlock_t *__rwlock) + { + int ret; + pthread_rwlock_t *realrwlock = (pthread_rwlock_t *) *(unsigned int *) __rwlock; + ++ TRACE_HOOK("rwlock %p", __rwlock); ++ + if (!hybris_is_pointer_in_shm((void*)realrwlock)) { + ret = pthread_rwlock_destroy(realrwlock); + free(realrwlock); +@@ -835,6 +1149,7 @@ static pthread_rwlock_t* hybris_set_real + { + unsigned int value = (*(unsigned int *) rwlock); + pthread_rwlock_t *realrwlock = (pthread_rwlock_t *) value; ++ + if (hybris_is_pointer_in_shm((void*)value)) + realrwlock = (pthread_rwlock_t *)hybris_get_shmpointer((hybris_shm_pointer_t)value); + +@@ -845,52 +1160,74 @@ static pthread_rwlock_t* hybris_set_real + return realrwlock; + } + +-static int my_pthread_rwlock_rdlock(pthread_rwlock_t *__rwlock) ++static int _hybris_hook_pthread_rwlock_rdlock(pthread_rwlock_t *__rwlock) + { ++ TRACE_HOOK("rwlock %p", __rwlock); ++ + pthread_rwlock_t *realrwlock = hybris_set_realrwlock(__rwlock); ++ + return pthread_rwlock_rdlock(realrwlock); + } + +-static int my_pthread_rwlock_tryrdlock(pthread_rwlock_t *__rwlock) ++static int _hybris_hook_pthread_rwlock_tryrdlock(pthread_rwlock_t *__rwlock) + { ++ TRACE_HOOK("rwlock %p", __rwlock); ++ + pthread_rwlock_t *realrwlock = hybris_set_realrwlock(__rwlock); ++ + return pthread_rwlock_tryrdlock(realrwlock); + } + +-static int my_pthread_rwlock_timedrdlock(pthread_rwlock_t *__rwlock, ++static int _hybris_hook_pthread_rwlock_timedrdlock(pthread_rwlock_t *__rwlock, + __const struct timespec *abs_timeout) + { ++ TRACE_HOOK("rwlock %p abs timeout %p", __rwlock, abs_timeout); ++ + pthread_rwlock_t *realrwlock = hybris_set_realrwlock(__rwlock); ++ + return pthread_rwlock_timedrdlock(realrwlock, abs_timeout); + } + +-static int my_pthread_rwlock_wrlock(pthread_rwlock_t *__rwlock) ++static int _hybris_hook_pthread_rwlock_wrlock(pthread_rwlock_t *__rwlock) + { ++ TRACE_HOOK("rwlock %p", __rwlock); ++ + pthread_rwlock_t *realrwlock = hybris_set_realrwlock(__rwlock); ++ + return pthread_rwlock_wrlock(realrwlock); + } + +-static int my_pthread_rwlock_trywrlock(pthread_rwlock_t *__rwlock) ++static int _hybris_hook_pthread_rwlock_trywrlock(pthread_rwlock_t *__rwlock) + { ++ TRACE_HOOK("rwlock %p", __rwlock); ++ + pthread_rwlock_t *realrwlock = hybris_set_realrwlock(__rwlock); ++ + return pthread_rwlock_trywrlock(realrwlock); + } + +-static int my_pthread_rwlock_timedwrlock(pthread_rwlock_t *__rwlock, ++static int _hybris_hook_pthread_rwlock_timedwrlock(pthread_rwlock_t *__rwlock, + __const struct timespec *abs_timeout) + { ++ TRACE_HOOK("rwlock %p abs timeout %p", __rwlock, abs_timeout); ++ + pthread_rwlock_t *realrwlock = hybris_set_realrwlock(__rwlock); ++ + return pthread_rwlock_timedwrlock(realrwlock, abs_timeout); + } + +-static int my_pthread_rwlock_unlock(pthread_rwlock_t *__rwlock) ++static int _hybris_hook_pthread_rwlock_unlock(pthread_rwlock_t *__rwlock) + { + unsigned int value = (*(unsigned int *) __rwlock); ++ ++ TRACE_HOOK("rwlock %p", __rwlock); ++ + if (value <= ANDROID_TOP_ADDR_VALUE_RWLOCK) { + LOGD("Trying to unlock a rwlock that's not locked/initialized" + " by Hybris, not unlocking."); + return 0; + } ++ + pthread_rwlock_t *realrwlock = (pthread_rwlock_t *) value; + if (hybris_is_pointer_in_shm((void*)value)) + realrwlock = (pthread_rwlock_t *)hybris_get_shmpointer((hybris_shm_pointer_t)value); +@@ -898,10 +1235,27 @@ static int my_pthread_rwlock_unlock(pthr + return pthread_rwlock_unlock(realrwlock); + } + ++#define min(X,Y) (((X) < (Y)) ? (X) : (Y)) + +-static int my_set_errno(int oi_errno) ++static pid_t _hybris_hook_pthread_gettid(pthread_t t) + { ++ TRACE_HOOK("thread %lu", (unsigned long) t); ++ ++ // glibc doesn't offer us a way to retrieve the thread id for a ++ // specific thread. However pthread_t is defined as unsigned ++ // long int and is the thread id so we can just copy it over ++ // into a pid_t. ++ pid_t tid; ++ memcpy(&tid, &t, min(sizeof(tid), sizeof(t))); ++ return tid; ++} ++ ++static int _hybris_hook_set_errno(int oi_errno) ++{ ++ TRACE_HOOK("errno %d", oi_errno); ++ + errno = oi_errno; ++ + return -1; + } + +@@ -916,7 +1270,7 @@ static int my_set_errno(int oi_errno) + * instead of calling one of the hooked methods. + * Therefore we need to set __isthreaded to true, even if we are not in a multi-threaded context. + */ +-static int __my_isthreaded = 1; ++static int ___hybris_hook_isthreaded = 1; + + /* + * redirection for bionic's __sF, which is defined as: +@@ -930,64 +1284,82 @@ static int __my_isthreaded = 1; + * Currently, only fputs is managed. + */ + #define BIONIC_SIZEOF_FILE 84 +-static char my_sF[3*BIONIC_SIZEOF_FILE] = {0}; ++static char _hybris_hook_sF[3*BIONIC_SIZEOF_FILE] = {0}; + static FILE *_get_actual_fp(FILE *fp) + { + char *c_fp = (char*)fp; +- if (c_fp == &my_sF[0]) ++ if (c_fp == &_hybris_hook_sF[0]) + return stdin; +- else if (c_fp == &my_sF[BIONIC_SIZEOF_FILE]) ++ else if (c_fp == &_hybris_hook_sF[BIONIC_SIZEOF_FILE]) + return stdout; +- else if (c_fp == &my_sF[BIONIC_SIZEOF_FILE*2]) ++ else if (c_fp == &_hybris_hook_sF[BIONIC_SIZEOF_FILE*2]) + return stderr; + + return fp; + } + +-static void my_clearerr(FILE *fp) ++static void _hybris_hook_clearerr(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + clearerr(_get_actual_fp(fp)); + } + +-static int my_fclose(FILE *fp) ++static int _hybris_hook_fclose(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return fclose(_get_actual_fp(fp)); + } + +-static int my_feof(FILE *fp) ++static int _hybris_hook_feof(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return feof(_get_actual_fp(fp)); + } + +-static int my_ferror(FILE *fp) ++static int _hybris_hook_ferror(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return ferror(_get_actual_fp(fp)); + } + +-static int my_fflush(FILE *fp) ++static int _hybris_hook_fflush(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return fflush(_get_actual_fp(fp)); + } + +-static int my_fgetc(FILE *fp) ++static int _hybris_hook_fgetc(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return fgetc(_get_actual_fp(fp)); + } + +-static int my_fgetpos(FILE *fp, fpos_t *pos) ++static int _hybris_hook_fgetpos(FILE *fp, fpos_t *pos) + { ++ TRACE_HOOK("fp %p pos %p", fp, pos); ++ + return fgetpos(_get_actual_fp(fp), pos); + } + +-static char* my_fgets(char *s, int n, FILE *fp) ++static char* _hybris_hook_fgets(char *s, int n, FILE *fp) + { ++ TRACE_HOOK("s %s n %d fp %p", s, n, fp); ++ + return fgets(s, n, _get_actual_fp(fp)); + } + +-FP_ATTRIB static int my_fprintf(FILE *fp, const char *fmt, ...) ++FP_ATTRIB static int _hybris_hook_fprintf(FILE *fp, const char *fmt, ...) + { + int ret = 0; + ++ TRACE_HOOK("fp %p fmt '%s'", fp, fmt); ++ + va_list args; + va_start(args,fmt); + ret = vfprintf(_get_actual_fp(fp), fmt, args); +@@ -996,30 +1368,40 @@ FP_ATTRIB static int my_fprintf(FILE *fp + return ret; + } + +-static int my_fputc(int c, FILE *fp) ++static int _hybris_hook_fputc(int c, FILE *fp) + { ++ TRACE_HOOK("c %d fp %p", c, fp); ++ + return fputc(c, _get_actual_fp(fp)); + } + +-static int my_fputs(const char *s, FILE *fp) ++static int _hybris_hook_fputs(const char *s, FILE *fp) + { ++ TRACE_HOOK("s '%s' fp %p", s, fp); ++ + return fputs(s, _get_actual_fp(fp)); + } + +-static size_t my_fread(void *ptr, size_t size, size_t nmemb, FILE *fp) ++static size_t _hybris_hook_fread(void *ptr, size_t size, size_t nmemb, FILE *fp) + { ++ TRACE_HOOK("ptr %p size %zu nmemb %zu fp %p", ptr, size, nmemb, fp); ++ + return fread(ptr, size, nmemb, _get_actual_fp(fp)); + } + +-static FILE* my_freopen(const char *filename, const char *mode, FILE *fp) ++static FILE* _hybris_hook_freopen(const char *filename, const char *mode, FILE *fp) + { ++ TRACE_HOOK("filename '%s' mode '%s' fp %p", filename, mode, fp); ++ + return freopen(filename, mode, _get_actual_fp(fp)); + } + +-FP_ATTRIB static int my_fscanf(FILE *fp, const char *fmt, ...) ++FP_ATTRIB static int _hybris_hook_fscanf(FILE *fp, const char *fmt, ...) + { + int ret = 0; + ++ TRACE_HOOK("fp %p fmt '%s'", fp, fmt); ++ + va_list args; + va_start(args,fmt); + ret = vfscanf(_get_actual_fp(fp), fmt, args); +@@ -1028,155 +1410,208 @@ FP_ATTRIB static int my_fscanf(FILE *fp, + return ret; + } + +-static int my_fseek(FILE *fp, long offset, int whence) ++static int _hybris_hook_fseek(FILE *fp, long offset, int whence) + { ++ TRACE_HOOK("fp %p offset %ld whence %d", fp, offset, whence); ++ + return fseek(_get_actual_fp(fp), offset, whence); + } + +-static int my_fseeko(FILE *fp, off_t offset, int whence) ++static int _hybris_hook_fseeko(FILE *fp, off_t offset, int whence) + { ++ TRACE_HOOK("fp %p offset %ld whence %d", fp, offset, whence); ++ + return fseeko(_get_actual_fp(fp), offset, whence); + } + +-static int my_fsetpos(FILE *fp, const fpos_t *pos) ++static int _hybris_hook_fsetpos(FILE *fp, const fpos_t *pos) + { ++ TRACE_HOOK("fp %p pos %p", fp, pos); ++ + return fsetpos(_get_actual_fp(fp), pos); + } + +-static long my_ftell(FILE *fp) ++static long _hybris_hook_ftell(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return ftell(_get_actual_fp(fp)); + } + +-static off_t my_ftello(FILE *fp) ++static off_t _hybris_hook_ftello(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return ftello(_get_actual_fp(fp)); + } + +-static size_t my_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *fp) ++static size_t _hybris_hook_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *fp) + { ++ TRACE_HOOK("ptr %p size %zu nmemb %zu fp %p", ptr, size, nmemb, fp); ++ + return fwrite(ptr, size, nmemb, _get_actual_fp(fp)); + } + +-static int my_getc(FILE *fp) ++static int _hybris_hook_getc(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return getc(_get_actual_fp(fp)); + } + +-static ssize_t my_getdelim(char ** lineptr, size_t *n, int delimiter, FILE * fp) ++static ssize_t _hybris_hook_getdelim(char ** lineptr, size_t *n, int delimiter, FILE * fp) + { ++ TRACE_HOOK("lineptr %p n %p delimiter %d fp %p", lineptr, n, delimiter, fp); ++ + return getdelim(lineptr, n, delimiter, _get_actual_fp(fp)); + } + +-static ssize_t my_getline(char **lineptr, size_t *n, FILE *fp) ++static ssize_t _hybris_hook_getline(char **lineptr, size_t *n, FILE *fp) + { ++ TRACE_HOOK("lineptr %p n %p fp %p", lineptr, n, fp); ++ + return getline(lineptr, n, _get_actual_fp(fp)); + } + +- +-static int my_putc(int c, FILE *fp) ++static int _hybris_hook_putc(int c, FILE *fp) + { ++ TRACE_HOOK("c %d fp %p", c, fp); ++ + return putc(c, _get_actual_fp(fp)); + } + +-static void my_rewind(FILE *fp) ++static void _hybris_hook_rewind(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + rewind(_get_actual_fp(fp)); + } + +-static void my_setbuf(FILE *fp, char *buf) ++static void _hybris_hook_setbuf(FILE *fp, char *buf) + { ++ TRACE_HOOK("fp %p buf '%s'", fp, buf); ++ + setbuf(_get_actual_fp(fp), buf); + } + +-static int my_setvbuf(FILE *fp, char *buf, int mode, size_t size) ++static int _hybris_hook_setvbuf(FILE *fp, char *buf, int mode, size_t size) + { ++ TRACE_HOOK("fp %p buf '%s' mode %d size %zu", fp, buf, mode, size); ++ + return setvbuf(_get_actual_fp(fp), buf, mode, size); + } + +-static int my_ungetc(int c, FILE *fp) ++static int _hybris_hook_ungetc(int c, FILE *fp) + { ++ TRACE_HOOK("c %d fp %p", c, fp); ++ + return ungetc(c, _get_actual_fp(fp)); + } + +-static int my_vfprintf(FILE *fp, const char *fmt, va_list arg) ++static int _hybris_hook_vfprintf(FILE *fp, const char *fmt, va_list arg) + { ++ TRACE_HOOK("fp %p fmt '%s'", fp, fmt); ++ + return vfprintf(_get_actual_fp(fp), fmt, arg); + } + +- +-static int my_vfscanf(FILE *fp, const char *fmt, va_list arg) ++static int _hybris_hook_vfscanf(FILE *fp, const char *fmt, va_list arg) + { ++ TRACE_HOOK("fp %p fmt '%s'", fp, fmt); ++ + return vfscanf(_get_actual_fp(fp), fmt, arg); + } + +-static int my_fileno(FILE *fp) ++static int _hybris_hook_fileno(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return fileno(_get_actual_fp(fp)); + } + +- +-static int my_pclose(FILE *fp) ++static int _hybris_hook_pclose(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return pclose(_get_actual_fp(fp)); + } + +-static void my_flockfile(FILE *fp) ++static void _hybris_hook_flockfile(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return flockfile(_get_actual_fp(fp)); + } + +-static int my_ftrylockfile(FILE *fp) ++static int _hybris_hook_ftrylockfile(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return ftrylockfile(_get_actual_fp(fp)); + } + +-static void my_funlockfile(FILE *fp) ++static void _hybris_hook_funlockfile(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return funlockfile(_get_actual_fp(fp)); + } + +- +-static int my_getc_unlocked(FILE *fp) ++static int _hybris_hook_getc_unlocked(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return getc_unlocked(_get_actual_fp(fp)); + } + +-static int my_putc_unlocked(int c, FILE *fp) ++static int _hybris_hook_putc_unlocked(int c, FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return putc_unlocked(c, _get_actual_fp(fp)); + } + + /* exists only on the BSD platform +-static char* my_fgetln(FILE *fp, size_t *len) ++static char* _hybris_hook_fgetln(FILE *fp, size_t *len) + { + return fgetln(_get_actual_fp(fp), len); + } + */ +-static int my_fpurge(FILE *fp) ++ ++static int _hybris_hook_fpurge(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + __fpurge(_get_actual_fp(fp)); + + return 0; + } + +-static int my_getw(FILE *fp) ++static int _hybris_hook_getw(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + return getw(_get_actual_fp(fp)); + } + +-static int my_putw(int w, FILE *fp) ++static int _hybris_hook_putw(int w, FILE *fp) + { ++ TRACE_HOOK("w %d fp %p", w, fp); ++ + return putw(w, _get_actual_fp(fp)); + } + +-static void my_setbuffer(FILE *fp, char *buf, int size) ++static void _hybris_hook_setbuffer(FILE *fp, char *buf, int size) + { ++ TRACE_HOOK("fp %p buf '%s' size %d", fp, buf, size); ++ + setbuffer(_get_actual_fp(fp), buf, size); + } + +-static int my_setlinebuf(FILE *fp) ++static int _hybris_hook_setlinebuf(FILE *fp) + { ++ TRACE_HOOK("fp %p", fp); ++ + setlinebuf(_get_actual_fp(fp)); + + return 0; +@@ -1191,7 +1626,7 @@ struct bionic_dirent { + char d_name[256]; + }; + +-static struct bionic_dirent *my_readdir(DIR *dirp) ++static struct bionic_dirent *_hybris_hook_readdir(DIR *dirp) + { + /** + * readdir(3) manpage says: +@@ -1207,6 +1642,8 @@ static struct bionic_dirent *my_readdir( + + static struct bionic_dirent result; + ++ TRACE_HOOK("dirp %p", dirp); ++ + struct dirent *real_result = readdir(dirp); + if (!real_result) { + return NULL; +@@ -1225,12 +1662,14 @@ static struct bionic_dirent *my_readdir( + return &result; + } + +-static int my_readdir_r(DIR *dir, struct bionic_dirent *entry, ++static int _hybris_hook_readdir_r(DIR *dir, struct bionic_dirent *entry, + struct bionic_dirent **result) + { + struct dirent entry_r; + struct dirent *result_r; + ++ TRACE_HOOK("dir %p entry %p result %p", dir, entry, result); ++ + int res = readdir_r(dir, &entry_r, &result_r); + + if (res == 0) { +@@ -1255,89 +1694,612 @@ static int my_readdir_r(DIR *dir, struct + return res; + } + +-extern long my_sysconf(int name); ++static int _hybris_hook_alphasort(struct bionic_dirent **a, ++ struct bionic_dirent **b) ++{ ++ return strcoll((*a)->d_name, (*b)->d_name); ++} + +-FP_ATTRIB static double my_strtod(const char *nptr, char **endptr) ++static int _hybris_hook_versionsort(struct bionic_dirent **a, ++ struct bionic_dirent **b) + { +- if (locale_inited == 0) +- { +- hybris_locale = newlocale(LC_ALL_MASK, "C", 0); +- locale_inited = 1; +- } +- return strtod_l(nptr, endptr, hybris_locale); ++ return strverscmp((*a)->d_name, (*b)->d_name); + } + +-extern int __cxa_atexit(void (*)(void*), void*, void*); +-extern void __cxa_finalize(void * d); ++static struct bionic_dirent *_hybris_hook_scandirat(int fd, DIR *dirp, struct bionic_dirent ***namelist, ++ int (*filter)(const struct bionic_dirent *), ++ int (*compar)(const struct bionic_dirent **, const struct bionic_dirent **)) ++{ ++ struct dirent **namelist_r; ++ static struct bionic_dirent **result; ++ struct bionic_dirent *filter_r; + +-struct open_redirect { +- const char *from; +- const char *to; +-}; ++ int i = 0; ++ size_t nItems = 0; + +-struct open_redirect open_redirects[] = { +- { "/dev/log/main", "/dev/log_main" }, +- { "/dev/log/radio", "/dev/log_radio" }, +- { "/dev/log/system", "/dev/log_system" }, +- { "/dev/log/events", "/dev/log_events" }, +- { NULL, NULL } +-}; ++ TRACE_HOOK("dirp %p", dirp); + +-int my_open(const char *pathname, int flags, ...) +-{ +- va_list ap; +- mode_t mode = 0; +- const char *target_path = pathname; +- +- if (pathname != NULL) { +- struct open_redirect *entry = &open_redirects[0]; +- while (entry->from != NULL) { +- if (strcmp(pathname, entry->from) == 0) { +- target_path = entry->to; +- break; +- } +- entry++; +- } +- } +- +- if (flags & O_CREAT) { +- va_start(ap, flags); +- mode = va_arg(ap, mode_t); +- va_end(ap); +- } ++ int res = scandirat(fd, dirp, &namelist_r, NULL, NULL); + +- return open(target_path, flags, mode); +-} ++ if (res != 0 && namelist_r != NULL) { + +-/** +- * NOTE: Normally we don't have to wrap __system_property_get (libc.so) as it is only used +- * through the property_get (libcutils.so) function. However when property_get is used +- * internally in libcutils.so we don't have any chance to hook our replacement in. +- * Therefore we have to hook __system_property_get too and just replace it with the +- * implementation of our internal property handling +- */ ++ result = malloc(res * sizeof(struct bionic_dirent)); ++ if (!result) ++ return -1; + +-int my_system_property_get(const char *name, const char *value) +-{ +- return property_get(name, value, NULL); ++ for (i = 0; i < res; i++) { ++ filter_r = malloc(sizeof(struct bionic_dirent)); ++ if (!filter_r) { ++ while (i-- > 0) ++ free(result[i]); ++ free(result); ++ return -1; ++ } ++ filter_r->d_ino = namelist_r[i]->d_ino; ++ filter_r->d_off = namelist_r[i]->d_off; ++ filter_r->d_reclen = namelist_r[i]->d_reclen; ++ filter_r->d_type = namelist_r[i]->d_type; ++ ++ strcpy(filter_r->d_name, namelist_r[i]->d_name); ++ filter_r->d_name[sizeof(namelist_r[i]->d_name) - 1] = '\0'; ++ ++ if (filter != NULL && !(*filter)(filter_r)) {//apply filter ++ free(filter_r); ++ continue; ++ } ++ ++ result[nItems++] = filter_r; ++ } ++ if (nItems && compar != NULL) ++ qsort(result, nItems, sizeof(struct bionic_dirent *), compar); ++ ++ *namelist = result; ++ } ++ ++ return res; + } + +-static __thread void *tls_hooks[16]; ++static struct bionic_dirent *_hybris_hook_scandir(DIR *dirp, struct bionic_dirent ***namelist, ++ int (*filter)(const struct bionic_dirent *), ++ int (*compar)(const struct bionic_dirent **, const struct bionic_dirent **)) ++{ ++ return _hybris_hook_scandirat(AT_FDCWD, dirp, namelist, filter, compar); ++} + +-void *__get_tls_hooks() ++static inline void swap(void **a, void **b) + { +- return tls_hooks; ++ void *tmp = *a; ++ *a = *b; ++ *b = tmp; + } + +-static struct _hook hooks[] = { +- {"property_get", property_get }, +- {"property_set", property_set }, +- {"__system_property_get", my_system_property_get }, +- {"getenv", getenv }, +- {"printf", printf }, +- {"malloc", my_malloc }, +- {"free", free }, +- {"calloc", calloc }, ++static int _hybris_hook_getaddrinfo(const char *hostname, const char *servname, ++ const struct addrinfo *hints, struct addrinfo **res) ++{ ++ struct addrinfo *fixed_hints = NULL; ++ ++ TRACE_HOOK("hostname '%s' servname '%s' hints %p res %p", ++ hostname, servname, hints, res); ++ ++ if (hints) { ++ fixed_hints = (struct addrinfo*) malloc(sizeof(struct addrinfo)); ++ memcpy(fixed_hints, hints, sizeof(struct addrinfo)); ++ // fix bionic -> glibc missmatch ++ swap((void**)&(fixed_hints->ai_canonname), (void**)&(fixed_hints->ai_addr)); ++ } ++ ++ int result = getaddrinfo(hostname, servname, fixed_hints, res); ++ ++ if (fixed_hints) ++ free(fixed_hints); ++ ++ // fix bionic <- glibc missmatch ++ struct addrinfo *it = *res; ++ while (it) { ++ swap((void**) &(it->ai_canonname), (void**) &(it->ai_addr)); ++ it = it->ai_next; ++ } ++ ++ return result; ++} ++ ++static void _hybris_hook_freeaddrinfo(struct addrinfo *__ai) ++{ ++ TRACE_HOOK("ai %p", __ai); ++ ++ if (__ai == NULL) ++ return; ++ ++ struct addrinfo *it = __ai; ++ while (it) { ++ swap((void**) &(it->ai_canonname), (void**) &(it->ai_addr)); ++ it = it->ai_next; ++ } ++ ++ freeaddrinfo(__ai); ++} ++ ++extern long _hybris_map_sysconf(int name); ++ ++long _hybris_hook_sysconf(int name) ++{ ++ TRACE_HOOK("name %d", name); ++ ++ return _hybris_map_sysconf(name); ++} ++ ++FP_ATTRIB static double _hybris_hook_strtod(const char *nptr, char **endptr) ++{ ++ TRACE_HOOK("nptr '%s' endptr %p", nptr, endptr); ++ ++ if (locale_inited == 0) { ++ hybris_locale = newlocale(LC_ALL_MASK, "C", 0); ++ locale_inited = 1; ++ } ++ ++ return strtod_l(nptr, endptr, hybris_locale); ++} ++ ++static long int _hybris_hook_strtol(const char* str, char** endptr, int base) ++{ ++ TRACE_HOOK("str '%s' endptr %p base %i", str, endptr, base); ++ ++ return strtol(str, endptr, base); ++} ++ ++static int ___hybris_hook_system_property_read(const void *pi, char *name, char *value) ++{ ++ TRACE_HOOK("pi %p name '%s' value '%s'", pi, name, value); ++ ++ return property_get(name, value, NULL); ++} ++ ++static int ___hybris_hook_system_property_foreach(void (*propfn)(const void *pi, void *cookie), void *cookie) ++{ ++ TRACE_HOOK("propfn %p cookie %p", propfn, cookie); ++ ++ return 0; ++} ++ ++static const void *___hybris_hook_system_property_find(const char *name) ++{ ++ TRACE_HOOK("name '%s'", name); ++ ++ return NULL; ++} ++ ++static unsigned int ___hybris_hook_system_property_serial(const void *pi) ++{ ++ TRACE_HOOK("pi %p", pi); ++ ++ return 0; ++} ++ ++static int ___hybris_hook_system_property_wait(const void *pi) ++{ ++ TRACE_HOOK("pi %p", pi); ++ ++ return 0; ++} ++ ++static int ___hybris_hook_system_property_update(void *pi, const char *value, unsigned int len) ++{ ++ TRACE_HOOK("pi %p value '%s' len %d", pi, value, len); ++ ++ return 0; ++} ++ ++static int ___hybris_hook_system_property_add(const char *name, unsigned int namelen, const char *value, unsigned int valuelen) ++{ ++ TRACE_HOOK("name '%s' namelen %d value '%s' valuelen %d", ++ name, namelen, value, valuelen); ++ return 0; ++} ++ ++static unsigned int ___hybris_hook_system_property_wait_any(unsigned int serial) ++{ ++ TRACE_HOOK("serial %d", serial); ++ ++ return 0; ++} ++ ++static const void *___hybris_hook_system_property_find_nth(unsigned n) ++{ ++ TRACE_HOOK("n %d", n); ++ ++ return NULL; ++} ++ ++/** ++ * NOTE: Normally we don't have to wrap __system_property_get (libc.so) as it is only used ++ * through the property_get (libcutils.so) function. However when property_get is used ++ * internally in libcutils.so we don't have any chance to hook our replacement in. ++ * Therefore we have to hook __system_property_get too and just replace it with the ++ * implementation of our internal property handling ++ */ ++ ++int _hybris_hook_system_property_get(const char *name, const char *value) ++{ ++ TRACE_HOOK("name '%s' value '%s'", name, value); ++ ++ return property_get(name, (char*) value, NULL); ++} ++ ++int _hybris_hook_property_get(const char *key, char *value, const char *default_value) ++{ ++ TRACE_HOOK("key '%s' value '%s' default value '%s'", ++ key, value, default_value); ++ ++ return property_get(key, value, default_value); ++} ++ ++int _hybris_hook_property_set(const char *key, const char *value) ++{ ++ TRACE_HOOK("key '%s' value '%s'", key, value); ++ ++ return property_set(key, value); ++} ++ ++char *_hybris_hook_getenv(const char *name) ++{ ++ TRACE_HOOK("name '%s'", name); ++ ++ return getenv(name); ++} ++ ++int _hybris_hook_setenv(const char *name, const char *value, int overwrite) ++{ ++ TRACE_HOOK("name '%s' value '%s' overwrite %d", name, value, overwrite); ++ ++ return setenv(name, value, overwrite); ++} ++ ++int _hybris_hook_putenv(char *string) ++{ ++ TRACE_HOOK("string '%s'", string); ++ ++ return putenv(string); ++} ++ ++int _hybris_hook_clearenv(void) ++{ ++ TRACE_HOOK(""); ++ ++ return clearenv(); ++} ++ ++extern int __cxa_atexit(void (*)(void*), void*, void*); ++extern void __cxa_finalize(void * d); ++ ++struct open_redirect { ++ const char *from; ++ const char *to; ++}; ++ ++struct open_redirect open_redirects[] = { ++ { "/dev/log/main", "/dev/alog/main" }, ++ { "/dev/log/radio", "/dev/alog/radio" }, ++ { "/dev/log/system", "/dev/alog/system" }, ++ { "/dev/log/events", "/dev/alog/events" }, ++ { NULL, NULL } ++}; ++ ++int _hybris_hook_open(const char *pathname, int flags, ...) ++{ ++ va_list ap; ++ mode_t mode = 0; ++ const char *target_path = pathname; ++ ++ TRACE_HOOK("pathname '%s' flags %d", pathname, flags); ++ ++ if (pathname != NULL) { ++ struct open_redirect *entry = &open_redirects[0]; ++ while (entry->from != NULL) { ++ if (strcmp(pathname, entry->from) == 0) { ++ target_path = entry->to; ++ break; ++ } ++ entry++; ++ } ++ } ++ ++ if (flags & O_CREAT) { ++ va_start(ap, flags); ++ mode = va_arg(ap, mode_t); ++ va_end(ap); ++ } ++ ++ return open(target_path, flags, mode); ++} ++ ++static __thread void *tls_hooks[16]; ++ ++static void *_hybris_hook_get_tls_hooks() ++{ ++ TRACE_HOOK(""); ++ return tls_hooks; ++} ++ ++int _hybris_hook_prctl(int option, unsigned long arg2, unsigned long arg3, ++ unsigned long arg4, unsigned long arg5) ++{ ++ TRACE_HOOK("option %d arg2 %lu arg3 %lu arg4 %lu arg5 %lu", ++ option, arg2, arg3, arg4, arg5); ++ ++#ifdef MALI_QUIRKS ++ if (option == PR_SET_NAME) { ++ char *name = (char*) arg2; ++ ++ if (strcmp(name, MALI_HIST_DUMP_THREAD_NAME) == 0) { ++ ++ // This can only work because prctl with PR_SET_NAME ++ // can be only called for the current thread and not ++ // for another thread so we can safely pause things. ++ ++ HYBRIS_DEBUG_LOG(HOOKS, "%s: Found mali-hist-dump, killing thread ...", ++ __FUNCTION__); ++ ++ pthread_exit(NULL); ++ } ++ } ++#endif ++ ++ return prctl(option, arg2, arg3, arg4, arg5); ++} ++ ++static char* _hybris_hook_basename(const char *path) ++{ ++ static __thread char buf[PATH_MAX]; ++ ++ TRACE_HOOK("path '%s'", path); ++ ++ memset(buf, 0, sizeof(buf)); ++ ++ if (path) ++ strncpy(buf, path, sizeof(buf)); ++ ++ buf[sizeof buf - 1] = '\0'; ++ ++ return basename(buf); ++} ++ ++static char* _hybris_hook_dirname(char *path) ++{ ++ static __thread char buf[PATH_MAX]; ++ ++ TRACE_HOOK("path '%s'", path); ++ ++ memset(buf, 0, sizeof(buf)); ++ ++ if (path) ++ strncpy(buf, path, sizeof(buf)); ++ ++ buf[sizeof buf - 1] = '\0'; ++ ++ return dirname(path); ++} ++ ++static char* _hybris_hook_strerror(int errnum) ++{ ++ TRACE_HOOK("errnum %d", errnum); ++ ++ return strerror(errnum); ++} ++ ++static char* _hybris_hook__gnu_strerror_r(int errnum, char *buf, size_t buf_len) ++{ ++ TRACE_HOOK("errnum %d buf '%s' buf len %zu", errnum, buf, buf_len); ++ ++ return strerror_r(errnum, buf, buf_len); ++} ++ ++static int _hybris_hook_mprotect(void *addr, size_t len, int prot) ++{ ++ TRACE_HOOK("addr %p len %zu prot %d", addr, len, prot); ++ ++ return mprotect(addr, len, prot); ++} ++ ++static int _hybris_hook_posix_memalign(void **memptr, size_t alignment, size_t size) ++{ ++ TRACE_HOOK("memptr %p alignment %zu size %zu", memptr, alignment, size); ++ ++ return posix_memalign(memptr, alignment, size); ++} ++ ++static pid_t _hybris_hook_fork(void) ++{ ++ TRACE_HOOK(""); ++ ++ return fork(); ++} ++ ++static locale_t _hybris_hook_newlocale(int category_mask, const char *locale, locale_t base) ++{ ++ TRACE_HOOK("category mask %i locale '%s'", category_mask, locale); ++ ++ return newlocale(category_mask, locale, base); ++} ++ ++static void _hybris_hook_freelocale(locale_t locobj) ++{ ++ TRACE_HOOK(""); ++ ++ return freelocale(locobj); ++} ++ ++static locale_t _hybris_hook_duplocale(locale_t locobj) ++{ ++ TRACE_HOOK(""); ++ ++ return duplocale(locobj); ++} ++ ++static locale_t _hybris_hook_uselocale(locale_t newloc) ++{ ++ TRACE_HOOK(""); ++ ++ return uselocale(newloc); ++} ++ ++static struct lconv* _hybris_hook_localeconv(void) ++{ ++ TRACE_HOOK(""); ++ ++ return localeconv(); ++} ++ ++static char* _hybris_hook_setlocale(int category, const char *locale) ++{ ++ TRACE_HOOK("category %i locale '%s'", category, locale); ++ ++ return setlocale(category, locale); ++} ++ ++static void* _hybris_hook_mmap(void *addr, size_t len, int prot, ++ int flags, int fd, off_t offset) ++{ ++ TRACE_HOOK("addr %p len %u prot %i flags %i fd %i offset %u", ++ addr, len, prot, flags, fd, offset); ++ ++ return mmap(addr, len, prot, flags, fd, offset); ++} ++ ++static int _hybris_hook_munmap(void *addr, size_t length) ++{ ++ TRACE_HOOK("addr %p length %u", addr, length); ++ ++ return munmap(addr, length); ++} ++ ++extern size_t strlcat(char *dst, const char *src, size_t siz); ++extern size_t strlcpy(char *dst, const char *src, size_t siz); ++ ++static int _hybris_hook_strcmp(const char *s1, const char *s2) ++{ ++ TRACE_HOOK("s1 '%s' s2 '%s'", s1, s2); ++ ++ if ( s1 == NULL || s2 == NULL) ++ return -1; ++ ++ return strcmp(s1, s2); ++} ++ ++static FILE* _hybris_hook_setmntent(const char *filename, const char *type) ++{ ++ TRACE_HOOK("filename %s type %s", filename, type); ++ ++ return setmntent(filename, type); ++} ++ ++static struct mntent* _hybris_hook_getmntent(FILE *fp) ++{ ++ TRACE_HOOK("fp %p", fp); ++ ++ return getmntent(_get_actual_fp(fp)); ++} ++ ++static struct mntent* _hybris_hook_getmntent_r(FILE *fp, struct mntent *e, char *buf, int buf_len) ++{ ++ TRACE_HOOK("fp %p e %p buf '%s' buf len %i", ++ fp, e, buf, buf_len); ++ ++ return getmntent_r(_get_actual_fp(fp), e, buf, buf_len); ++} ++ ++int _hybris_hook_endmntent(FILE *fp) ++{ ++ TRACE_HOOK("fp %p", fp); ++ ++ return endmntent(_get_actual_fp(fp)); ++} ++ ++static int _hybris_hook_fputws(const wchar_t *ws, FILE *stream) ++{ ++ TRACE_HOOK("stream %p", stream); ++ ++ return fputws(ws, _get_actual_fp(stream)); ++} ++ ++static int _hybris_hook_vfwprintf(FILE *stream, const wchar_t *format, va_list args) ++{ ++ TRACE_HOOK("stream %p", stream); ++ ++ return vfwprintf(_get_actual_fp(stream), format, args); ++} ++ ++static wint_t _hybris_hook_fputwc(wchar_t wc, FILE *stream) ++{ ++ TRACE_HOOK("stream %p", stream); ++ ++ return fputwc(wc, _get_actual_fp(stream)); ++} ++ ++static wint_t _hybris_hook_putwc(wchar_t wc, FILE *stream) ++{ ++ TRACE_HOOK("stream %p", stream); ++ ++ return putwc(wc, _get_actual_fp(stream)); ++} ++ ++static wint_t _hybris_hook_fgetwc(FILE *stream) ++{ ++ TRACE_HOOK("stream %p", stream); ++ ++ return fgetwc(_get_actual_fp(stream)); ++} ++ ++static wint_t _hybris_hook_getwc(FILE *stream) ++{ ++ TRACE_HOOK("stream %p", stream); ++ ++ return getwc(_get_actual_fp(stream)); ++} ++ ++static void *_hybris_hook_android_dlopen(const char *filename, int flag) ++{ ++ TRACE("filename %s flag %i", filename, flag); ++ ++ return _android_dlopen(filename,flag); ++} ++ ++static void *_hybris_hook_android_dlsym(void *handle, const char *symbol) ++{ ++ TRACE("handle %p symbol %s", handle, symbol); ++ ++ return _android_dlsym(handle,symbol); ++} ++ ++static void* _hybris_hook_android_dladdr(void *addr, Dl_info *info) ++{ ++ TRACE("addr %p info %p", addr, info); ++ ++ return _android_dladdr(addr, info); ++} ++ ++static int _hybris_hook_android_dlclose(void *handle) ++{ ++ TRACE("handle %p", handle); ++ ++ return _android_dlclose(handle); ++} ++ ++static const char *_hybris_hook_android_dlerror(void) ++{ ++ TRACE(""); ++ ++ return android_dlerror(); ++} ++ ++static struct _hook hooks_common[] = { ++ {"property_get", _hybris_hook_property_get }, ++ {"property_set", _hybris_hook_property_set }, ++ {"__system_property_get", _hybris_hook_system_property_get }, ++ {"getenv", _hybris_hook_getenv}, ++ {"printf", printf }, ++ {"malloc", _hybris_hook_malloc }, ++ {"free", free }, ++ {"calloc", calloc }, + {"cfree", cfree }, + {"realloc", realloc }, + {"memalign", memalign }, +@@ -1345,22 +2307,24 @@ static struct _hook hooks[] = { + {"pvalloc", pvalloc }, + {"fread", fread }, + {"getxattr", getxattr}, ++ {"mprotect", _hybris_hook_mprotect}, + /* string.h */ + {"memccpy",memccpy}, + {"memchr",memchr}, + {"memrchr",memrchr}, +- {"memcmp",memcmp}, +- {"memcpy",my_memcpy}, ++ {"memcmp",_hybris_hook_memcmp}, ++ {"memcpy",_hybris_hook_memcpy}, + {"memmove",memmove}, + {"memset",memset}, + {"memmem",memmem}, +- // {"memswap",memswap}, ++ {"getlogin", getlogin}, ++ // {"memswap",memswap}, + {"index",index}, + {"rindex",rindex}, + {"strchr",strchr}, + {"strrchr",strrchr}, +- {"strlen",my_strlen}, +- {"strcmp",strcmp}, ++ {"strlen",_hybris_hook_strlen}, ++ {"strcmp",_hybris_hook_strcmp}, + {"strcpy",strcpy}, + {"strcat",strcat}, + {"strcasecmp",strcasecmp}, +@@ -1369,16 +2333,14 @@ static struct _hook hooks[] = { + {"strstr",strstr}, + {"strtok",strtok}, + {"strtok_r",strtok_r}, +- {"strerror",strerror}, ++ {"strerror",_hybris_hook_strerror}, + {"strerror_r",strerror_r}, + {"strnlen",strnlen}, + {"strncat",strncat}, + {"strndup",strndup}, + {"strncmp",strncmp}, + {"strncpy",strncpy}, +- {"strtod", my_strtod}, +- //{"strlcat",strlcat}, +- //{"strlcpy",strlcpy}, ++ {"strtod", _hybris_hook_strtod}, + {"strcspn",strcspn}, + {"strpbrk",strpbrk}, + {"strsep",strsep}, +@@ -1395,17 +2357,19 @@ static struct _hook hooks[] = { + {"index",index}, + {"rindex",rindex}, + {"strcasecmp",strcasecmp}, ++ {"__sprintf_chk", __sprintf_chk}, ++ {"__snprintf_chk", __snprintf_chk}, + {"strncasecmp",strncasecmp}, + /* dirent.h */ + {"opendir", opendir}, + {"closedir", closedir}, + /* pthread.h */ + {"getauxval", getauxval}, +- {"gettid", my_gettid}, ++ {"gettid", _hybris_hook_gettid}, + {"getpid", getpid}, + {"pthread_atfork", pthread_atfork}, +- {"pthread_create", my_pthread_create}, +- {"pthread_kill", pthread_kill}, ++ {"pthread_create", _hybris_hook_pthread_create}, ++ {"pthread_kill", _hybris_hook_pthread_kill}, + {"pthread_exit", pthread_exit}, + {"pthread_join", pthread_join}, + {"pthread_detach", pthread_detach}, +@@ -1413,72 +2377,78 @@ static struct _hook hooks[] = { + {"pthread_equal", pthread_equal}, + {"pthread_getschedparam", pthread_getschedparam}, + {"pthread_setschedparam", pthread_setschedparam}, +- {"pthread_mutex_init", my_pthread_mutex_init}, +- {"pthread_mutex_destroy", my_pthread_mutex_destroy}, +- {"pthread_mutex_lock", my_pthread_mutex_lock}, +- {"pthread_mutex_unlock", my_pthread_mutex_unlock}, +- {"pthread_mutex_trylock", my_pthread_mutex_trylock}, +- {"pthread_mutex_lock_timeout_np", my_pthread_mutex_lock_timeout_np}, ++ {"pthread_mutex_init", _hybris_hook_pthread_mutex_init}, ++ {"pthread_mutex_destroy", _hybris_hook_pthread_mutex_destroy}, ++ {"pthread_mutex_lock", _hybris_hook_pthread_mutex_lock}, ++ {"pthread_mutex_unlock", _hybris_hook_pthread_mutex_unlock}, ++ {"pthread_mutex_trylock", _hybris_hook_pthread_mutex_trylock}, ++ {"pthread_mutex_lock_timeout_np", _hybris_hook_pthread_mutex_lock_timeout_np}, ++ {"pthread_mutex_timedlock", _hybris_hook_pthread_mutex_timedlock}, + {"pthread_mutexattr_init", pthread_mutexattr_init}, + {"pthread_mutexattr_destroy", pthread_mutexattr_destroy}, + {"pthread_mutexattr_gettype", pthread_mutexattr_gettype}, + {"pthread_mutexattr_settype", pthread_mutexattr_settype}, + {"pthread_mutexattr_getpshared", pthread_mutexattr_getpshared}, +- {"pthread_mutexattr_setpshared", my_pthread_mutexattr_setpshared}, ++ {"pthread_mutexattr_setpshared", _hybris_hook_pthread_mutexattr_setpshared}, + {"pthread_condattr_init", pthread_condattr_init}, + {"pthread_condattr_getpshared", pthread_condattr_getpshared}, + {"pthread_condattr_setpshared", pthread_condattr_setpshared}, + {"pthread_condattr_destroy", pthread_condattr_destroy}, +- {"pthread_cond_init", my_pthread_cond_init}, +- {"pthread_cond_destroy", my_pthread_cond_destroy}, +- {"pthread_cond_broadcast", my_pthread_cond_broadcast}, +- {"pthread_cond_signal", my_pthread_cond_signal}, +- {"pthread_cond_wait", my_pthread_cond_wait}, +- {"pthread_cond_timedwait", my_pthread_cond_timedwait}, +- {"pthread_cond_timedwait_monotonic", my_pthread_cond_timedwait}, +- {"pthread_cond_timedwait_monotonic_np", my_pthread_cond_timedwait}, +- {"pthread_cond_timedwait_relative_np", my_pthread_cond_timedwait_relative_np}, ++ {"pthread_condattr_getclock", pthread_condattr_getclock}, ++ {"pthread_condattr_setclock", pthread_condattr_setclock}, ++ {"pthread_cond_init", _hybris_hook_pthread_cond_init}, ++ {"pthread_cond_destroy", _hybris_hook_pthread_cond_destroy}, ++ {"pthread_cond_broadcast", _hybris_hook_pthread_cond_broadcast}, ++ {"pthread_cond_signal", _hybris_hook_pthread_cond_signal}, ++ {"pthread_cond_wait", _hybris_hook_pthread_cond_wait}, ++ {"pthread_cond_timedwait", _hybris_hook_pthread_cond_timedwait}, ++ {"pthread_cond_timedwait_monotonic", _hybris_hook_pthread_cond_timedwait}, ++ {"pthread_cond_timedwait_monotonic_np", _hybris_hook_pthread_cond_timedwait}, ++ {"pthread_cond_timedwait_relative_np", _hybris_hook_pthread_cond_timedwait_relative_np}, + {"pthread_key_delete", pthread_key_delete}, +- {"pthread_setname_np", pthread_setname_np}, ++ {"pthread_setname_np", _hybris_hook_pthread_setname_np}, + {"pthread_once", pthread_once}, + {"pthread_key_create", pthread_key_create}, +- {"pthread_setspecific", pthread_setspecific}, +- {"pthread_getspecific", pthread_getspecific}, +- {"pthread_attr_init", my_pthread_attr_init}, +- {"pthread_attr_destroy", my_pthread_attr_destroy}, +- {"pthread_attr_setdetachstate", my_pthread_attr_setdetachstate}, +- {"pthread_attr_getdetachstate", my_pthread_attr_getdetachstate}, +- {"pthread_attr_setschedpolicy", my_pthread_attr_setschedpolicy}, +- {"pthread_attr_getschedpolicy", my_pthread_attr_getschedpolicy}, +- {"pthread_attr_setschedparam", my_pthread_attr_setschedparam}, +- {"pthread_attr_getschedparam", my_pthread_attr_getschedparam}, +- {"pthread_attr_setstacksize", my_pthread_attr_setstacksize}, +- {"pthread_attr_getstacksize", my_pthread_attr_getstacksize}, +- {"pthread_attr_setstackaddr", my_pthread_attr_setstackaddr}, +- {"pthread_attr_getstackaddr", my_pthread_attr_getstackaddr}, +- {"pthread_attr_setstack", my_pthread_attr_setstack}, +- {"pthread_attr_getstack", my_pthread_attr_getstack}, +- {"pthread_attr_setguardsize", my_pthread_attr_setguardsize}, +- {"pthread_attr_getguardsize", my_pthread_attr_getguardsize}, +- {"pthread_attr_setscope", my_pthread_attr_setscope}, +- {"pthread_attr_setscope", my_pthread_attr_getscope}, +- {"pthread_getattr_np", my_pthread_getattr_np}, +- {"pthread_rwlockattr_init", my_pthread_rwlockattr_init}, +- {"pthread_rwlockattr_destroy", my_pthread_rwlockattr_destroy}, +- {"pthread_rwlockattr_setpshared", my_pthread_rwlockattr_setpshared}, +- {"pthread_rwlockattr_getpshared", my_pthread_rwlockattr_getpshared}, +- {"pthread_rwlock_init", my_pthread_rwlock_init}, +- {"pthread_rwlock_destroy", my_pthread_rwlock_destroy}, +- {"pthread_rwlock_unlock", my_pthread_rwlock_unlock}, +- {"pthread_rwlock_wrlock", my_pthread_rwlock_wrlock}, +- {"pthread_rwlock_rdlock", my_pthread_rwlock_rdlock}, +- {"pthread_rwlock_tryrdlock", my_pthread_rwlock_tryrdlock}, +- {"pthread_rwlock_trywrlock", my_pthread_rwlock_trywrlock}, +- {"pthread_rwlock_timedrdlock", my_pthread_rwlock_timedrdlock}, +- {"pthread_rwlock_timedwrlock", my_pthread_rwlock_timedwrlock}, ++ {"pthread_setspecific", _hybris_hook_pthread_setspecific}, ++ {"pthread_getspecific", _hybris_hook_pthread_getspecific}, ++ {"pthread_attr_init", _hybris_hook_pthread_attr_init}, ++ {"pthread_attr_destroy", _hybris_hook_pthread_attr_destroy}, ++ {"pthread_attr_setdetachstate", _hybris_hook_pthread_attr_setdetachstate}, ++ {"pthread_attr_getdetachstate", _hybris_hook_pthread_attr_getdetachstate}, ++ {"pthread_attr_setschedpolicy", _hybris_hook_pthread_attr_setschedpolicy}, ++ {"pthread_attr_getschedpolicy", _hybris_hook_pthread_attr_getschedpolicy}, ++ {"pthread_attr_setschedparam", _hybris_hook_pthread_attr_setschedparam}, ++ {"pthread_attr_getschedparam", _hybris_hook_pthread_attr_getschedparam}, ++ {"pthread_attr_setstacksize", _hybris_hook_pthread_attr_setstacksize}, ++ {"pthread_attr_getstacksize", _hybris_hook_pthread_attr_getstacksize}, ++ {"pthread_attr_setstackaddr", _hybris_hook_pthread_attr_setstackaddr}, ++ {"pthread_attr_getstackaddr", _hybris_hook_pthread_attr_getstackaddr}, ++ {"pthread_attr_setstack", _hybris_hook_pthread_attr_setstack}, ++ {"pthread_attr_getstack", _hybris_hook_pthread_attr_getstack}, ++ {"pthread_attr_setguardsize", _hybris_hook_pthread_attr_setguardsize}, ++ {"pthread_attr_getguardsize", _hybris_hook_pthread_attr_getguardsize}, ++ {"pthread_attr_setscope", _hybris_hook_pthread_attr_setscope}, ++ {"pthread_attr_getscope", _hybris_hook_pthread_attr_getscope}, ++ {"pthread_getattr_np", _hybris_hook_pthread_getattr_np}, ++ {"pthread_rwlockattr_init", _hybris_hook_pthread_rwlockattr_init}, ++ {"pthread_rwlockattr_destroy", _hybris_hook_pthread_rwlockattr_destroy}, ++ {"pthread_rwlockattr_setpshared", _hybris_hook_pthread_rwlockattr_setpshared}, ++ {"pthread_rwlockattr_getpshared", _hybris_hook_pthread_rwlockattr_getpshared}, ++ {"pthread_rwlock_init", _hybris_hook_pthread_rwlock_init}, ++ {"pthread_rwlock_destroy", _hybris_hook_pthread_rwlock_destroy}, ++ {"pthread_rwlock_unlock", _hybris_hook_pthread_rwlock_unlock}, ++ {"pthread_rwlock_wrlock", _hybris_hook_pthread_rwlock_wrlock}, ++ {"pthread_rwlock_rdlock", _hybris_hook_pthread_rwlock_rdlock}, ++ {"pthread_rwlock_tryrdlock", _hybris_hook_pthread_rwlock_tryrdlock}, ++ {"pthread_rwlock_trywrlock", _hybris_hook_pthread_rwlock_trywrlock}, ++ {"pthread_rwlock_timedrdlock", _hybris_hook_pthread_rwlock_timedrdlock}, ++ {"pthread_rwlock_timedwrlock", _hybris_hook_pthread_rwlock_timedwrlock}, ++ /* bionic-only pthread */ ++ {"__pthread_gettid", _hybris_hook_pthread_gettid}, ++ {"pthread_gettid_np", _hybris_hook_pthread_gettid}, + /* stdio.h */ +- {"__isthreaded", &__my_isthreaded}, +- {"__sF", &my_sF}, ++ {"__isthreaded", &___hybris_hook_isthreaded}, ++ {"__sF", &_hybris_hook_sF}, + {"fopen", fopen}, + {"fdopen", fdopen}, + {"popen", popen}, +@@ -1489,79 +2459,80 @@ static struct _hook hooks[] = { + {"snprintf", snprintf}, + {"vsprintf", vsprintf}, + {"vsnprintf", vsnprintf}, +- {"clearerr", my_clearerr}, +- {"fclose", my_fclose}, +- {"feof", my_feof}, +- {"ferror", my_ferror}, +- {"fflush", my_fflush}, +- {"fgetc", my_fgetc}, +- {"fgetpos", my_fgetpos}, +- {"fgets", my_fgets}, +- {"fprintf", my_fprintf}, +- {"fputc", my_fputc}, +- {"fputs", my_fputs}, +- {"fread", my_fread}, +- {"freopen", my_freopen}, +- {"fscanf", my_fscanf}, +- {"fseek", my_fseek}, +- {"fseeko", my_fseeko}, +- {"fsetpos", my_fsetpos}, +- {"ftell", my_ftell}, +- {"ftello", my_ftello}, +- {"fwrite", my_fwrite}, +- {"getc", my_getc}, +- {"getdelim", my_getdelim}, +- {"getline", my_getline}, +- {"putc", my_putc}, +- {"rewind", my_rewind}, +- {"setbuf", my_setbuf}, +- {"setvbuf", my_setvbuf}, +- {"ungetc", my_ungetc}, ++ {"clearerr", _hybris_hook_clearerr}, ++ {"fclose", _hybris_hook_fclose}, ++ {"feof", _hybris_hook_feof}, ++ {"ferror", _hybris_hook_ferror}, ++ {"fflush", _hybris_hook_fflush}, ++ {"fgetc", _hybris_hook_fgetc}, ++ {"fgetpos", _hybris_hook_fgetpos}, ++ {"fgets", _hybris_hook_fgets}, ++ {"fprintf", _hybris_hook_fprintf}, ++ {"fputc", _hybris_hook_fputc}, ++ {"fputs", _hybris_hook_fputs}, ++ {"fread", _hybris_hook_fread}, ++ {"freopen", _hybris_hook_freopen}, ++ {"fscanf", _hybris_hook_fscanf}, ++ {"fseek", _hybris_hook_fseek}, ++ {"fseeko", _hybris_hook_fseeko}, ++ {"fsetpos", _hybris_hook_fsetpos}, ++ {"ftell", _hybris_hook_ftell}, ++ {"ftello", _hybris_hook_ftello}, ++ {"fwrite", _hybris_hook_fwrite}, ++ {"getc", _hybris_hook_getc}, ++ {"getdelim", _hybris_hook_getdelim}, ++ {"getline", _hybris_hook_getline}, ++ {"putc", _hybris_hook_putc}, ++ {"rewind", _hybris_hook_rewind}, ++ {"setbuf", _hybris_hook_setbuf}, ++ {"setvbuf", _hybris_hook_setvbuf}, ++ {"ungetc", _hybris_hook_ungetc}, + {"vasprintf", vasprintf}, +- {"vfprintf", my_vfprintf}, +- {"vfscanf", my_vfscanf}, +- {"fileno", my_fileno}, +- {"pclose", my_pclose}, +- {"flockfile", my_flockfile}, +- {"ftrylockfile", my_ftrylockfile}, +- {"funlockfile", my_funlockfile}, +- {"getc_unlocked", my_getc_unlocked}, +- {"putc_unlocked", my_putc_unlocked}, +- //{"fgetln", my_fgetln}, +- {"fpurge", my_fpurge}, +- {"getw", my_getw}, +- {"putw", my_putw}, +- {"setbuffer", my_setbuffer}, +- {"setlinebuf", my_setlinebuf}, ++ {"vfprintf", _hybris_hook_vfprintf}, ++ {"vfscanf", _hybris_hook_vfscanf}, ++ {"fileno", _hybris_hook_fileno}, ++ {"pclose", _hybris_hook_pclose}, ++ {"flockfile", _hybris_hook_flockfile}, ++ {"ftrylockfile", _hybris_hook_ftrylockfile}, ++ {"funlockfile", _hybris_hook_funlockfile}, ++ {"getc_unlocked", _hybris_hook_getc_unlocked}, ++ {"putc_unlocked", _hybris_hook_putc_unlocked}, ++ //{"fgetln", _hybris_hook_fgetln}, ++ {"fpurge", _hybris_hook_fpurge}, ++ {"getw", _hybris_hook_getw}, ++ {"putw", _hybris_hook_putw}, ++ {"setbuffer", _hybris_hook_setbuffer}, ++ {"setlinebuf", _hybris_hook_setlinebuf}, + {"__errno", __errno_location}, +- {"__set_errno", my_set_errno}, ++ {"__set_errno", _hybris_hook_set_errno}, + /* net specifics, to avoid __res_get_state */ +- {"getaddrinfo", getaddrinfo}, ++ {"getaddrinfo", _hybris_hook_getaddrinfo}, ++ {"freeaddrinfo", _hybris_hook_freeaddrinfo}, + {"gethostbyaddr", gethostbyaddr}, + {"gethostbyname", gethostbyname}, + {"gethostbyname2", gethostbyname2}, + {"gethostent", gethostent}, + {"strftime", strftime}, +- {"sysconf", my_sysconf}, +- {"dlopen", android_dlopen}, +- {"dlerror", android_dlerror}, +- {"dlsym", android_dlsym}, +- {"dladdr", android_dladdr}, +- {"dlclose", android_dlclose}, ++ {"sysconf", _hybris_hook_sysconf}, ++ {"dlopen", _hybris_hook_android_dlopen}, ++ {"dlerror", _hybris_hook_android_dlerror}, ++ {"dlsym", _hybris_hook_android_dlsym}, ++ {"dladdr", _hybris_hook_android_dladdr}, ++ {"dlclose", _hybris_hook_android_dlclose}, + /* dirent.h */ + {"opendir", opendir}, + {"fdopendir", fdopendir}, + {"closedir", closedir}, +- {"readdir", my_readdir}, +- {"readdir_r", my_readdir_r}, ++ {"readdir", _hybris_hook_readdir}, ++ {"readdir_r", _hybris_hook_readdir_r}, + {"rewinddir", rewinddir}, + {"seekdir", seekdir}, + {"telldir", telldir}, + {"dirfd", dirfd}, + /* fcntl.h */ +- {"open", my_open}, ++ {"open", _hybris_hook_open}, + // TODO: scandir, scandirat, alphasort, versionsort +- {"__get_tls_hooks", __get_tls_hooks}, ++ {"__get_tls_hooks", _hybris_hook_get_tls_hooks}, + {"sscanf", sscanf}, + {"scanf", scanf}, + {"vscanf", vscanf}, +@@ -1575,6 +2546,9 @@ static struct _hook hooks[] = { + {"timer_gettime", timer_gettime}, + {"timer_delete", timer_delete}, + {"timer_getoverrun", timer_getoverrun}, ++ {"localtime", localtime}, ++ {"localtime_r", localtime_r}, ++ {"gmtime", gmtime}, + {"abort", abort}, + {"writev", writev}, + /* unistd.h */ +@@ -1583,34 +2557,372 @@ static struct _hook hooks[] = { + {"getgrgid", getgrgid}, + {"__cxa_atexit", __cxa_atexit}, + {"__cxa_finalize", __cxa_finalize}, +- {NULL, NULL}, ++ {"__system_property_read", ___hybris_hook_system_property_read}, ++ {"__system_property_set", property_set}, ++ {"__system_property_foreach", ___hybris_hook_system_property_foreach}, ++ {"__system_property_find", ___hybris_hook_system_property_find}, ++ {"__system_property_serial", ___hybris_hook_system_property_serial}, ++ {"__system_property_wait", ___hybris_hook_system_property_wait}, ++ {"__system_property_update", ___hybris_hook_system_property_update}, ++ {"__system_property_add", ___hybris_hook_system_property_add}, ++ {"__system_property_wait_any", ___hybris_hook_system_property_wait_any}, ++ {"__system_property_find_nth", ___hybris_hook_system_property_find_nth}, ++ /* sys/prctl.h */ ++ {"prctl", _hybris_hook_prctl}, ++}; ++ ++static struct _hook hooks_mm[] = { ++ {"strtol", _hybris_hook_strtol}, ++ {"strlcat",strlcat}, ++ {"strlcpy",strlcpy}, ++ {"setenv", _hybris_hook_setenv}, ++ {"putenv", _hybris_hook_putenv}, ++ {"clearenv", _hybris_hook_clearenv}, ++ {"dprintf", dprintf}, ++ {"mallinfo", mallinfo}, ++ {"malloc_usable_size", _hybris_hook_malloc_usable_size}, ++ {"posix_memalign", _hybris_hook_posix_memalign}, ++ {"mprotect", _hybris_hook_mprotect}, ++ {"__memcpy_chk", __memcpy_chk}, ++ {"__memset_chk", __memset_chk}, ++ {"__gnu_strerror_r",_hybris_hook__gnu_strerror_r}, ++ {"__strncpy_chk",__strncpy_chk}, ++ {"pthread_rwlockattr_getkind_np", _hybris_hook_pthread_rwlockattr_getkind_np}, ++ {"pthread_rwlockattr_setkind_np", _hybris_hook_pthread_rwlockattr_setkind_np}, ++ /* unistd.h */ ++ {"fork", _hybris_hook_fork}, ++ {"ttyname", ttyname}, ++ {"swprintf", swprintf}, ++ {"fmemopen", fmemopen}, ++ {"open_memstream", open_memstream}, ++ {"open_wmemstream", open_wmemstream}, ++ {"ptsname", ptsname}, ++ {"__hybris_set_errno_internal", _hybris_hook_set_errno}, ++ {"getservbyname", getservbyname}, ++ {"scandir", scandir}, ++ {"scandir64", scandir64}, ++ /* libgen.h */ ++ {"basename", _hybris_hook_basename}, ++ {"dirname", _hybris_hook_dirname}, ++ /* locale.h */ ++ {"newlocale", _hybris_hook_newlocale}, ++ {"freelocale", _hybris_hook_freelocale}, ++ {"duplocale", _hybris_hook_duplocale}, ++ {"uselocale", _hybris_hook_uselocale}, ++ {"localeconv", _hybris_hook_localeconv}, ++ {"setlocale", _hybris_hook_setlocale}, ++ /* sys/mman.h */ ++ {"mmap", _hybris_hook_mmap}, ++ {"munmap", _hybris_hook_munmap}, ++ /* wchar.h */ ++ {"wmemchr", wmemchr}, ++ {"wmemcmp", wmemcmp}, ++ {"wmemcpy", wmemcpy}, ++ {"wmemmove", wmemmove}, ++ {"wmemset", wmemset}, ++ {"wmempcpy", wmempcpy}, ++ {"fputws", _hybris_hook_fputws}, ++ // It's enough to hook vfwprintf here as fwprintf will call it with a ++ // proper va_list in place so we don't have to handle this here. ++ {"vfwprintf", _hybris_hook_vfwprintf}, ++ {"fputwc", _hybris_hook_fputwc}, ++ {"putwc", _hybris_hook_putwc}, ++ {"fgetwc", _hybris_hook_fgetwc}, ++ {"getwc", _hybris_hook_getwc}, ++ /* sched.h */ ++ {"clone", clone}, ++ /* mntent.h */ ++ {"setmntent", _hybris_hook_setmntent}, ++ {"getmntent", _hybris_hook_getmntent}, ++ {"getmntent_r", _hybris_hook_getmntent_r}, ++ {"endmntent", _hybris_hook_endmntent}, ++ /* stdlib.h */ ++ {"system", system}, ++ /* pwd.h */ ++ {"getgrnam", getgrnam}, ++ {"getpwuid", getpwuid}, ++ {"getpwnam", getpwnam}, ++ /* signal.h */ ++ /* Hooks commented out for the moment as we need proper translations between ++ * bionic and glibc types for them to work (for instance, sigset_t has ++ * different definitions in each library). ++ */ ++#if 0 ++ {"sigaction", sigaction}, ++ {"sigaddset", sigaddset}, ++ {"sigaltstack", sigaltstack}, ++ {"sigblock", sigblock}, ++ {"sigdelset", sigdelset}, ++ {"sigemptyset", sigemptyset}, ++ {"sigfillset", sigfillset}, ++ {"siginterrupt", siginterrupt}, ++ {"sigismember", sigismember}, ++ {"siglongjmp", siglongjmp}, ++ {"signal", signal}, ++ {"signalfd", signalfd}, ++ {"sigpending", sigpending}, ++ {"sigprocmask", sigprocmask}, ++ {"sigqueue", sigqueue}, ++ // setjmp.h defines segsetjmp via a #define and the real symbol ++ // we have to forward to is __sigsetjmp ++ {"sigsetjmp", __sigsetjmp}, ++ {"sigsetmask", sigsetmask}, ++ {"sigsuspend", sigsuspend}, ++ {"sigtimedwait", sigtimedwait}, ++ {"sigwait", sigwait}, ++ {"sigwaitinfo", sigwaitinfo}, ++#endif ++ /* dirent.h */ ++ {"scandir", _hybris_hook_scandir}, ++ {"scandirat", _hybris_hook_scandirat}, ++ {"alphasort,", _hybris_hook_alphasort}, ++ {"versionsort,", _hybris_hook_versionsort}, ++ {"scandir64", scandir}, + }; + +-void *get_hooked_symbol(char *sym) ++ ++static int hook_cmp(const void *a, const void *b) ++{ ++ return strcmp(((struct _hook*)a)->name, ((struct _hook*)b)->name); ++} ++ ++void hybris_set_hook_callback(hybris_hook_cb callback) ++{ ++ hook_callback = callback; ++} ++ ++static int get_android_sdk_version() + { +- struct _hook *ptr = &hooks[0]; ++ static int sdk_version = -1; ++ ++ if (sdk_version > 0) ++ return sdk_version; ++ ++ char value[PROP_VALUE_MAX]; ++ property_get("ro.build.version.sdk", value, "19"); ++ ++ sdk_version = 19; ++ if (strlen(value) > 0) ++ sdk_version = atoi(value); ++ ++#ifdef UBUNTU_LINKER_OVERRIDES ++ /* We override both frieza and turbo here until they are ready to be ++ * upgraded to the newer linker. */ ++ char device_name[PROP_VALUE_MAX]; ++ memset(device_name, 0, sizeof(device_name)); ++ property_get("ro.build.product", device_name, ""); ++ if (strlen(device_name) > 0) { ++ /* Force SDK version for both frieza/cooler and turbo for the time being */ ++ if (strcmp(device_name, "frieza") == 0 || ++ strcmp(device_name, "cooler") == 0 || ++ strcmp(device_name, "turbo") == 0) ++ sdk_version = 19; ++ } ++#endif ++ ++ char *version_override = getenv("HYBRIS_ANDROID_SDK_VERSION"); ++ if (version_override) ++ sdk_version = atoi(version_override); ++ ++ LOGD("Using SDK API version %i\n", sdk_version); ++ ++ return sdk_version; ++} ++ ++#define HOOKS_SIZE(hooks) \ ++ (sizeof(hooks) / sizeof(hooks[0])) ++ ++ ++static void* __hybris_get_hooked_symbol(const char *sym, const char *requester) ++{ ++ static int sorted = 0; + static int counter = -1; ++ void *found = NULL; ++ struct _hook key; + +- while (ptr->name != NULL) ++ /* First check if we have a callback registered which could ++ * give us a context specific hook implementation */ ++ if (hook_callback) + { +- if (strcmp(sym, ptr->name) == 0){ +- return ptr->func; +- } +- ptr++; ++ found = hook_callback(sym, requester); ++ if (found) ++ return (void*) found; + } +- if (strstr(sym, "pthread") != NULL) ++ ++ if (!sorted) ++ { ++ qsort(hooks_common, HOOKS_SIZE(hooks_common), sizeof(hooks_common[0]), hook_cmp); ++ qsort(hooks_mm, HOOKS_SIZE(hooks_mm), sizeof(hooks_mm[0]), hook_cmp); ++ sorted = 1; ++ } ++ ++ /* Allow newer hooks to override those which are available for all versions */ ++ key.name = sym; ++ if (get_android_sdk_version() > 21) ++ found = bsearch(&key, hooks_mm, HOOKS_SIZE(hooks_mm), sizeof(hooks_mm[0]), hook_cmp); ++ if (!found) ++ found = bsearch(&key, hooks_common, HOOKS_SIZE(hooks_common), sizeof(hooks_common[0]), hook_cmp); ++ ++ if (found) ++ return ((struct _hook*) found)->func; ++ ++ if (strncmp(sym, "pthread", 7) == 0 || ++ strncmp(sym, "__pthread", 9) == 0) + { + /* safe */ + if (strcmp(sym, "pthread_sigmask") == 0) + return NULL; + /* not safe */ + counter--; +- LOGD("%s %i\n", sym, counter); ++ // If you're experiencing a crash later on check the address of the ++ // function pointer being call. If it matches the printed counter ++ // value here then you can easily find out which symbol is missing. ++ LOGD("Missing hook for pthread symbol %s (counter %i)\n", sym, counter); + return (void *) counter; + } ++ ++ if (!getenv("HYBRIS_DONT_PRINT_SYMBOLS_WITHOUT_HOOK")) ++ LOGD("Could not find a hook for symbol %s", sym); ++ + return NULL; + } + +-void android_linker_init() ++static void *linker_handle = NULL; ++ ++static void* __hybris_load_linker(const char *path) ++{ ++ void *handle = dlopen(path, RTLD_NOW | RTLD_LOCAL); ++ if (!handle) { ++ fprintf(stderr, "ERROR: Failed to load hybris linker for Android SDK version %d\n", ++ get_android_sdk_version()); ++ return NULL; ++ } ++ return handle; ++} ++ ++#define LINKER_NAME_JB "jb" ++#define LINKER_NAME_MM "mm" ++ ++#if defined(WANT_LINKER_JB) ++#define LINKER_NAME_DEFAULT LINKER_NAME_JB ++#elif defined(WANT_LINKER_MM) ++#define LINKER_NAME_DEFAULT LINKER_NAME_MM ++#endif ++ ++static int linker_initialized = 0; ++ ++static void __hybris_linker_init() ++{ ++ LOGD("Linker initialization"); ++ ++ int sdk_version = get_android_sdk_version(); ++ ++ char path[PATH_MAX]; ++ const char *name = LINKER_NAME_DEFAULT; ++ ++ /* See https://source.android.com/source/build-numbers.html for ++ * an overview over available SDK version numbers and which ++ * Android version they relate to. */ ++#if defined(WANT_LINKER_MM) ++ if (sdk_version <= 23) ++ name = LINKER_NAME_MM; ++#endif ++#if defined(WANT_LINKER_JB) ++ if (sdk_version < 21) ++ name = LINKER_NAME_JB; ++#endif ++ ++ const char *linker_dir = LINKER_PLUGIN_DIR; ++ const char *user_linker_dir = getenv("HYBRIS_LINKER_DIR"); ++ if (user_linker_dir) ++ linker_dir = user_linker_dir; ++ ++ snprintf(path, PATH_MAX, "%s/%s.so", linker_dir, name); ++ ++ LOGD("Loading linker from %s..", path); ++ ++ linker_handle = __hybris_load_linker(path); ++ if (!linker_handle) ++ exit(1); ++ ++ /* Load all necessary symbols we need from the linker */ ++ _android_linker_init = dlsym(linker_handle, "android_linker_init"); ++ _android_dlopen = dlsym(linker_handle, "android_dlopen"); ++ _android_dlsym = dlsym(linker_handle, "android_dlsym"); ++ _android_dladdr = dlsym(linker_handle, "android_dladdr"); ++ _android_dlclose = dlsym(linker_handle, "android_dlclose"); ++ _android_dlerror = dlsym(linker_handle, "android_dlerror"); ++ ++ /* Now its time to setup the linker itself */ ++ _android_linker_init(sdk_version, __hybris_get_hooked_symbol); ++ ++ linker_initialized = 1; ++} ++ ++#define ENSURE_LINKER_IS_LOADED() \ ++ if (!linker_initialized) \ ++ __hybris_linker_init(); ++ ++/* NOTE: As we're not linking directly with the linker anymore ++ * but several users are using android_* functions directly we ++ * have to export them here. */ ++ ++void *android_dlopen(const char *filename, int flag) ++{ ++ ENSURE_LINKER_IS_LOADED(); ++ ++ if (!_android_dlopen) ++ return NULL; ++ ++ return _android_dlopen(filename,flag); ++} ++ ++void *android_dlsym(void *handle, const char *symbol) ++{ ++ ENSURE_LINKER_IS_LOADED(); ++ ++ if (!_android_dlsym) ++ return NULL; ++ ++ return _android_dlsym(handle,symbol); ++} ++ ++int android_dlclose(void *handle) ++{ ++ ENSURE_LINKER_IS_LOADED(); ++ ++ if (!_android_dlclose) ++ return -1; ++ ++ return _android_dlclose(handle); ++} ++ ++const char *android_dlerror(void) ++{ ++ ENSURE_LINKER_IS_LOADED(); ++ ++ if (!_android_dlerror) ++ return NULL; ++ ++ return _android_dlerror(); ++} ++ ++void *hybris_dlopen(const char *filename, int flag) ++{ ++ return android_dlopen(filename,flag); ++} ++ ++void *hybris_dlsym(void *handle, const char *symbol) ++{ ++ return android_dlsym(handle,symbol); ++} ++ ++int hybris_dlclose(void *handle) ++{ ++ return android_dlclose(handle); ++} ++ ++const char *hybris_dlerror(void) + { ++ return android_dlerror(); + } +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/hooks_shm.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/hooks_shm.c +@@ -123,7 +123,9 @@ static void _hybris_shm_init() + else { + LOGD("Creating a new shared memory segment."); + +- _hybris_shm_fd = shm_open(HYBRIS_SHM_PATH, O_RDWR | O_CREAT, 0660); ++ mode_t pumask = umask(0); ++ _hybris_shm_fd = shm_open(HYBRIS_SHM_PATH, O_RDWR | O_CREAT, 0666); ++ umask(pumask); + if (_hybris_shm_fd >= 0) { + ftruncate( _hybris_shm_fd, size_to_map ); + /* Map the memory object */ +@@ -171,11 +173,12 @@ static void _hybris_shm_extend_region() + + /* + * Determine if the pointer that has been extracted by hybris is +- * pointing to an address in the shared memory ++ * pointing to an address in the shared memory. + */ + int hybris_is_pointer_in_shm(void *ptr) + { +- if ((unsigned int)ptr >= HYBRIS_SHM_MASK) ++ if (((unsigned int) ptr >= HYBRIS_SHM_MASK) && ++ ((unsigned int) ptr <= HYBRIS_SHM_MASK_TOP)) + return 1; + + return 0; +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/hooks_shm.h ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/hooks_shm.h +@@ -20,6 +20,9 @@ + + #include + ++/* Leave space to workaround the issue that Android might pass negative int values */ ++#define HYBRIS_SHM_MASK_TOP 0xFFFFFFF0UL ++ + typedef unsigned int hybris_shm_pointer_t; + + /* +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/jb/Makefile.am ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/jb/Makefile.am +@@ -6,26 +6,28 @@ if WANT_ARCH_X86 + ARCHFLAGS = -DANDROID_X86_LINKER + endif + +-noinst_LTLIBRARIES = \ +- libandroid-linker.la +-libandroid_linker_la_SOURCES = \ ++modlibexecdir = $(libdir)/libhybris/linker ++modlibexec_LTLIBRARIES = jb.la ++jb_la_SOURCES = \ + dlfcn.c \ + linker.c \ + linker_environ.c \ + linker_format.c \ +- rt.c +-libandroid_linker_la_CFLAGS = \ ++ rt.c \ ++ ../strlcpy.c ++jb_la_CFLAGS = \ + -I$(top_srcdir)/include \ + $(ANDROID_HEADERS_CFLAGS) \ + -I$(top_srcdir)/common \ + -D_GNU_SOURCE \ +- -DLINKER_TEXT_BASE=0xB0000100 \ +- -DLINKER_AREA_SIZE=0x01000000 \ + -DDEFAULT_HYBRIS_LD_LIBRARY_PATH="\"@DEFAULT_HYBRIS_LD_LIBRARY_PATH@\"" \ + $(ARCHFLAGS) ++jb_la_LDFLAGS = \ ++ -module \ ++ -avoid-version + + if WANT_DEBUG +-libandroid_linker_la_CFLAGS += -DLINKER_DEBUG=1 ++jb_la_CFLAGS += -DLINKER_DEBUG=1 + else +-libandroid_linker_la_CFLAGS += -DLINKER_DEBUG=0 ++jb_la_CFLAGS += -DLINKER_DEBUG=0 + endif +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/jb/dlfcn.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/jb/dlfcn.c +@@ -78,7 +78,7 @@ const char *android_dlerror(void) + void *android_dlsym(void *handle, const char *symbol) + { + soinfo *found; +- Elf32_Sym *sym; ++ Elf_Sym *sym; + unsigned bind; + + pthread_mutex_lock(&dl_lock); +@@ -142,7 +142,7 @@ int android_dladdr(const void *addr, Dl_ + info->dli_fbase = (void*)si->base; + + /* Determine if any symbol in the library contains the specified address */ +- Elf32_Sym *sym = find_containing_symbol(addr, si); ++ Elf_Sym *sym = find_containing_symbol(addr, si); + + if(sym != NULL) { + info->dli_sname = si->strtab + sym->st_name; +@@ -171,7 +171,7 @@ int android_dl_iterate_phdr(int (*cb)(st + // 0000000 00011111 111112 22222222 2333333 333344444444445555555 + // 0123456 78901234 567890 12345678 9012345 678901234567890123456 + #define ANDROID_LIBDL_STRTAB \ +- "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_unwind_find_exidx\0dl_iterate_phdr\0" ++ "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_iterate_phdr\0dl_unwind_find_exidx\0" + + _Unwind_Ptr android_dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount); + +@@ -191,7 +191,7 @@ _Unwind_Ptr android_dl_unwind_find_exidx + #endif + + +-static Elf32_Sym libdl_symtab[] = { ++static Elf_Sym libdl_symtab[] = { + // total length of libdl_info.strtab, including trailing 0 + // This is actually the the STH_UNDEF entry. Technically, it's + // supposed to have st_name == 0, but instead, it points to an index +@@ -199,44 +199,42 @@ static Elf32_Sym libdl_symtab[] = { + { st_name: sizeof(ANDROID_LIBDL_STRTAB) - 1, + }, + { st_name: 0, // starting index of the name in libdl_info.strtab +- st_value: (Elf32_Addr) &android_dlopen, ++ st_value: (Elf_Addr) &android_dlopen, + st_info: STB_GLOBAL << 4, + st_shndx: 1, + }, + { st_name: 7, +- st_value: (Elf32_Addr) &android_dlclose, ++ st_value: (Elf_Addr) &android_dlclose, + st_info: STB_GLOBAL << 4, + st_shndx: 1, + }, + { st_name: 15, +- st_value: (Elf32_Addr) &android_dlsym, ++ st_value: (Elf_Addr) &android_dlsym, + st_info: STB_GLOBAL << 4, + st_shndx: 1, + }, + { st_name: 21, +- st_value: (Elf32_Addr) &android_dlerror, ++ st_value: (Elf_Addr) &android_dlerror, + st_info: STB_GLOBAL << 4, + st_shndx: 1, + }, + { st_name: 29, +- st_value: (Elf32_Addr) &android_dladdr, ++ st_value: (Elf_Addr) &android_dladdr, + st_info: STB_GLOBAL << 4, + st_shndx: 1, + }, +-#ifdef ANDROID_ARM_LINKER + { st_name: 36, +- st_value: (Elf32_Addr) &android_dl_unwind_find_exidx, ++ st_value: (Elf_Addr) &android_dl_iterate_phdr, + st_info: STB_GLOBAL << 4, + st_shndx: 1, + }, +- { st_name: 57, +-#else +- { st_name: 36, +-#endif +- st_value: (Elf32_Addr) &android_dl_iterate_phdr, ++#ifdef ANDROID_ARM_LINKER ++ { st_name: 52, ++ st_value: (Elf_Addr) &android_dl_unwind_find_exidx, + st_info: STB_GLOBAL << 4, + st_shndx: 1, + }, ++#endif + }; + + /* Fake out a hash table with a single bucket. +@@ -273,12 +271,8 @@ soinfo libdl_info = { + symtab: libdl_symtab, + + refcount: 1, +- nbucket: 1, +-#if defined(ANDROID_ARM_LINKER) +- nchain: 8, +-#else +- nchain: 7, +-#endif ++ nbucket: sizeof(libdl_buckets)/sizeof(unsigned), ++ nchain: sizeof(libdl_chains)/sizeof(unsigned), + bucket: libdl_buckets, + chain: libdl_chains, + }; +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/jb/linker.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/jb/linker.c +@@ -79,6 +79,7 @@ + * having a hard limit (64) + */ + ++static void* (*_get_hooked_symbol)(const char *symbol, const char *requester); + + static int link_image(soinfo *si, unsigned wr_offset); + +@@ -380,10 +381,10 @@ android_dl_iterate_phdr(int (*cb)(struct + return rv; + } + +-static Elf32_Sym *_elf_lookup(soinfo *si, unsigned hash, const char *name) ++static Elf_Sym *_elf_lookup(soinfo *si, unsigned hash, const char *name) + { +- Elf32_Sym *s; +- Elf32_Sym *symtab = si->symtab; ++ Elf_Sym *s; ++ Elf_Sym *symtab = si->symtab; + const char *strtab = si->strtab; + unsigned n; + +@@ -425,11 +426,11 @@ static unsigned elfhash(const char *_nam + return h; + } + +-static Elf32_Sym * ++static Elf_Sym * + _do_lookup(soinfo *si, const char *name, unsigned *base) + { + unsigned elf_hash = elfhash(name); +- Elf32_Sym *s; ++ Elf_Sym *s; + unsigned *d; + soinfo *lsi = si; + int i; +@@ -501,17 +502,17 @@ done: + /* This is used by dl_sym(). It performs symbol lookup only within the + specified soinfo object and not in any of its dependencies. + */ +-Elf32_Sym *lookup_in_library(soinfo *si, const char *name) ++Elf_Sym *lookup_in_library(soinfo *si, const char *name) + { + return _elf_lookup(si, elfhash(name), name); + } + + /* This is used by dl_sym(). It performs a global symbol lookup. + */ +-Elf32_Sym *lookup(const char *name, soinfo **found, soinfo *start) ++Elf_Sym *lookup(const char *name, soinfo **found, soinfo *start) + { + unsigned elf_hash = elfhash(name); +- Elf32_Sym *s = NULL; ++ Elf_Sym *s = NULL; + soinfo *si; + + if(start == NULL) { +@@ -552,7 +553,7 @@ soinfo *find_containing_library(const vo + return NULL; + } + +-Elf32_Sym *find_containing_symbol(const void *addr, soinfo *si) ++Elf_Sym *find_containing_symbol(const void *addr, soinfo *si) + { + unsigned int i; + unsigned soaddr = (unsigned)addr - si->base; +@@ -560,7 +561,7 @@ Elf32_Sym *find_containing_symbol(const + /* Search the library's symbol table for any defined symbol which + * contains this address */ + for(i=0; inchain; i++) { +- Elf32_Sym *sym = &si->symtab[i]; ++ Elf_Sym *sym = &si->symtab[i]; + + if(sym->st_shndx != SHN_UNDEF && + soaddr >= sym->st_value && +@@ -575,7 +576,7 @@ Elf32_Sym *find_containing_symbol(const + #if 0 + static void dump(soinfo *si) + { +- Elf32_Sym *s = si->symtab; ++ Elf_Sym *s = si->symtab; + unsigned n; + + for(n = 0; n < si->nchain; n++) { +@@ -704,7 +705,7 @@ is_prelinked(int fd, const char *name) + static int + verify_elf_object(void *base, const char *name) + { +- Elf32_Ehdr *hdr = (Elf32_Ehdr *) base; ++ Elf_Ehdr *hdr = (Elf_Ehdr *) base; + + if (hdr->e_ident[EI_MAG0] != ELFMAG0) return -1; + if (hdr->e_ident[EI_MAG1] != ELFMAG1) return -1; +@@ -749,8 +750,8 @@ get_lib_extents(int fd, const char *name + unsigned min_vaddr = 0xffffffff; + unsigned max_vaddr = 0; + unsigned char *_hdr = (unsigned char *)__hdr; +- Elf32_Ehdr *ehdr = (Elf32_Ehdr *)_hdr; +- Elf32_Phdr *phdr; ++ Elf_Ehdr *ehdr = (Elf_Ehdr *)_hdr; ++ Elf_Phdr *phdr; + int cnt; + + TRACE("[ %5d Computing extents for '%s'. ]\n", pid, name); +@@ -769,7 +770,7 @@ get_lib_extents(int fd, const char *name + TRACE("[ %5d - Non-prelinked library '%s' found. ]\n", pid, name); + } + +- phdr = (Elf32_Phdr *)(_hdr + ehdr->e_phoff); ++ phdr = (Elf_Phdr *)(_hdr + ehdr->e_phoff); + + /* find the min/max p_vaddrs from all the PT_LOAD segments so we can + * get the range. */ +@@ -884,12 +885,12 @@ err: + static int + load_segments(int fd, void *header, soinfo *si) + { +- Elf32_Ehdr *ehdr = (Elf32_Ehdr *)header; +- Elf32_Phdr *phdr = (Elf32_Phdr *)((unsigned char *)header + ehdr->e_phoff); +- Elf32_Addr base = (Elf32_Addr) si->base; ++ Elf_Ehdr *ehdr = (Elf_Ehdr *)header; ++ Elf_Phdr *phdr = (Elf_Phdr *)((unsigned char *)header + ehdr->e_phoff); ++ Elf_Addr base = (Elf_Addr) si->base; + int cnt; + unsigned len; +- Elf32_Addr tmp; ++ Elf_Addr tmp; + unsigned char *pbase; + unsigned char *extra_base; + unsigned extra_len; +@@ -955,7 +956,7 @@ load_segments(int fd, void *header, soin + * | | + * _+---------------------+ page boundary + */ +- tmp = (Elf32_Addr)(((unsigned)pbase + len + PAGE_SIZE - 1) & ++ tmp = (Elf_Addr)(((unsigned)pbase + len + PAGE_SIZE - 1) & + (~PAGE_MASK)); + if (tmp < (base + phdr->p_vaddr + phdr->p_memsz)) { + extra_len = base + phdr->p_vaddr + phdr->p_memsz - tmp; +@@ -1019,7 +1020,7 @@ load_segments(int fd, void *header, soin + phdr->p_vaddr, phdr->p_memsz); + goto fail; + } +- si->gnu_relro_start = (Elf32_Addr) (base + phdr->p_vaddr); ++ si->gnu_relro_start = (Elf_Addr) (base + phdr->p_vaddr); + si->gnu_relro_len = (unsigned) phdr->p_memsz; + } else { + #ifdef ANDROID_ARM_LINKER +@@ -1066,11 +1067,11 @@ fail: + */ + #if 0 + static unsigned +-get_wr_offset(int fd, const char *name, Elf32_Ehdr *ehdr) ++get_wr_offset(int fd, const char *name, Elf_Ehdr *ehdr) + { +- Elf32_Shdr *shdr_start; +- Elf32_Shdr *shdr; +- int shdr_sz = ehdr->e_shnum * sizeof(Elf32_Shdr); ++ Elf_Shdr *shdr_start; ++ Elf_Shdr *shdr; ++ int shdr_sz = ehdr->e_shnum * sizeof(Elf_Shdr); + int cnt; + unsigned wr_offset = 0xffffffff; + +@@ -1103,7 +1104,7 @@ load_library(const char *name) + unsigned req_base; + const char *bname; + soinfo *si = NULL; +- Elf32_Ehdr *hdr; ++ Elf_Ehdr *hdr; + + if(fd == -1) { + DL_ERR("Library '%s' not found", name); +@@ -1160,8 +1161,8 @@ load_library(const char *name) + + /* this might not be right. Technically, we don't even need this info + * once we go through 'load_segments'. */ +- hdr = (Elf32_Ehdr *)si->base; +- si->phdr = (Elf32_Phdr *)((unsigned char *)si->base + hdr->e_phoff); ++ hdr = (Elf_Ehdr *)si->base; ++ si->phdr = (Elf_Phdr *)((unsigned char *)si->base + hdr->e_phoff); + si->phnum = hdr->e_phnum; + /**/ + +@@ -1260,7 +1261,7 @@ unsigned unload_library(soinfo *si) + * in link_image. This is needed to undo the DT_NEEDED hack below. + */ + if ((si->gnu_relro_start != 0) && (si->gnu_relro_len != 0)) { +- Elf32_Addr start = (si->gnu_relro_start & ~PAGE_MASK); ++ Elf_Addr start = (si->gnu_relro_start & ~PAGE_MASK); + unsigned len = (si->gnu_relro_start - start) + si->gnu_relro_len; + if (mprotect((void *) start, len, PROT_READ | PROT_WRITE) < 0) + DL_ERR("%5d %s: could not undo GNU_RELRO protections. " +@@ -1303,16 +1304,16 @@ unsigned unload_library(soinfo *si) + } + + /* TODO: don't use unsigned for addrs below. It works, but is not +- * ideal. They should probably be either uint32_t, Elf32_Addr, or unsigned ++ * ideal. They should probably be either uint32_t, Elf_Addr, or unsigned + * long. + */ +-static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count) ++static int reloc_library(soinfo *si, Elf_Rel *rel, unsigned count) + { +- Elf32_Sym *symtab = si->symtab; ++ Elf_Sym *symtab = si->symtab; + const char *strtab = si->strtab; +- Elf32_Sym *s; ++ Elf_Sym *s; + unsigned base; +- Elf32_Rel *start = rel; ++ Elf_Rel *start = rel; + unsigned idx; + + for (idx = 0; idx < count; ++idx) { +@@ -1327,7 +1328,7 @@ static int reloc_library(soinfo *si, Elf + if(sym != 0) { + sym_name = (char *)(strtab + symtab[sym].st_name); + INFO("HYBRIS: '%s' checking hooks for sym '%s'\n", si->name, sym_name); +- sym_addr = get_hooked_symbol(sym_name); ++ sym_addr = _get_hooked_symbol(sym_name, si->name); + if (sym_addr != NULL) { + INFO("HYBRIS: '%s' hooked symbol %s to %x\n", si->name, + sym_name, sym_addr); +@@ -1711,7 +1712,7 @@ static int nullify_closed_stdio (void) + static int link_image(soinfo *si, unsigned wr_offset) + { + unsigned *d; +- Elf32_Phdr *phdr = si->phdr; ++ Elf_Phdr *phdr = si->phdr; + int phnum = si->phnum; + + INFO("[ %5d linking %s ]\n", pid, si->name); +@@ -1794,7 +1795,7 @@ static int link_image(soinfo *si, unsign + phdr->p_vaddr, phdr->p_memsz); + goto fail; + } - si->gnu_relro_start = (Elf32_Addr) (si->base + phdr->p_vaddr); + si->gnu_relro_start = (Elf_Addr) (si->base + phdr->p_vaddr); si->gnu_relro_len = (unsigned) phdr->p_memsz; } } -@@ -1822,7 +1822,7 @@ static int link_image(soinfo *si, unsign +@@ -1821,7 +1822,7 @@ static int link_image(soinfo *si, unsign si->strtab = (const char *) (si->base + *d); break; case DT_SYMTAB: @@ -9683,7 +14316,7 @@ break; case DT_PLTREL: if(*d != DT_REL) { -@@ -1831,13 +1831,13 @@ static int link_image(soinfo *si, unsign +@@ -1830,13 +1831,13 @@ static int link_image(soinfo *si, unsign } break; case DT_JMPREL: @@ -9699,7 +14332,7 @@ break; case DT_RELSZ: si->rel_count = *d / 8; -@@ -1869,7 +1869,7 @@ static int link_image(soinfo *si, unsign +@@ -1868,7 +1869,7 @@ static int link_image(soinfo *si, unsign pid, si->name, si->init_array); break; case DT_INIT_ARRAYSZ: @@ -9708,7 +14341,7 @@ break; case DT_FINI_ARRAY: si->fini_array = (unsigned *)(si->base + *d); -@@ -1877,7 +1877,7 @@ static int link_image(soinfo *si, unsign +@@ -1876,7 +1877,7 @@ static int link_image(soinfo *si, unsign pid, si->name, si->fini_array); break; case DT_FINI_ARRAYSZ: @@ -9717,7 +14350,7 @@ break; case DT_PREINIT_ARRAY: si->preinit_array = (unsigned *)(si->base + *d); -@@ -1885,7 +1885,7 @@ static int link_image(soinfo *si, unsign +@@ -1884,7 +1885,7 @@ static int link_image(soinfo *si, unsign pid, si->name, si->preinit_array); break; case DT_PREINIT_ARRAYSZ: @@ -9726,7 +14359,7 @@ break; case DT_TEXTREL: /* TODO: make use of this. */ -@@ -1987,7 +1987,7 @@ static int link_image(soinfo *si, unsign +@@ -1986,7 +1987,7 @@ static int link_image(soinfo *si, unsign #endif if (si->gnu_relro_start != 0 && si->gnu_relro_len != 0) { @@ -9735,7 +14368,7 @@ unsigned len = (si->gnu_relro_start - start) + si->gnu_relro_len; if (mprotect((void *) start, len, PROT_READ) < 0) { DL_ERR("%5d GNU_RELRO mprotect of library '%s' failed: %d (%s)\n", -@@ -2170,7 +2170,7 @@ sanitize: +@@ -2169,7 +2170,7 @@ sanitize: while(vecs[0] != 0){ switch(vecs[0]){ case AT_PHDR: @@ -9744,7 +14377,7 @@ break; case AT_PHNUM: si->phnum = (int) vecs[1]; -@@ -2190,7 +2190,7 @@ sanitize: +@@ -2189,7 +2190,7 @@ sanitize: si->base = 0; for ( nn = 0; nn < si->phnum; nn++ ) { if (si->phdr[nn].p_type == PT_PHDR) { @@ -9753,7 +14386,7 @@ break; } } -@@ -2303,9 +2303,9 @@ static unsigned find_linker_base(unsigne +@@ -2302,9 +2303,9 @@ static unsigned find_linker_base(unsigne */ unsigned __linker_init(unsigned **elfdata) { unsigned linker_addr = find_linker_base(elfdata); @@ -9764,510 +14397,9566 @@ + Elf_Phdr *phdr = + (Elf_Phdr *)((unsigned char *) linker_addr + elf_hdr->e_phoff); - soinfo linker_so; - memset(&linker_so, 0, sizeof(soinfo)); ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/common/jb/linker.h -+++ libhybris-0.1.0+git20131207+e452e83/hybris/common/jb/linker.h -@@ -38,6 +38,26 @@ - #define PAGE_SIZE 4096 - #define PAGE_MASK 4095 + soinfo linker_so; + memset(&linker_so, 0, sizeof(soinfo)); +@@ -2333,3 +2334,8 @@ unsigned __linker_init(unsigned **elfdat + // the main part of the linker now. + return __linker_init_post_relocation(elfdata); + } ++ ++void android_linker_init(int sdk_version, void *(get_hooked_symbol)(const char*, const char*)) { ++ (void) sdk_version; ++ _get_hooked_symbol = get_hooked_symbol; ++} +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/jb/linker.h ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/jb/linker.h +@@ -38,6 +38,26 @@ + #define PAGE_SIZE 4096 + #define PAGE_MASK 4095 + ++#if defined(__x86_64__) ++typedef Elf64_Ehdr Elf_Ehdr; ++typedef Elf64_Shdr Elf_Shdr; ++typedef Elf64_Sym Elf_Sym; ++typedef Elf64_Addr Elf_Addr; ++typedef Elf64_Phdr Elf_Phdr; ++typedef Elf64_Half Elf_Half; ++typedef Elf64_Rel Elf_Rel; ++typedef Elf64_Rela Elf_Rela; ++#else ++typedef Elf32_Ehdr Elf_Ehdr; ++typedef Elf32_Shdr Elf_Shdr; ++typedef Elf32_Sym Elf_Sym; ++typedef Elf32_Addr Elf_Addr; ++typedef Elf32_Phdr Elf_Phdr; ++typedef Elf32_Half Elf_Half; ++typedef Elf32_Rel Elf_Rel; ++typedef Elf32_Rela Elf_Rela; ++#endif ++ + void debugger_init(); + const char *addr_to_name(unsigned addr); + +@@ -55,10 +75,10 @@ struct link_map + /* needed for dl_iterate_phdr to be passed to the callbacks provided */ + struct dl_phdr_info + { +- Elf32_Addr dlpi_addr; ++ Elf_Addr dlpi_addr; + const char *dlpi_name; +- const Elf32_Phdr *dlpi_phdr; +- Elf32_Half dlpi_phnum; ++ const Elf_Phdr *dlpi_phdr; ++ Elf_Half dlpi_phnum; + }; + + +@@ -90,7 +110,7 @@ typedef struct soinfo soinfo; + struct soinfo + { + const char name[SOINFO_NAME_LEN]; +- Elf32_Phdr *phdr; ++ Elf_Phdr *phdr; + int phnum; + unsigned entry; + unsigned base; +@@ -107,7 +127,7 @@ struct soinfo + unsigned flags; + + const char *strtab; +- Elf32_Sym *symtab; ++ Elf_Sym *symtab; + + unsigned nbucket; + unsigned nchain; +@@ -116,10 +136,10 @@ struct soinfo + + unsigned *plt_got; + +- Elf32_Rel *plt_rel; ++ Elf_Rel *plt_rel; + unsigned plt_rel_count; + +- Elf32_Rel *rel; ++ Elf_Rel *rel; + unsigned rel_count; + + unsigned *preinit_array; +@@ -144,7 +164,7 @@ struct soinfo + + int constructors_called; + +- Elf32_Addr gnu_relro_start; ++ Elf_Addr gnu_relro_start; + unsigned gnu_relro_len; + + }; +@@ -202,18 +222,17 @@ extern soinfo libdl_info; + + soinfo *find_library(const char *name); + unsigned unload_library(soinfo *si); +-Elf32_Sym *lookup_in_library(soinfo *si, const char *name); +-Elf32_Sym *lookup(const char *name, soinfo **found, soinfo *start); ++Elf_Sym *lookup_in_library(soinfo *si, const char *name); ++Elf_Sym *lookup(const char *name, soinfo **found, soinfo *start); + soinfo *find_containing_library(const void *addr); +-Elf32_Sym *find_containing_symbol(const void *addr, soinfo *si); ++Elf_Sym *find_containing_symbol(const void *addr, soinfo *si); + const char *linker_get_error(void); + void call_constructors_recursive(soinfo *si); + ++int dl_iterate_phdr(int (*cb)(struct dl_phdr_info *, size_t, void *), void *); + #ifdef ANDROID_ARM_LINKER + typedef long unsigned int *_Unwind_Ptr; + _Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount); +-#elif defined(ANDROID_X86_LINKER) +-int dl_iterate_phdr(int (*cb)(struct dl_phdr_info *, size_t, void *), void *); + #endif + + #endif +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/jb/linker_format.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/jb/linker_format.c +@@ -268,7 +268,7 @@ static int log_vprint(int prio, const ch + result = vformat_buffer(buf, sizeof buf, fmt, args); + if (log_fd < 0) { +- log_fd = open("/dev/log/main", O_WRONLY); ++ log_fd = open("/dev/alog/main", O_WRONLY); + if (log_fd < 0) { + log_fd = fileno(stdout); // kernel doesn't have android log + return result; +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/Makefile.am +@@ -0,0 +1,50 @@ ++bionic = $(top_srcdir)/common/mm/bionic ++bionic_libc = $(bionic)/libc ++ ++modlibexecdir = $(libdir)/libhybris/linker ++modlibexec_LTLIBRARIES = mm.la ++ ++ARCH_FLAGS = ++ ++AM_CFLAGS = \ ++ -std=gnu99 ++ ++AM_CPPFLAGS = \ ++ -std=gnu++11 \ ++ -Wold-style-cast \ ++ -fno-stack-protector \ ++ -Wstrict-overflow=5 ++ ++mm_la_SOURCES = \ ++ hybris_compat.cpp \ ++ dlfcn.cpp \ ++ linker_allocator.cpp \ ++ linker_block_allocator.cpp \ ++ linker.cpp \ ++ linker_memory.cpp \ ++ linker_phdr.cpp \ ++ linker_sdk_versions.cpp \ ++ rt.cpp \ ++ ../strlcpy.c \ ++ ../strlcat.c ++mm_la_CPPFLAGS = \ ++ $(AM_CPPFLAGS) \ ++ -I$(top_srcdir)/include \ ++ -I$(top_srcdir)/common \ ++ -I$(bionic_libc)/ \ ++ -I$(bionic_libc)/include \ ++ -DDEFAULT_HYBRIS_LD_LIBRARY_PATH="\"@DEFAULT_HYBRIS_LD_LIBRARY_PATH@\"" \ ++ $(ARCH_FLAGS) \ ++ $(ANDROID_HEADERS_CFLAGS) ++mm_la_LDFLAGS = \ ++ -lsupc++ \ ++ -module \ ++ -avoid-version ++ ++if WANT_DEBUG ++mm_la_CPPFLAGS += \ ++ -DTRACE_DEBUG=1 ++else ++mm_la_CPPFLAGS += \ ++ -DTRACE_DEBUG=1 ++endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/NOTICE +@@ -0,0 +1,204 @@ ++Copyright (C) 2007 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. ++ ++------------------------------------------------------------------- ++ ++Copyright (C) 2008 The Android Open Source Project ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions ++are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in ++ the documentation and/or other materials provided with the ++ distribution. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++SUCH DAMAGE. ++ ++------------------------------------------------------------------- ++ ++Copyright (C) 2010 The Android Open Source Project ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions ++are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in ++ the documentation and/or other materials provided with the ++ distribution. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++SUCH DAMAGE. ++ ++------------------------------------------------------------------- ++ ++Copyright (C) 2012 The Android Open Source Project ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions ++are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in ++ the documentation and/or other materials provided with the ++ distribution. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++SUCH DAMAGE. ++ ++------------------------------------------------------------------- ++ ++Copyright (C) 2013 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. ++ ++------------------------------------------------------------------- ++ ++Copyright (C) 2013 The Android Open Source Project ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions ++are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in ++ the documentation and/or other materials provided with the ++ distribution. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++SUCH DAMAGE. ++ ++------------------------------------------------------------------- ++ ++Copyright (C) 2014 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. ++ ++------------------------------------------------------------------- ++ ++Copyright (C) 2015 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. ++ ++------------------------------------------------------------------- ++ ++Copyright (C) 2015 The Android Open Source Project ++All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions ++are met: ++ * Redistributions of source code must retain the above copyright ++ notice, this list of conditions and the following disclaimer. ++ * Redistributions in binary form must reproduce the above copyright ++ notice, this list of conditions and the following disclaimer in ++ the documentation and/or other materials provided with the ++ distribution. ++ ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++SUCH DAMAGE. ++ ++------------------------------------------------------------------- ++ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/bionic/pthread_internal.h +@@ -0,0 +1,141 @@ ++/* ++ * Copyright (C) 2008 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++#ifndef _PTHREAD_INTERNAL_H_ ++#define _PTHREAD_INTERNAL_H_ ++ ++#include ++#include ++ ++#include "private/bionic_tls.h" ++ ++/* Has the thread been detached by a pthread_join or pthread_detach call? */ ++#define PTHREAD_ATTR_FLAG_DETACHED 0x00000001 ++ ++/* Has the thread been joined by another thread? */ ++#define PTHREAD_ATTR_FLAG_JOINED 0x00000002 ++ ++struct pthread_key_data_t { ++ uintptr_t seq; // Use uintptr_t just for alignment, as we use pointer below. ++ void* data; ++}; ++ ++enum ThreadJoinState { ++ THREAD_NOT_JOINED, ++ THREAD_EXITED_NOT_JOINED, ++ THREAD_JOINED, ++ THREAD_DETACHED ++}; ++ ++struct pthread_internal_t { ++ struct pthread_internal_t* next; ++ struct pthread_internal_t* prev; ++ ++ pid_t tid; ++ ++ private: ++ pid_t cached_pid_; ++ ++ public: ++ pid_t invalidate_cached_pid() { ++ pid_t old_value; ++ get_cached_pid(&old_value); ++ set_cached_pid(0); ++ return old_value; ++ } ++ ++ void set_cached_pid(pid_t value) { ++ cached_pid_ = value; ++ } ++ ++ bool get_cached_pid(pid_t* cached_pid) { ++ *cached_pid = cached_pid_; ++ return (*cached_pid != 0); ++ } ++ ++ pthread_attr_t attr; ++ ++ ThreadJoinState join_state; ++ ++ //__pthread_cleanup_t* cleanup_stack; ++ ++ void* (*start_routine)(void*); ++ void* start_routine_arg; ++ void* return_value; ++ ++ void* alternate_signal_stack; ++ ++ pthread_mutex_t startup_handshake_mutex; ++ ++ size_t mmap_size; ++ ++ void* tls[BIONIC_TLS_SLOTS]; ++ ++ pthread_key_data_t key_data[BIONIC_PTHREAD_KEY_COUNT]; ++ ++ /* ++ * The dynamic linker implements dlerror(3), which makes it hard for us to implement this ++ * per-thread buffer by simply using malloc(3) and free(3). ++ */ ++#define __BIONIC_DLERROR_BUFFER_SIZE 512 ++ char dlerror_buffer[__BIONIC_DLERROR_BUFFER_SIZE]; ++}; ++ ++ int __init_thread(pthread_internal_t* thread); ++ void __init_tls(pthread_internal_t* thread); ++ void __init_alternate_signal_stack(pthread_internal_t*); ++ ++ pthread_t __pthread_internal_add(pthread_internal_t* thread); ++ pthread_internal_t* __pthread_internal_find(pthread_t pthread_id); ++ void __pthread_internal_remove(pthread_internal_t* thread); ++ void __pthread_internal_remove_and_free(pthread_internal_t* thread); ++ ++// Make __get_thread() inlined for performance reason. See http://b/19825434. ++static inline pthread_internal_t* __get_thread() { ++ return reinterpret_cast(__get_tls()[TLS_SLOT_THREAD_ID]); ++} ++ ++ void pthread_key_clean_all(void); ++ ++/* ++ * Traditionally we gave threads a 1MiB stack. When we started ++ * allocating per-thread alternate signal stacks to ease debugging of ++ * stack overflows, we subtracted the same amount we were using there ++ * from the default thread stack size. This should keep memory usage ++ * roughly constant. ++ */ ++#define PTHREAD_STACK_SIZE_DEFAULT ((1 * 1024 * 1024) - SIGSTKSZ) ++ ++/* Leave room for a guard page in the internally created signal stacks. */ ++#define SIGNAL_STACK_SIZE (SIGSTKSZ + PAGE_SIZE) ++ ++/* Needed by fork. */ ++ extern void __bionic_atfork_run_prepare(); ++ extern void __bionic_atfork_run_child(); ++ extern void __bionic_atfork_run_parent(); ++ ++#endif /* _PTHREAD_INTERNAL_H_ */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/include/android/api-level.h +@@ -0,0 +1,38 @@ ++/* ++ * Copyright (C) 2008 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++#ifndef ANDROID_API_LEVEL_H ++#define ANDROID_API_LEVEL_H ++ ++/* ++ * Magic version number for a current development build, which has ++ * not yet turned into an official release. ++ */ ++#define __ANDROID_API__ 10000 ++ ++#endif /* ANDROID_API_LEVEL_H */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/include/android/dlext.h +@@ -0,0 +1,107 @@ ++/* ++ * Copyright (C) 2014 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_DLEXT_H__ ++#define __ANDROID_DLEXT_H__ ++ ++#include ++#include ++#include ++#include /* for off64_t */ ++ ++__BEGIN_DECLS ++ ++/* bitfield definitions for android_dlextinfo.flags */ ++enum { ++ /* When set, the reserved_addr and reserved_size fields must point to an ++ * already-reserved region of address space which will be used to load the ++ * library if it fits. If the reserved region is not large enough, the load ++ * will fail. ++ */ ++ ANDROID_DLEXT_RESERVED_ADDRESS = 0x1, ++ ++ /* As DLEXT_RESERVED_ADDRESS, but if the reserved region is not large enough, ++ * the linker will choose an available address instead. ++ */ ++ ANDROID_DLEXT_RESERVED_ADDRESS_HINT = 0x2, ++ ++ /* When set, write the GNU RELRO section of the mapped library to relro_fd ++ * after relocation has been performed, to allow it to be reused by another ++ * process loading the same library at the same address. This implies ++ * ANDROID_DLEXT_USE_RELRO. ++ */ ++ ANDROID_DLEXT_WRITE_RELRO = 0x4, ++ ++ /* When set, compare the GNU RELRO section of the mapped library to relro_fd ++ * after relocation has been performed, and replace any relocated pages that ++ * are identical with a version mapped from the file. ++ */ ++ ANDROID_DLEXT_USE_RELRO = 0x8, ++ ++ /* Instruct dlopen to use library_fd instead of opening file by name. ++ * The filename parameter is still used to identify the library. ++ */ ++ ANDROID_DLEXT_USE_LIBRARY_FD = 0x10, ++ ++ /* If opening a library using library_fd read it starting at library_fd_offset. ++ * This flag is only valid when ANDROID_DLEXT_USE_LIBRARY_FD is set. ++ */ ++ ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET = 0x20, ++ ++ /* When set, do not check if the library has already been loaded by file stat(2)s. ++ * ++ * This flag allows forced loading of the library in the case when for some ++ * reason multiple ELF files share the same filename (because the already-loaded ++ * library has been removed and overwritten, for example). ++ * ++ * Note that if the library has the same dt_soname as an old one and some other ++ * library has the soname in DT_NEEDED list, the first one will be used to resolve any ++ * dependencies. ++ */ ++ ANDROID_DLEXT_FORCE_LOAD = 0x40, ++ ++ /* When set, if the minimum p_vaddr of the ELF file's PT_LOAD segments is non-zero, ++ * the dynamic linker will load it at that address. ++ * ++ * This flag is for ART internal use only. ++ */ ++ ANDROID_DLEXT_FORCE_FIXED_VADDR = 0x80, ++ ++ /* Mask of valid bits */ ++ ANDROID_DLEXT_VALID_FLAG_BITS = ANDROID_DLEXT_RESERVED_ADDRESS | ++ ANDROID_DLEXT_RESERVED_ADDRESS_HINT | ++ ANDROID_DLEXT_WRITE_RELRO | ++ ANDROID_DLEXT_USE_RELRO | ++ ANDROID_DLEXT_USE_LIBRARY_FD | ++ ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET | ++ ANDROID_DLEXT_FORCE_LOAD | ++ ANDROID_DLEXT_FORCE_FIXED_VADDR, ++}; ++ ++typedef struct { ++ uint64_t flags; ++ void* reserved_addr; ++ size_t reserved_size; ++ int relro_fd; ++ int library_fd; ++ off64_t library_fd_offset; ++} android_dlextinfo; ++ ++extern void* android_dlopen_ext(const char* filename, int flag, const android_dlextinfo* extinfo); ++ ++__END_DECLS ++ ++#endif /* __ANDROID_DLEXT_H__ */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/include/link.h +@@ -0,0 +1,80 @@ ++/* ++ * Copyright (C) 2012 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++#ifndef _LINK_H_ ++#define _LINK_H_ ++ ++#include ++#include ++ ++__BEGIN_DECLS ++ ++#if __LP64__ ++#define ElfW(type) Elf64_ ## type ++#else ++#define ElfW(type) Elf32_ ## type ++#endif ++ ++struct dl_phdr_info { ++ ElfW(Addr) dlpi_addr; ++ const char* dlpi_name; ++ const ElfW(Phdr)* dlpi_phdr; ++ ElfW(Half) dlpi_phnum; ++}; ++ ++int dl_iterate_phdr(int (*)(struct dl_phdr_info*, size_t, void*), void*); ++ ++#ifdef __arm__ ++typedef long unsigned int* _Unwind_Ptr; ++_Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr, int*); ++#endif ++ ++/* Used by the dynamic linker to communicate with the debugger. */ ++struct link_map { ++ ElfW(Addr) l_addr; ++ char* l_name; ++ ElfW(Dyn)* l_ld; ++ struct link_map* l_next; ++ struct link_map* l_prev; ++}; ++ ++/* Used by the dynamic linker to communicate with the debugger. */ ++struct r_debug { ++ int32_t r_version; ++ struct link_map* r_map; ++ ElfW(Addr) r_brk; ++ enum { ++ RT_CONSISTENT, ++ RT_ADD, ++ RT_DELETE ++ } r_state; ++ ElfW(Addr) r_ldbase; ++}; ++ ++__END_DECLS ++ ++#endif /* _LINK_H_ */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/ErrnoRestorer.h +@@ -0,0 +1,43 @@ ++/* ++ * Copyright (C) 2013 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 ERRNO_RESTORER_H ++#define ERRNO_RESTORER_H ++ ++#include ++ ++#include "bionic_macros.h" ++ ++class ErrnoRestorer { ++ public: ++ explicit ErrnoRestorer() : saved_errno_(errno) { ++ } ++ ++ ~ErrnoRestorer() { ++ errno = saved_errno_; ++ } ++ ++ void override(int new_errno) { ++ saved_errno_ = new_errno; ++ } ++ ++ private: ++ int saved_errno_; ++ ++ DISALLOW_COPY_AND_ASSIGN(ErrnoRestorer); ++}; ++ ++#endif // ERRNO_RESTORER_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/KernelArgumentBlock.h +@@ -0,0 +1,81 @@ ++/* ++ * Copyright (C) 2013 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 KERNEL_ARGUMENT_BLOCK_H ++#define KERNEL_ARGUMENT_BLOCK_H ++ ++#include ++#include ++#include ++#include ++ ++#include "private/bionic_macros.h" ++ ++struct abort_msg_t; ++ ++// When the kernel starts the dynamic linker, it passes a pointer to a block ++// of memory containing argc, the argv array, the environment variable array, ++// and the array of ELF aux vectors. This class breaks that block up into its ++// constituents for easy access. ++class KernelArgumentBlock { ++ public: ++ KernelArgumentBlock(void* raw_args) { ++ uintptr_t* args = reinterpret_cast(raw_args); ++ argc = static_cast(*args); ++ argv = reinterpret_cast(args + 1); ++ envp = argv + argc + 1; ++ ++ // Skip over all environment variable definitions to find aux vector. ++ // The end of the environment block is marked by two NULL pointers. ++ char** p = envp; ++ while (*p != NULL) { ++ ++p; ++ } ++ ++p; // Skip second NULL; ++ ++ auxv = reinterpret_cast(p); ++ } ++ ++ // Similar to ::getauxval but doesn't require the libc global variables to be set up, ++ // so it's safe to call this really early on. This function also lets you distinguish ++ // between the inability to find the given type and its value just happening to be 0. ++ unsigned long getauxval(unsigned long type, bool* found_match = NULL) { ++ for (ElfW(auxv_t)* v = auxv; v->a_type != AT_NULL; ++v) { ++ if (v->a_type == type) { ++ if (found_match != NULL) { ++ *found_match = true; ++ } ++ return v->a_un.a_val; ++ } ++ } ++ if (found_match != NULL) { ++ *found_match = false; ++ } ++ return 0; ++ } ++ ++ int argc; ++ char** argv; ++ char** envp; ++ ElfW(auxv_t)* auxv; ++ ++ abort_msg_t** abort_message_ptr; ++ ++ private: ++ DISALLOW_COPY_AND_ASSIGN(KernelArgumentBlock); ++}; ++ ++#endif // KERNEL_ARGUMENT_BLOCK_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/NetdClientDispatch.h +@@ -0,0 +1,36 @@ ++/* ++ * Copyright (C) 2014 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 PRIVATE_NETD_CLIENT_DISPATCH_H ++#define PRIVATE_NETD_CLIENT_DISPATCH_H ++ ++#include ++#include ++ ++__BEGIN_DECLS ++ ++struct NetdClientDispatch { ++ int (*accept4)(int, struct sockaddr*, socklen_t*, int); ++ int (*connect)(int, const struct sockaddr*, socklen_t); ++ int (*socket)(int, int, int); ++ unsigned (*netIdForResolv)(unsigned); ++}; ++ ++extern struct NetdClientDispatch __netdClientDispatch; ++ ++__END_DECLS ++ ++#endif // PRIVATE_NETD_CLIENT_DISPATCH_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/ScopeGuard.h +@@ -0,0 +1,53 @@ ++/* ++ * Copyright (C) 2014 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 _SCOPE_GUARD_H ++#define _SCOPE_GUARD_H ++ ++#include "private/bionic_macros.h" ++ ++// TODO: include explicit std::move when it becomes available ++template ++class ScopeGuard { ++ public: ++ ScopeGuard(F f) : f_(f), active_(true) {} ++ ++ ScopeGuard(ScopeGuard&& that) : f_(that.f_), active_(that.active_) { ++ that.active_ = false; ++ } ++ ++ ~ScopeGuard() { ++ if (active_) { ++ f_(); ++ } ++ } ++ ++ void disable() { ++ active_ = false; ++ } ++ private: ++ F f_; ++ bool active_; ++ ++ DISALLOW_IMPLICIT_CONSTRUCTORS(ScopeGuard); ++}; ++ ++template ++ScopeGuard make_scope_guard(T f) { ++ return ScopeGuard(f); ++} ++ ++#endif // _SCOPE_GUARD_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/ScopedPthreadMutexLocker.h +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (C) 2012 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 SCOPED_PTHREAD_MUTEX_LOCKER_H ++#define SCOPED_PTHREAD_MUTEX_LOCKER_H ++ ++#include ++ ++#include "bionic_macros.h" ++ ++class ScopedPthreadMutexLocker { ++ public: ++ explicit ScopedPthreadMutexLocker(pthread_mutex_t* mu) : mu_(mu) { ++ pthread_mutex_lock(mu_); ++ } ++ ++ ~ScopedPthreadMutexLocker() { ++ pthread_mutex_unlock(mu_); ++ } ++ ++ private: ++ pthread_mutex_t* mu_; ++ ++ DISALLOW_COPY_AND_ASSIGN(ScopedPthreadMutexLocker); ++}; ++ ++#endif // SCOPED_PTHREAD_MUTEX_LOCKER_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/ScopedReaddir.h +@@ -0,0 +1,50 @@ ++/* ++ * Copyright (C) 2013 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 SCOPED_READDIR_H ++#define SCOPED_READDIR_H ++ ++#include ++ ++#include "private/bionic_macros.h" ++ ++class ScopedReaddir { ++ public: ++ ScopedReaddir(const char* path) { ++ dir_ = opendir(path); ++ } ++ ++ ~ScopedReaddir() { ++ if (dir_ != NULL) { ++ closedir(dir_); ++ } ++ } ++ ++ bool IsBad() { ++ return dir_ == NULL; ++ } ++ ++ dirent* ReadEntry() { ++ return readdir(dir_); ++ } ++ ++ private: ++ DIR* dir_; ++ ++ DISALLOW_COPY_AND_ASSIGN(ScopedReaddir); ++}; ++ ++#endif // SCOPED_READDIR_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/ThreadLocalBuffer.h +@@ -0,0 +1,61 @@ ++/* ++ * Copyright (C) 2012 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++#ifndef _BIONIC_THREAD_LOCAL_BUFFER_H_included ++#define _BIONIC_THREAD_LOCAL_BUFFER_H_included ++ ++#include ++#include ++ ++// TODO: use __thread instead? ++ ++template ++class ThreadLocalBuffer { ++ public: ++ ThreadLocalBuffer() { ++ // We used to use pthread_once to initialize the keys, but life is more predictable ++ // if we allocate them all up front when the C library starts up, via __constructor__. ++ pthread_key_create(&key_, free); ++ } ++ ++ T* get() { ++ T* result = reinterpret_cast(pthread_getspecific(key_)); ++ if (result == nullptr) { ++ result = reinterpret_cast(calloc(1, Size)); ++ pthread_setspecific(key_, result); ++ } ++ return result; ++ } ++ ++ size_t size() { return Size; } ++ ++ private: ++ pthread_key_t key_; ++}; ++ ++#endif // _BIONIC_THREAD_LOCAL_BUFFER_H_included +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/UniquePtr.h +@@ -0,0 +1,140 @@ ++/* ++ * 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. ++ * 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 UNIQUE_PTR_H_included ++#define UNIQUE_PTR_H_included ++ ++// Default deleter for pointer types. ++template ++struct DefaultDelete { ++ enum { type_must_be_complete = sizeof(T) }; ++ DefaultDelete() {} ++ void operator()(T* p) const { ++ delete p; ++ } ++}; ++ ++// Default deleter for array types. ++template ++struct DefaultDelete { ++ enum { type_must_be_complete = sizeof(T) }; ++ void operator()(T* p) const { ++ delete[] p; ++ } ++}; ++ ++// A smart pointer that deletes the given pointer on destruction. ++// Equivalent to C++0x's std::unique_ptr (a combination of boost::scoped_ptr ++// and boost::scoped_array). ++// Named to be in keeping with Android style but also to avoid ++// collision with any other implementation, until we can switch over ++// to unique_ptr. ++// Use thus: ++// UniquePtr c(new C); ++template > ++class UniquePtr { ++public: ++ // Construct a new UniquePtr, taking ownership of the given raw pointer. ++ explicit UniquePtr(T* ptr = nullptr) : mPtr(ptr) { } ++ ++ UniquePtr(UniquePtr&& that) { ++ mPtr = that.mPtr; ++ that.mPtr = nullptr; ++ } ++ ++ ~UniquePtr() { ++ reset(); ++ } ++ ++ // Accessors. ++ T& operator*() const { return *mPtr; } ++ T* operator->() const { return mPtr; } ++ T* get() const { return mPtr; } ++ ++ // Returns the raw pointer and hands over ownership to the caller. ++ // The pointer will not be deleted by UniquePtr. ++ T* release() __attribute__((warn_unused_result)) { ++ T* result = mPtr; ++ mPtr = nullptr; ++ return result; ++ } ++ ++ // Takes ownership of the given raw pointer. ++ // If this smart pointer previously owned a different raw pointer, that ++ // raw pointer will be freed. ++ void reset(T* ptr = nullptr) { ++ if (ptr != mPtr) { ++ D()(mPtr); ++ mPtr = ptr; ++ } ++ } ++ ++private: ++ // The raw pointer. ++ T* mPtr; ++ ++ // Comparing unique pointers is probably a mistake, since they're unique. ++ template bool operator==(const UniquePtr& p) const = delete; ++ template bool operator!=(const UniquePtr& p) const = delete; ++ ++ // Disallow copy and assignment. ++ UniquePtr(const UniquePtr&) = delete; ++ void operator=(const UniquePtr&) = delete; ++}; ++ ++// Partial specialization for array types. Like std::unique_ptr, this removes ++// operator* and operator-> but adds operator[]. ++template ++class UniquePtr { ++public: ++ explicit UniquePtr(T* ptr = NULL) : mPtr(ptr) { ++ } ++ UniquePtr(UniquePtr&& that) { ++ mPtr = that.mPtr; ++ that.mPtr = nullptr; ++ } ++ ++ ~UniquePtr() { ++ reset(); ++ } ++ ++ T& operator[](size_t i) const { ++ return mPtr[i]; ++ } ++ T* get() const { return mPtr; } ++ ++ T* release() __attribute__((warn_unused_result)) { ++ T* result = mPtr; ++ mPtr = NULL; ++ return result; ++ } ++ ++ void reset(T* ptr = NULL) { ++ if (ptr != mPtr) { ++ D()(mPtr); ++ mPtr = ptr; ++ } ++ } ++ ++private: ++ T* mPtr; ++ ++ // Disallow copy and assignment. ++ UniquePtr(const UniquePtr&) = delete; ++ void operator=(const UniquePtr&) = delete; ++}; ++ ++#endif // UNIQUE_PTR_H_included +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/__get_tls.h +@@ -0,0 +1,53 @@ ++/* ++ * Copyright (C) 2008 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++#ifndef __BIONIC_PRIVATE_GET_TLS_H_ ++#define __BIONIC_PRIVATE_GET_TLS_H_ ++ ++#if defined(__aarch64__) ++# define __get_tls() ({ void** __val; __asm__("mrs %0, tpidr_el0" : "=r"(__val)); __val; }) ++#elif defined(__arm__) ++# define __get_tls() ({ void** __val; __asm__("mrc p15, 0, %0, c13, c0, 3" : "=r"(__val)); __val; }) ++#elif defined(__mips__) ++# define __get_tls() \ ++ /* On mips32r1, this goes via a kernel illegal instruction trap that's optimized for v1. */ \ ++ ({ register void** __val asm("v1"); \ ++ __asm__(".set push\n" \ ++ ".set mips32r2\n" \ ++ "rdhwr %0,$29\n" \ ++ ".set pop\n" : "=r"(__val)); \ ++ __val; }) ++#elif defined(__i386__) ++# define __get_tls() ({ void** __val; __asm__("movl %%gs:0, %0" : "=r"(__val)); __val; }) ++#elif defined(__x86_64__) ++# define __get_tls() ({ void** __val; __asm__("mov %%fs:0, %0" : "=r"(__val)); __val; }) ++#else ++#error unsupported architecture ++#endif ++ ++#endif /* __BIONIC_PRIVATE_GET_TLS_H_ */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_asm.h +@@ -0,0 +1,64 @@ ++/* ++ * Copyright (C) 2013 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++#ifndef _PRIVATE_BIONIC_ASM_H_ ++#define _PRIVATE_BIONIC_ASM_H_ ++ ++#include /* For system call numbers. */ ++#define MAX_ERRNO 4095 /* For recognizing system call error returns. */ ++ ++#define __bionic_asm_custom_entry(f) ++#define __bionic_asm_custom_end(f) ++#define __bionic_asm_function_type @function ++ ++#include ++ ++#define ENTRY(f) \ ++ .text; \ ++ .globl f; \ ++ .align __bionic_asm_align; \ ++ .type f, __bionic_asm_function_type; \ ++ f: \ ++ __bionic_asm_custom_entry(f); \ ++ .cfi_startproc \ ++ ++#define END(f) \ ++ .cfi_endproc; \ ++ .size f, .-f; \ ++ __bionic_asm_custom_end(f) \ ++ ++/* Like ENTRY, but with hidden visibility. */ ++#define ENTRY_PRIVATE(f) \ ++ ENTRY(f); \ ++ .hidden f \ ++ ++#define ALIAS_SYMBOL(alias, original) \ ++ .globl alias; \ ++ .equ alias, original ++ ++#endif /* _PRIVATE_BIONIC_ASM_H_ */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_auxv.h +@@ -0,0 +1,41 @@ ++/* ++ * Copyright (C) 2013 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++#ifndef _PRIVATE_BIONIC_AUXV_H_ ++#define _PRIVATE_BIONIC_AUXV_H_ ++ ++#include ++#include ++#include ++ ++__BEGIN_DECLS ++ ++extern ElfW(auxv_t)* __libc_auxv; ++ ++__END_DECLS ++ ++#endif /* _PRIVATE_BIONIC_AUXV_H_ */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_config.h +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (C) 2014 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 _BIONIC_CONFIG_H_ ++#define _BIONIC_CONFIG_H_ ++ ++// valloc(3) and pvalloc(3) were removed from POSIX 2004. We do not include them ++// for LP64, but the symbols remain in LP32 for binary compatibility. ++#if !defined(__LP64__) ++#define HAVE_DEPRECATED_MALLOC_FUNCS 1 ++#endif ++ ++#endif // _BIONIC_CONFIG_H_ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_constants.h +@@ -0,0 +1,22 @@ ++/* ++ * Copyright (C) 2014 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 _BIONIC_CONSTANTS_H_ ++#define _BIONIC_CONSTANTS_H_ ++ ++#define NS_PER_S 1000000000 ++ ++#endif // _BIONIC_CONSTANTS_H_ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_futex.h +@@ -0,0 +1,72 @@ ++/* ++ * Copyright (C) 2008 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++#ifndef _BIONIC_FUTEX_H ++#define _BIONIC_FUTEX_H ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++__BEGIN_DECLS ++ ++struct timespec; ++ ++static inline __always_inline int __futex(volatile void* ftx, int op, int value, const struct timespec* timeout) { ++ // Our generated syscall assembler sets errno, but our callers (pthread functions) don't want to. ++ int saved_errno = errno; ++ int result = syscall(__NR_futex, ftx, op, value, timeout); ++ if (__predict_false(result == -1)) { ++ result = -errno; ++ errno = saved_errno; ++ } ++ return result; ++} ++ ++static inline int __futex_wake(volatile void* ftx, int count) { ++ return __futex(ftx, FUTEX_WAKE, count, NULL); ++} ++ ++static inline int __futex_wake_ex(volatile void* ftx, bool shared, int count) { ++ return __futex(ftx, shared ? FUTEX_WAKE : FUTEX_WAKE_PRIVATE, count, NULL); ++} ++ ++static inline int __futex_wait(volatile void* ftx, int value, const struct timespec* timeout) { ++ return __futex(ftx, FUTEX_WAIT, value, timeout); ++} ++ ++static inline int __futex_wait_ex(volatile void* ftx, bool shared, int value, const struct timespec* timeout) { ++ return __futex(ftx, shared ? FUTEX_WAIT : FUTEX_WAIT_PRIVATE, value, timeout); ++} ++ ++__END_DECLS ++ ++#endif /* _BIONIC_FUTEX_H */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_lock.h +@@ -0,0 +1,74 @@ ++/* ++ * Copyright (C) 2015 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++#ifndef _BIONIC_LOCK_H ++#define _BIONIC_LOCK_H ++ ++#include ++#include "private/bionic_futex.h" ++ ++class Lock { ++ private: ++ enum LockState { ++ Unlocked = 0, ++ LockedWithoutWaiter, ++ LockedWithWaiter, ++ }; ++ _Atomic(LockState) state; ++ bool process_shared; ++ ++ public: ++ Lock(bool process_shared = false) { ++ init(process_shared); ++ } ++ ++ void init(bool process_shared) { ++ atomic_init(&state, Unlocked); ++ this->process_shared = process_shared; ++ } ++ ++ void lock() { ++ LockState old_state = Unlocked; ++ if (__predict_true(atomic_compare_exchange_strong_explicit(&state, &old_state, ++ LockedWithoutWaiter, memory_order_acquire, memory_order_relaxed))) { ++ return; ++ } ++ while (atomic_exchange_explicit(&state, LockedWithWaiter, memory_order_acquire) != Unlocked) { ++ // TODO: As the critical section is brief, it is a better choice to spin a few times befor sleeping. ++ __futex_wait_ex(&state, process_shared, LockedWithWaiter, NULL); ++ } ++ return; ++ } ++ ++ void unlock() { ++ if (atomic_exchange_explicit(&state, Unlocked, memory_order_release) == LockedWithWaiter) { ++ __futex_wake_ex(&state, process_shared, 1); ++ } ++ } ++}; ++ ++#endif // _BIONIC_LOCK_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_macros.h +@@ -0,0 +1,49 @@ ++/* ++ * 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. ++ * 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 _BIONIC_MACROS_H_ ++#define _BIONIC_MACROS_H_ ++ ++// Frameworks OpenGL code currently leaks this header and allows ++// collisions with other declarations, e.g., from libnativehelper. ++// TODO: Remove once cleaned up. b/18334516 ++#if !defined(DISALLOW_COPY_AND_ASSIGN) ++// DISALLOW_COPY_AND_ASSIGN disallows the copy and operator= functions. ++// It goes in the private: declarations in a class. ++#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ ++ TypeName(const TypeName&) = delete; \ ++ void operator=(const TypeName&) = delete ++#endif // !defined(DISALLOW_COPY_AND_ASSIGN) ++ ++// A macro to disallow all the implicit constructors, namely the ++// default constructor, copy constructor and operator= functions. ++// ++// This should be used in the private: declarations for a class ++// that wants to prevent anyone from instantiating it. This is ++// especially useful for classes containing only static methods. ++#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ ++ TypeName() = delete; \ ++ DISALLOW_COPY_AND_ASSIGN(TypeName) ++ ++#define BIONIC_ALIGN(value, alignment) \ ++ (((value) + (alignment) - 1) & ~((alignment) - 1)) ++ ++#define BIONIC_ROUND_UP_POWER_OF_2(value) \ ++ (sizeof(value) == 8) \ ++ ? (1UL << (64 - __builtin_clzl(static_cast(value)))) \ ++ : (1UL << (32 - __builtin_clz(static_cast(value)))) ++ ++#endif // _BIONIC_MACROS_H_ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_mbstate.h +@@ -0,0 +1,54 @@ ++/* ++ * Copyright (C) 2014 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++#ifndef _BIONIC_MBSTATE_H ++#define _BIONIC_MBSTATE_H ++ ++#include ++ ++__BEGIN_DECLS ++ ++/* ++ * These return values are specified by POSIX for multibyte conversion ++ * functions. ++ */ ++#define __MB_ERR_ILLEGAL_SEQUENCE static_cast(-1) ++#define __MB_ERR_INCOMPLETE_SEQUENCE static_cast(-2) ++ ++#define __MB_IS_ERR(rv) (rv == __MB_ERR_ILLEGAL_SEQUENCE || \ ++ rv == __MB_ERR_INCOMPLETE_SEQUENCE) ++ ++size_t mbstate_bytes_so_far(const mbstate_t* ps); ++void mbstate_set_byte(mbstate_t* ps, int i, char byte); ++uint8_t mbstate_get_byte(const mbstate_t* ps, int n); ++size_t reset_and_return_illegal(int _errno, mbstate_t* ps); ++size_t reset_and_return(int _return, mbstate_t* ps); ++ ++__END_DECLS ++ ++#endif // _BIONIC_MBSTATE_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_prctl.h +@@ -0,0 +1,26 @@ ++/* ++ * Copyright (C) 2014 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 BIONIC_PRCTL_H ++#define BIONIC_PRCTL_H ++ ++#include ++ ++// This is only supported by Android kernels, so it's not in the uapi headers. ++#define PR_SET_VMA 0x53564d41 ++#define PR_SET_VMA_ANON_NAME 0 ++ ++#endif // BIONIC_PRCTL_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_ssp.h +@@ -0,0 +1,45 @@ ++/* ++ * Copyright (C) 2012 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++#ifndef _PRIVATE_SSP_H ++#define _PRIVATE_SSP_H ++ ++#include ++#include ++ ++__BEGIN_DECLS ++ ++/* GCC uses this on ARM and MIPS; we use it on x86 to set the guard in TLS. */ ++extern uintptr_t __stack_chk_guard; ++ ++/* GCC calls this if a stack guard check fails. */ ++extern void __stack_chk_fail(); ++ ++__END_DECLS ++ ++#endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_string_utils.h +@@ -0,0 +1,31 @@ ++/* ++ * Copyright (C) 2014 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 _BIONIC_STRING_UTILS_H_ ++#define _BIONIC_STRING_UTILS_H_ ++ ++#include ++ ++static inline bool ends_with(const char* s1, const char* s2) { ++ size_t s1_length = strlen(s1); ++ size_t s2_length = strlen(s2); ++ if (s2_length > s1_length) { ++ return false; ++ } ++ return memcmp(s1 + (s1_length - s2_length), s2, s2_length) == 0; ++} ++ ++#endif // _BIONIC_STRING_UTILS_H_ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_systrace.h +@@ -0,0 +1,35 @@ ++/* ++ * Copyright (C) 2014 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 BIONIC_SYSTRACE_H ++#define BIONIC_SYSTRACE_H ++ ++#include "bionic_macros.h" ++ ++// Tracing class for bionic. To begin a trace at a specified point: ++// ScopedTrace("Trace message"); ++// The trace will end when the contructor goes out of scope. ++ ++class ScopedTrace { ++ public: ++ explicit ScopedTrace(const char* message); ++ ~ScopedTrace(); ++ ++ private: ++ DISALLOW_COPY_AND_ASSIGN(ScopedTrace); ++}; ++ ++#endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_time.h +@@ -0,0 +1,41 @@ ++/* ++ * Copyright (C) 2011 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++#ifndef _BIONIC_TIME_H ++#define _BIONIC_TIME_H ++ ++#include ++#include ++ ++__BEGIN_DECLS ++ ++// We can't remove this (and this file) until we fix MtpUtils.cpp. ++time_t mktime_tz(struct tm* const, char const*); ++ ++__END_DECLS ++ ++#endif /* _BIONIC_TIME_H */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_time_conversions.h +@@ -0,0 +1,46 @@ ++/* ++ * Copyright (C) 2013 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++#ifndef _BIONIC_TIME_CONVERSIONS_H ++#define _BIONIC_TIME_CONVERSIONS_H ++ ++#include ++#include ++ ++__BEGIN_DECLS ++ ++ bool timespec_from_timeval(timespec& ts, const timeval& tv); ++ void timespec_from_ms(timespec& ts, const int ms); ++ ++ void timeval_from_timespec(timeval& tv, const timespec& ts); ++ ++ bool timespec_from_absolute_timespec(timespec& ts, const timespec& abs_ts, clockid_t clock); ++ ++__END_DECLS ++ ++#endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/bionic_tls.h +@@ -0,0 +1,120 @@ ++/* ++ * Copyright (C) 2008 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++#ifndef __BIONIC_PRIVATE_BIONIC_TLS_H_ ++#define __BIONIC_PRIVATE_BIONIC_TLS_H_ ++ ++#include ++#include ++#include "bionic_macros.h" ++#include "__get_tls.h" ++ ++__BEGIN_DECLS ++ ++/** WARNING WARNING WARNING ++ ** ++ ** This header file is *NOT* part of the public Bionic ABI/API ++ ** and should not be used/included by user-serviceable parts of ++ ** the system (e.g. applications). ++ ** ++ ** It is only provided here for the benefit of the system dynamic ++ ** linker and the OpenGL sub-system (which needs to access the ++ ** pre-allocated slot directly for performance reason). ++ **/ ++ ++// Well-known TLS slots. What data goes in which slot is arbitrary unless otherwise noted. ++enum { ++ TLS_SLOT_SELF = 0, // The kernel requires this specific slot for x86. ++ TLS_SLOT_THREAD_ID, ++ TLS_SLOT_ERRNO = 5, ++ ++ // These two aren't used by bionic itself, but allow the graphics code to ++ // access TLS directly rather than using the pthread API. ++ TLS_SLOT_OPENGL_API = 6, ++ TLS_SLOT_OPENGL = 7, ++ ++ // This slot is only used to pass information from the dynamic linker to ++ // libc.so when the C library is loaded in to memory. The C runtime init ++ // function will then clear it. Since its use is extremely temporary, ++ // we reuse an existing location that isn't needed during libc startup. ++ TLS_SLOT_BIONIC_PREINIT = TLS_SLOT_OPENGL_API, ++ ++ TLS_SLOT_STACK_GUARD = 8, // GCC requires this specific slot for x86. ++ TLS_SLOT_DLERROR, ++ ++ BIONIC_TLS_SLOTS // Must come last! ++}; ++ ++/* ++ * Bionic uses some pthread keys internally. All pthread keys used internally ++ * should be created in constructors, except for keys that may be used in or ++ * before constructors. ++ * ++ * We need to manually maintain the count of pthread keys used internally, but ++ * pthread_test should fail if we forget. ++ * ++ * These are the pthread keys currently used internally by libc: ++ * ++ * basename libc (ThreadLocalBuffer) ++ * dirname libc (ThreadLocalBuffer) ++ * uselocale libc (can be used in constructors) ++ * getmntent_mntent libc (ThreadLocalBuffer) ++ * getmntent_strings libc (ThreadLocalBuffer) ++ * ptsname libc (ThreadLocalBuffer) ++ * ttyname libc (ThreadLocalBuffer) ++ * strerror libc (ThreadLocalBuffer) ++ * strsignal libc (ThreadLocalBuffer) ++ * passwd libc (ThreadLocalBuffer) ++ * group libc (ThreadLocalBuffer) ++ * _res_key libc (constructor in BSD code) ++ */ ++ ++#define LIBC_PTHREAD_KEY_RESERVED_COUNT 12 ++ ++#if defined(USE_JEMALLOC) ++/* Internally, jemalloc uses a single key for per thread data. */ ++#define JEMALLOC_PTHREAD_KEY_RESERVED_COUNT 1 ++#define BIONIC_PTHREAD_KEY_RESERVED_COUNT (LIBC_PTHREAD_KEY_RESERVED_COUNT + JEMALLOC_PTHREAD_KEY_RESERVED_COUNT) ++#else ++#define BIONIC_PTHREAD_KEY_RESERVED_COUNT LIBC_PTHREAD_KEY_RESERVED_COUNT ++#endif ++ ++/* ++ * Maximum number of pthread keys allocated. ++ * This includes pthread keys used internally and externally. ++ */ ++#define BIONIC_PTHREAD_KEY_COUNT (BIONIC_PTHREAD_KEY_RESERVED_COUNT + PTHREAD_KEYS_MAX) ++ ++__END_DECLS ++ ++#if defined(__cplusplus) ++class KernelArgumentBlock; ++extern void __libc_init_tls(KernelArgumentBlock& args); ++#endif ++ ++#endif /* __BIONIC_PRIVATE_BIONIC_TLS_H_ */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/kernel_sigset_t.h +@@ -0,0 +1,54 @@ ++/* ++ * Copyright (C) 2013 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 LIBC_PRIVATE_KERNEL_SIGSET_T_H_ ++#define LIBC_PRIVATE_KERNEL_SIGSET_T_H_ ++ ++#include ++ ++// Our sigset_t is wrong for ARM and x86. It's 32-bit but the kernel expects 64 bits. ++// This means we can't support real-time signals correctly until we can change the ABI. ++// In the meantime, we can use this union to pass an appropriately-sized block of memory ++// to the kernel, at the cost of not being able to refer to real-time signals. ++union kernel_sigset_t { ++ kernel_sigset_t() { ++ clear(); ++ } ++ ++ kernel_sigset_t(const sigset_t* value) { ++ clear(); ++ set(value); ++ } ++ ++ void clear() { ++ __builtin_memset(this, 0, sizeof(*this)); ++ } ++ ++ void set(const sigset_t* value) { ++ bionic = *value; ++ } ++ ++ sigset_t* get() { ++ return &bionic; ++ } ++ ++ sigset_t bionic; ++#ifndef __mips__ ++ uint32_t kernel[2]; ++#endif ++}; ++ ++#endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/libc_events.h +@@ -0,0 +1,50 @@ ++/* ++ * Copyright (C) 2013 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++#ifndef _LIBC_EVENTS_H ++#define _LIBC_EVENTS_H ++ ++ ++// This is going to be included in assembler code so only allow #define ++// values instead of defining an enum. ++ ++#define BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW 80100 ++#define BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW 80105 ++#define BIONIC_EVENT_MEMMOVE_BUFFER_OVERFLOW 80110 ++#define BIONIC_EVENT_STRNCAT_BUFFER_OVERFLOW 80115 ++#define BIONIC_EVENT_STRNCPY_BUFFER_OVERFLOW 80120 ++#define BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW 80125 ++#define BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW 80130 ++#define BIONIC_EVENT_STPCPY_BUFFER_OVERFLOW 80135 ++#define BIONIC_EVENT_STPNCPY_BUFFER_OVERFLOW 80140 ++ ++#define BIONIC_EVENT_RESOLVER_OLD_RESPONSE 80300 ++#define BIONIC_EVENT_RESOLVER_WRONG_SERVER 80305 ++#define BIONIC_EVENT_RESOLVER_WRONG_QUERY 80310 ++ ++#endif // _LIBC_EVENTS_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/libc_logging.h +@@ -0,0 +1,111 @@ ++/* ++ * Copyright (C) 2010 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++#ifndef _LIBC_LOGGING_H ++#define _LIBC_LOGGING_H ++ ++#include ++#include ++#include ++#include ++ ++__BEGIN_DECLS ++ ++#include "libc_events.h" ++ ++enum { ++ ANDROID_LOG_UNKNOWN = 0, ++ ANDROID_LOG_DEFAULT, /* only for SetMinPriority() */ ++ ++ ANDROID_LOG_VERBOSE, ++ ANDROID_LOG_DEBUG, ++ ANDROID_LOG_INFO, ++ ANDROID_LOG_WARN, ++ ANDROID_LOG_ERROR, ++ ANDROID_LOG_FATAL, ++ ++ ANDROID_LOG_SILENT, /* only for SetMinPriority(); must be last */ ++}; ++ ++enum { ++ LOG_ID_MIN = 0, ++ ++ LOG_ID_MAIN = 0, ++ LOG_ID_RADIO = 1, ++ LOG_ID_EVENTS = 2, ++ LOG_ID_SYSTEM = 3, ++ LOG_ID_CRASH = 4, ++ ++ LOG_ID_MAX ++}; ++ ++struct abort_msg_t { ++ size_t size; ++ char msg[0]; ++}; ++ ++// ++// Formats a message to the log (priority 'fatal'), then aborts. ++// ++ ++ void __libc_fatal(const char* format, ...); ++ ++// ++// Formats a message to the log (priority 'fatal'), but doesn't abort. ++// Used by the malloc implementation to ensure that debuggerd dumps memory ++// around the bad address. ++// ++ ++ void __libc_fatal_no_abort(const char* format, ...); ++ ++// ++// Formatting routines for the C library's internal debugging. ++// Unlike the usual alternatives, these don't allocate, and they don't drag in all of stdio. ++// ++ ++ int __libc_format_buffer(char* buffer, size_t buffer_size, const char* format, ...); ++ ++ int __libc_format_fd(int fd, const char* format, ...); ++ ++ int __libc_format_log(int priority, const char* tag, const char* format, ...); ++ ++ int __libc_format_log_va_list(int priority, const char* tag, const char* format, ++ va_list ap); ++ ++// ++// Event logging. ++// ++ ++ void __libc_android_log_event_int(int32_t tag, int value); ++ void __libc_android_log_event_uid(int32_t tag); ++ ++ void __fortify_chk_fail(const char* msg, uint32_t event_tag); ++ ++__END_DECLS ++ ++#endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/bionic/libc/private/thread_private.h +@@ -0,0 +1,55 @@ ++/* $OpenBSD: thread_private.h,v 1.18 2006/02/22 07:16:31 otto Exp $ */ ++ ++/* PUBLIC DOMAIN: No Rights Reserved. Marco S Hyman */ ++ ++#ifndef _THREAD_PRIVATE_H_ ++#define _THREAD_PRIVATE_H_ ++ ++#include ++ ++__BEGIN_DECLS ++ ++/* ++ * This file defines the thread library interface to libc. Thread ++ * libraries must implement the functions described here for proper ++ * inter-operation with libc. libc contains weak versions of the ++ * described functions for operation in a non-threaded environment. ++ */ ++ ++/* ++ * helper macro to make unique names in the thread namespace ++ */ ++#define __THREAD_NAME(name) __CONCAT(_thread_tagname_,name) ++ ++struct __thread_private_tag_t { ++ pthread_mutex_t _private_lock; ++ pthread_key_t _private_key; ++}; ++ ++#define _THREAD_PRIVATE_MUTEX(name) \ ++ static struct __thread_private_tag_t __THREAD_NAME(name) = { PTHREAD_MUTEX_INITIALIZER, -1 } ++#define _THREAD_PRIVATE_MUTEX_LOCK(name) \ ++ pthread_mutex_lock( &__THREAD_NAME(name)._private_lock ) ++#define _THREAD_PRIVATE_MUTEX_UNLOCK(name) \ ++ pthread_mutex_unlock( &__THREAD_NAME(name)._private_lock ) ++ ++/* Note that these aren't compatible with the usual OpenBSD ones which lazy-initialize! */ ++#define _MUTEX_LOCK(l) pthread_mutex_lock((pthread_mutex_t*) l) ++#define _MUTEX_UNLOCK(l) pthread_mutex_unlock((pthread_mutex_t*) l) ++ ++ void _thread_atexit_lock(void); ++ void _thread_atexit_unlock(void); ++ ++#define _ATEXIT_LOCK() _thread_atexit_lock() ++#define _ATEXIT_UNLOCK() _thread_atexit_unlock() ++ ++ void _thread_arc4_lock(void); ++ void _thread_arc4_unlock(void); ++ ++#define _ARC4_LOCK() _thread_arc4_lock() ++#define _ARC4_UNLOCK() _thread_arc4_unlock() ++#define _ARC4_ATFORK(f) pthread_atfork(NULL, NULL, (f)) ++ ++__END_DECLS ++ ++#endif /* _THREAD_PRIVATE_H_ */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/dlfcn.cpp +@@ -0,0 +1,298 @@ ++/* ++ * Copyright (C) 2007 The Android Open Source Project ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++#include "linker.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include "private/bionic_tls.h" ++#include "private/ScopedPthreadMutexLocker.h" ++#include "private/ThreadLocalBuffer.h" ++ ++#include "hybris_compat.h" ++ ++/* This file hijacks the symbols stubbed out in libdl.so. */ ++ ++static pthread_mutex_t g_dl_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; ++ ++static char dl_err_buf[1024]; ++static const char *dl_err_str; ++ ++static const char* __bionic_set_dlerror(char* new_value) { ++#ifdef DISABLED_FOR_HYBRIS_SUPPORT ++ char** dlerror_slot = &reinterpret_cast(__get_tls())[TLS_SLOT_DLERROR]; ++ ++ const char* old_value = *dlerror_slot; ++ *dlerror_slot = new_value; ++ return old_value; ++#else ++ char *dlerror_slot = dl_err_buf; ++ const char *old_value = dlerror_slot; ++ dlerror_slot = new_value; ++ return old_value; ++#endif ++} ++ ++static void __bionic_format_dlerror(const char* msg, const char* detail) { ++#ifdef DISABLED_FOR_HYBRIS_SUPPORT ++ char* buffer = __get_thread()->dlerror_buffer; ++#else ++ char* buffer = dl_err_buf; ++#endif ++ strlcpy(buffer, msg, __BIONIC_DLERROR_BUFFER_SIZE); ++ if (detail != nullptr) { ++ strlcat(buffer, ": ", __BIONIC_DLERROR_BUFFER_SIZE); ++ strlcat(buffer, detail, __BIONIC_DLERROR_BUFFER_SIZE); ++ } ++ ++ __bionic_set_dlerror(buffer); ++} ++ ++extern "C" const char* android_dlerror() { ++ const char* old_value = __bionic_set_dlerror(nullptr); ++ return old_value; ++} ++ ++void android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) { ++ ScopedPthreadMutexLocker locker(&g_dl_mutex); ++ do_android_get_LD_LIBRARY_PATH(buffer, buffer_size); ++} ++ ++void android_update_LD_LIBRARY_PATH(const char* ld_library_path) { ++ ScopedPthreadMutexLocker locker(&g_dl_mutex); ++ do_android_update_LD_LIBRARY_PATH(ld_library_path); ++} ++ ++static void* dlopen_ext(const char* filename, int flags, const android_dlextinfo* extinfo) { ++ ScopedPthreadMutexLocker locker(&g_dl_mutex); ++ soinfo* result = do_dlopen(filename, flags, extinfo); ++ if (result == nullptr) { ++ __bionic_format_dlerror("dlopen failed", linker_get_error_buffer()); ++ return nullptr; ++ } ++ return result; ++} ++ ++extern "C" void* android_dlopen_ext(const char* filename, int flags, const android_dlextinfo* extinfo) { ++ return dlopen_ext(filename, flags, extinfo); ++} ++ ++extern "C" void* android_dlopen(const char* filename, int flags) { ++ return dlopen_ext(filename, flags, nullptr); ++} ++ ++extern "C" void* android_dlsym(void* handle, const char* symbol) { ++ ScopedPthreadMutexLocker locker(&g_dl_mutex); ++ ++#if !defined(__LP64__) ++ if (handle == nullptr) { ++ __bionic_format_dlerror("dlsym library handle is null", nullptr); ++ return nullptr; ++ } ++#endif ++ ++ if (symbol == nullptr) { ++ __bionic_format_dlerror("dlsym symbol name is null", nullptr); ++ return nullptr; ++ } ++ ++ soinfo* found = nullptr; ++ const ElfW(Sym)* sym = nullptr; ++ void* caller_addr = __builtin_return_address(0); ++ soinfo* caller = find_containing_library(caller_addr); ++ ++ if (handle == RTLD_DEFAULT || handle == RTLD_NEXT) { ++ sym = dlsym_linear_lookup(symbol, &found, caller, handle); ++ } else { ++ sym = dlsym_handle_lookup(reinterpret_cast(handle), &found, symbol); ++ } ++ ++ if (sym != nullptr) { ++ unsigned bind = ELF_ST_BIND(sym->st_info); ++ ++ if ((bind == STB_GLOBAL || bind == STB_WEAK) && sym->st_shndx != 0) { ++ return reinterpret_cast(found->resolve_symbol_address(sym)); ++ } ++ ++ __bionic_format_dlerror("symbol found but not global", symbol); ++ return nullptr; ++ } else { ++ __bionic_format_dlerror("undefined symbol", symbol); ++ return nullptr; ++ } ++} ++ ++extern "C" int android_dladdr(const void* addr, Dl_info* info) { ++ ScopedPthreadMutexLocker locker(&g_dl_mutex); ++ ++ // Determine if this address can be found in any library currently mapped. ++ soinfo* si = find_containing_library(addr); ++ if (si == nullptr) { ++ return 0; ++ } ++ ++ memset(info, 0, sizeof(Dl_info)); ++ ++ info->dli_fname = si->get_realpath(); ++ // Address at which the shared object is loaded. ++ info->dli_fbase = reinterpret_cast(si->base); ++ ++ // Determine if any symbol in the library contains the specified address. ++ ElfW(Sym)* sym = si->find_symbol_by_address(addr); ++ if (sym != nullptr) { ++ info->dli_sname = si->get_string(sym->st_name); ++ info->dli_saddr = reinterpret_cast(si->resolve_symbol_address(sym)); ++ } ++ ++ return 1; ++} ++ ++extern "C" int android_dlclose(void* handle) { ++ ScopedPthreadMutexLocker locker(&g_dl_mutex); ++ do_dlclose(reinterpret_cast(handle)); ++ // dlclose has no defined errors. ++ return 0; ++} ++ ++int dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data) { ++ ScopedPthreadMutexLocker locker(&g_dl_mutex); ++ return do_dl_iterate_phdr(cb, data); ++} ++ ++void android_set_application_target_sdk_version(uint32_t target) { ++ // lock to avoid modification in the middle of dlopen. ++ ScopedPthreadMutexLocker locker(&g_dl_mutex); ++ set_application_target_sdk_version(target); ++} ++ ++uint32_t android_get_application_target_sdk_version() { ++ return get_application_target_sdk_version(); ++} ++ ++// name_offset: starting index of the name in libdl_info.strtab ++#define ELF32_SYM_INITIALIZER(name_offset, value, shndx) \ ++ { name_offset, \ ++ reinterpret_cast(value), \ ++ /* st_size */ 0, \ ++ (shndx == 0) ? 0 : (STB_GLOBAL << 4), \ ++ /* st_other */ 0, \ ++ shndx, \ ++ } ++ ++#define ELF64_SYM_INITIALIZER(name_offset, value, shndx) \ ++ { name_offset, \ ++ (shndx == 0) ? 0 : (STB_GLOBAL << 4), \ ++ /* st_other */ 0, \ ++ shndx, \ ++ reinterpret_cast(value), \ ++ /* st_size */ 0, \ ++ } ++ ++#if defined(__arm__) ++_Unwind_Ptr android_dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount); ++#endif ++ ++static const char ANDROID_LIBDL_STRTAB[] = ++ // 0000000 00011111 111112 22222222 2333333 3333444444444455555555556666666 6667777777777888888888899999 99999 ++ // 0123456 78901234 567890 12345678 9012345 6789012345678901234567890123456 7890123456789012345678901234 56789 ++ "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0android_update_LD_LIBRARY_PATH\0android_get_LD_LIBRARY_PATH\0dl_it" ++ // 00000000001 1111111112222222222 3333333333444444444455555555556666666666777 777777788888888889999999999 ++ // 01234567890 1234567890123456789 0123456789012345678901234567890123456789012 345678901234567890123456789 ++ "erate_phdr\0android_dlopen_ext\0android_set_application_target_sdk_version\0android_get_application_tar" ++ // 0000000000111111 ++ // 0123456789012345 ++ "get_sdk_version\0" ++#if defined(__arm__) ++ // 216 ++ "dl_unwind_find_exidx\0" ++#endif ++ ; ++ ++static ElfW(Sym) g_libdl_symtab[] = { ++ // Total length of libdl_info.strtab, including trailing 0. ++ // This is actually the STH_UNDEF entry. Technically, it's ++ // supposed to have st_name == 0, but instead, it points to an index ++ // in the strtab with a \0 to make iterating through the symtab easier. ++ ELFW(SYM_INITIALIZER)(sizeof(ANDROID_LIBDL_STRTAB) - 1, nullptr, 0), ++ ELFW(SYM_INITIALIZER)( 0, &android_dlopen, 1), ++ ELFW(SYM_INITIALIZER)( 7, &android_dlclose, 1), ++ ELFW(SYM_INITIALIZER)( 15, &android_dlsym, 1), ++ ELFW(SYM_INITIALIZER)( 21, &android_dlerror, 1), ++ ELFW(SYM_INITIALIZER)( 29, &android_dladdr, 1), ++ ELFW(SYM_INITIALIZER)( 36, &android_update_LD_LIBRARY_PATH, 1), ++ ELFW(SYM_INITIALIZER)( 67, &android_get_LD_LIBRARY_PATH, 1), ++ ELFW(SYM_INITIALIZER)( 95, &dl_iterate_phdr, 1), ++ ELFW(SYM_INITIALIZER)(111, &android_dlopen_ext, 1), ++ ELFW(SYM_INITIALIZER)(130, &android_set_application_target_sdk_version, 1), ++ ELFW(SYM_INITIALIZER)(173, &android_get_application_target_sdk_version, 1), ++#if defined(__arm__) ++ ELFW(SYM_INITIALIZER)(216, &dl_unwind_find_exidx, 1), ++#endif ++}; ++ ++// Fake out a hash table with a single bucket. ++// ++// A search of the hash table will look through g_libdl_symtab starting with index 1, then ++// use g_libdl_chains to find the next index to look at. g_libdl_chains should be set up to ++// walk through every element in g_libdl_symtab, and then end with 0 (sentinel value). ++// ++// That is, g_libdl_chains should look like { 0, 2, 3, ... N, 0 } where N is the number ++// of actual symbols, or nelems(g_libdl_symtab)-1 (since the first element of g_libdl_symtab is not ++// a real symbol). (See soinfo_elf_lookup().) ++// ++// Note that adding any new symbols here requires stubbing them out in libdl. ++static unsigned g_libdl_buckets[1] = { 1 }; ++#if defined(__arm__) ++static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0 }; ++#else ++static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0 }; ++#endif ++ ++static uint8_t __libdl_info_buf[sizeof(soinfo)] __attribute__((aligned(8))); ++static soinfo* __libdl_info = nullptr; ++ ++// This is used by the dynamic linker. Every process gets these symbols for free. ++soinfo* get_libdl_info() { ++ if (__libdl_info == nullptr) { ++ __libdl_info = new (__libdl_info_buf) soinfo("libdl.so", nullptr, 0, RTLD_GLOBAL); ++ __libdl_info->flags_ |= FLAG_LINKED; ++ __libdl_info->strtab_ = ANDROID_LIBDL_STRTAB; ++ __libdl_info->symtab_ = g_libdl_symtab; ++ __libdl_info->nbucket_ = sizeof(g_libdl_buckets)/sizeof(unsigned); ++ __libdl_info->nchain_ = sizeof(g_libdl_chains)/sizeof(unsigned); ++ __libdl_info->bucket_ = g_libdl_buckets; ++ __libdl_info->chain_ = g_libdl_chains; ++ __libdl_info->ref_count_ = 1; ++ __libdl_info->strtab_size_ = sizeof(ANDROID_LIBDL_STRTAB); ++ __libdl_info->local_group_root_ = __libdl_info; ++ __libdl_info->soname_ = "libdl.so"; ++ __libdl_info->target_sdk_version_ = __ANDROID_API__; ++#if DISABLED_FOR_HYBRIS_SUPPORT ++#if defined(__arm__) ++ strlcpy(__libdl_info->old_name_, __libdl_info->soname_, sizeof(__libdl_info->old_name_)); ++#endif ++#endif ++ } ++ ++ return __libdl_info; ++} +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/hybris_compat.cpp +@@ -0,0 +1,29 @@ ++/* ++ * Copyright (C) 2008 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++#include "hybris_compat.h" +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/hybris_compat.h +@@ -0,0 +1,58 @@ ++/* ++ * Copyright (C) 2008 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++ ++#ifndef HYBRIS_ANDROID_MM_COMPAT_H_ ++#define HYBRIS_ANDROID_MM_COMPAT_H_ ++ ++#include ++#include ++ ++extern "C" size_t strlcpy(char *dest, const char *src, size_t size); ++extern "C" size_t strlcat(char *dst, const char *src, size_t size); ++ ++#define ELF_ST_BIND(x) ((x) >> 4) ++ ++#ifndef PAGE_SIZE ++#define PAGE_SIZE 4096 ++#endif ++ ++#define PAGE_MASK (~(PAGE_SIZE - 1)) ++ ++/* ++ * From bionic/libc/include/elf.h ++ * ++ * Android compressed rel/rela sections ++ */ ++#define DT_ANDROID_REL (DT_LOOS + 2) ++#define DT_ANDROID_RELSZ (DT_LOOS + 3) ++ ++#define DT_ANDROID_RELA (DT_LOOS + 4) ++#define DT_ANDROID_RELASZ (DT_LOOS + 5) ++ ++#endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linked_list.h +@@ -0,0 +1,180 @@ ++/* ++ * Copyright (C) 2014 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 __LINKED_LIST_H ++#define __LINKED_LIST_H ++ ++#include "private/bionic_macros.h" ++ ++template ++struct LinkedListEntry { ++ LinkedListEntry* next; ++ T* element; ++}; ++ ++/* ++ * Represents linked list of objects of type T ++ */ ++template ++class LinkedList { ++ public: ++ LinkedList() : head_(nullptr), tail_(nullptr) {} ++ ~LinkedList() { ++ clear(); ++ } ++ ++ LinkedList(LinkedList&& that) { ++ this->head_ = that.head_; ++ this->tail_ = that.tail_; ++ that.head_ = that.tail_ = nullptr; ++ } ++ ++ void push_front(T* const element) { ++ LinkedListEntry* new_entry = Allocator::alloc(); ++ new_entry->next = head_; ++ new_entry->element = element; ++ head_ = new_entry; ++ if (tail_ == nullptr) { ++ tail_ = new_entry; ++ } ++ } ++ ++ void push_back(T* const element) { ++ LinkedListEntry* new_entry = Allocator::alloc(); ++ new_entry->next = nullptr; ++ new_entry->element = element; ++ if (tail_ == nullptr) { ++ tail_ = head_ = new_entry; ++ } else { ++ tail_->next = new_entry; ++ tail_ = new_entry; ++ } ++ } ++ ++ T* pop_front() { ++ if (head_ == nullptr) { ++ return nullptr; ++ } ++ ++ LinkedListEntry* entry = head_; ++ T* element = entry->element; ++ head_ = entry->next; ++ Allocator::free(entry); ++ ++ if (head_ == nullptr) { ++ tail_ = nullptr; ++ } ++ ++ return element; ++ } ++ ++ T* front() const { ++ if (head_ == nullptr) { ++ return nullptr; ++ } ++ ++ return head_->element; ++ } ++ ++ void clear() { ++ while (head_ != nullptr) { ++ LinkedListEntry* p = head_; ++ head_ = head_->next; ++ Allocator::free(p); ++ } ++ ++ tail_ = nullptr; ++ } ++ ++ template ++ void for_each(F action) const { ++ visit([&] (T* si) { ++ action(si); ++ return true; ++ }); ++ } ++ ++ template ++ bool visit(F action) const { ++ for (LinkedListEntry* e = head_; e != nullptr; e = e->next) { ++ if (!action(e->element)) { ++ return false; ++ } ++ } ++ return true; ++ } ++ ++ template ++ void remove_if(F predicate) { ++ for (LinkedListEntry* e = head_, *p = nullptr; e != nullptr;) { ++ if (predicate(e->element)) { ++ LinkedListEntry* next = e->next; ++ if (p == nullptr) { ++ head_ = next; ++ } else { ++ p->next = next; ++ } ++ Allocator::free(e); ++ e = next; ++ } else { ++ p = e; ++ e = e->next; ++ } ++ } ++ } ++ ++ template ++ T* find_if(F predicate) const { ++ for (LinkedListEntry* e = head_; e != nullptr; e = e->next) { ++ if (predicate(e->element)) { ++ return e->element; ++ } ++ } ++ ++ return nullptr; ++ } ++ ++ size_t copy_to_array(T* array[], size_t array_length) const { ++ size_t sz = 0; ++ for (LinkedListEntry* e = head_; sz < array_length && e != nullptr; e = e->next) { ++ array[sz++] = e->element; ++ } ++ ++ return sz; ++ } ++ ++ bool contains(const T* el) const { ++ for (LinkedListEntry* e = head_; e != nullptr; e = e->next) { ++ if (e->element == el) { ++ return true; ++ } ++ } ++ return false; ++ } ++ ++ static LinkedList make_list(T* const element) { ++ LinkedList one_element_list; ++ one_element_list.push_back(element); ++ return one_element_list; ++ } ++ ++ private: ++ LinkedListEntry* head_; ++ LinkedListEntry* tail_; ++ DISALLOW_COPY_AND_ASSIGN(LinkedList); ++}; ++ ++#endif // __LINKED_LIST_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker.cpp +@@ -0,0 +1,3391 @@ ++/* ++ * Copyright (C) 2008 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++ ++// Private C library headers. ++#include "private/bionic_tls.h" ++#include "private/KernelArgumentBlock.h" ++#include "private/ScopedPthreadMutexLocker.h" ++#include "private/ScopeGuard.h" ++#include "private/UniquePtr.h" ++ ++#include "linker.h" ++#include "linker_block_allocator.h" ++#include "linker_debug.h" ++#include "linker_sleb128.h" ++#include "linker_phdr.h" ++#include "linker_relocs.h" ++#include "linker_reloc_iterators.h" ++ ++#include "hybris_compat.h" ++ ++#ifdef DISABLED_FOR_HYBRIS_SUPPORT ++extern void __libc_init_AT_SECURE(KernelArgumentBlock&); ++#endif ++ ++// Override macros to use C++ style casts. ++#undef ELF_ST_TYPE ++#define ELF_ST_TYPE(x) (static_cast(x) & 0xf) ++ ++static ElfW(Addr) get_elf_exec_load_bias(const ElfW(Ehdr)* elf); ++ ++static LinkerTypeAllocator g_soinfo_allocator; ++static LinkerTypeAllocator> g_soinfo_links_allocator; ++ ++static soinfo* solist = get_libdl_info(); ++static soinfo* sonext = get_libdl_info(); ++static soinfo* somain; // main process, always the one after libdl_info ++ ++static const char* const kDefaultLdPaths[] = { ++#if defined(__LP64__) ++ "/vendor/lib64", ++ "/system/lib64", ++#else ++ "/vendor/lib", ++ "/system/lib", ++#endif ++ nullptr ++}; ++ ++static const ElfW(Versym) kVersymNotNeeded = 0; ++static const ElfW(Versym) kVersymGlobal = 1; ++ ++static std::vector g_ld_library_paths; ++static std::vector g_ld_preload_names; ++ ++static std::vector g_ld_preloads; ++ ++int g_ld_debug_verbosity = 0; ++ ++abort_msg_t* g_abort_message = nullptr; // For debuggerd. ++ ++#if STATS ++struct linker_stats_t { ++ int count[kRelocMax]; ++}; ++ ++static linker_stats_t linker_stats; ++ ++void count_relocation(RelocationKind kind) { ++ ++linker_stats.count[kind]; ++} ++#else ++void count_relocation(RelocationKind) { ++} ++#endif ++ ++#if COUNT_PAGES ++uint32_t bitmask[4096]; ++#endif ++ ++static char __linker_dl_err_buf[768]; ++ ++char* linker_get_error_buffer() { ++ return &__linker_dl_err_buf[0]; ++} ++ ++size_t linker_get_error_buffer_size() { ++ return sizeof(__linker_dl_err_buf); ++} ++ ++// This function is an empty stub where GDB locates a breakpoint to get notified ++// about linker activity. ++extern "C" ++void __attribute__((noinline)) __attribute__((visibility("default"))) rtld_db_dlactivity(); ++ ++static pthread_mutex_t g__r_debug_mutex = PTHREAD_MUTEX_INITIALIZER; ++static r_debug _r_debug = ++ {1, nullptr, reinterpret_cast(&rtld_db_dlactivity), r_debug::RT_CONSISTENT, 0}; ++ ++static link_map* r_debug_tail = 0; ++ ++static void* (*_get_hooked_symbol)(const char *sym, const char *requester); ++ ++static void insert_soinfo_into_debug_map(soinfo* info) { ++ // Copy the necessary fields into the debug structure. ++ link_map* map = &(info->link_map_head); ++ map->l_addr = info->load_bias; ++ // link_map l_name field is not const. ++ map->l_name = const_cast(info->get_realpath()); ++ map->l_ld = info->dynamic; ++ ++ // Stick the new library at the end of the list. ++ // gdb tends to care more about libc than it does ++ // about leaf libraries, and ordering it this way ++ // reduces the back-and-forth over the wire. ++ if (r_debug_tail) { ++ r_debug_tail->l_next = map; ++ map->l_prev = r_debug_tail; ++ map->l_next = 0; ++ } else { ++ _r_debug.r_map = map; ++ map->l_prev = 0; ++ map->l_next = 0; ++ } ++ r_debug_tail = map; ++} ++ ++static void remove_soinfo_from_debug_map(soinfo* info) { ++ link_map* map = &(info->link_map_head); ++ ++ if (r_debug_tail == map) { ++ r_debug_tail = map->l_prev; ++ } ++ ++ if (map->l_prev) { ++ map->l_prev->l_next = map->l_next; ++ } ++ if (map->l_next) { ++ map->l_next->l_prev = map->l_prev; ++ } ++} ++ ++static void notify_gdb_of_load(soinfo* info) { ++ if (info->is_main_executable()) { ++ // GDB already knows about the main executable ++ return; ++ } ++ ++ ScopedPthreadMutexLocker locker(&g__r_debug_mutex); ++ ++ _r_debug.r_state = r_debug::RT_ADD; ++ rtld_db_dlactivity(); ++ ++ insert_soinfo_into_debug_map(info); ++ ++ _r_debug.r_state = r_debug::RT_CONSISTENT; ++ rtld_db_dlactivity(); ++} ++ ++static void notify_gdb_of_unload(soinfo* info) { ++ if (info->is_main_executable()) { ++ // GDB already knows about the main executable ++ return; ++ } ++ ++ ScopedPthreadMutexLocker locker(&g__r_debug_mutex); ++ ++ _r_debug.r_state = r_debug::RT_DELETE; ++ rtld_db_dlactivity(); ++ ++ remove_soinfo_from_debug_map(info); ++ ++ _r_debug.r_state = r_debug::RT_CONSISTENT; ++ rtld_db_dlactivity(); ++} ++ ++void notify_gdb_of_libraries() { ++ _r_debug.r_state = r_debug::RT_ADD; ++ rtld_db_dlactivity(); ++ _r_debug.r_state = r_debug::RT_CONSISTENT; ++ rtld_db_dlactivity(); ++} ++ ++LinkedListEntry* SoinfoListAllocator::alloc() { ++ return g_soinfo_links_allocator.alloc(); ++} ++ ++void SoinfoListAllocator::free(LinkedListEntry* entry) { ++ g_soinfo_links_allocator.free(entry); ++} ++ ++static soinfo* soinfo_alloc(const char* name, struct stat* file_stat, ++ off64_t file_offset, uint32_t rtld_flags) { ++ if (strlen(name) >= PATH_MAX) { ++ DL_ERR("library name \"%s\" too long", name); ++ return nullptr; ++ } ++ ++ soinfo* si = new (g_soinfo_allocator.alloc()) soinfo(name, file_stat, file_offset, rtld_flags); ++ ++ sonext->next = si; ++ sonext = si; ++ ++ TRACE("name %s: allocated soinfo @ %p", name, si); ++ return si; ++} ++ ++static void soinfo_free(soinfo* si) { ++ if (si == nullptr) { ++ return; ++ } ++ ++ if (si->base != 0 && si->size != 0) { ++ munmap(reinterpret_cast(si->base), si->size); ++ } ++ ++ soinfo *prev = nullptr, *trav; ++ ++ TRACE("name %s: freeing soinfo @ %p", si->get_realpath(), si); ++ ++ for (trav = solist; trav != nullptr; trav = trav->next) { ++ if (trav == si) { ++ break; ++ } ++ prev = trav; ++ } ++ ++ if (trav == nullptr) { ++ // si was not in solist ++ DL_ERR("name \"%s\"@%p is not in solist!", si->get_realpath(), si); ++ return; ++ } ++ ++ // clear links to/from si ++ si->remove_all_links(); ++ ++ // prev will never be null, because the first entry in solist is ++ // always the static libdl_info. ++ prev->next = si->next; ++ if (si == sonext) { ++ sonext = prev; ++ } ++ ++ si->~soinfo(); ++ g_soinfo_allocator.free(si); ++} ++ ++static void parse_path(const char* path, const char* delimiters, ++ std::vector* paths) { ++ if (path == nullptr) { ++ return; ++ } ++ ++ paths->clear(); ++ ++ for (const char *p = path; ; ++p) { ++ size_t len = strcspn(p, delimiters); ++ // skip empty tokens ++ if (len == 0) { ++ continue; ++ } ++ ++ paths->push_back(std::string(p, len)); ++ p += len; ++ ++ if (*p == '\0') { ++ break; ++ } ++ } ++} ++ ++static void parse_LD_LIBRARY_PATH(const char* path) { ++ parse_path(path, ":", &g_ld_library_paths); ++} ++ ++static void parse_LD_PRELOAD(const char* path) { ++ // We have historically supported ':' as well as ' ' in LD_PRELOAD. ++ parse_path(path, " :", &g_ld_preload_names); ++} ++ ++static bool realpath_fd(int fd, std::string* realpath) { ++ std::vector buf(PATH_MAX), proc_self_fd(PATH_MAX); ++ snprintf(&proc_self_fd[0], proc_self_fd.size(), "/proc/self/fd/%d", fd); ++ if (readlink(&proc_self_fd[0], &buf[0], buf.size()) == -1) { ++ PRINT("readlink('%s') failed: %s [fd=%d]", &proc_self_fd[0], strerror(errno), fd); ++ return false; ++ } ++ ++ *realpath = std::string(&buf[0]); ++ return true; ++} ++ ++#if defined(__arm__) ++ ++// For a given PC, find the .so that it belongs to. ++// Returns the base address of the .ARM.exidx section ++// for that .so, and the number of 8-byte entries ++// in that section (via *pcount). ++// ++// Intended to be called by libc's __gnu_Unwind_Find_exidx(). ++// ++// This function is exposed via dlfcn.cpp and libdl.so. ++_Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int* pcount) { ++ uintptr_t addr = reinterpret_cast(pc); ++ ++ for (soinfo* si = solist; si != 0; si = si->next) { ++ if ((addr >= si->base) && (addr < (si->base + si->size))) { ++ *pcount = si->ARM_exidx_count; ++ return reinterpret_cast<_Unwind_Ptr>(si->ARM_exidx); ++ } ++ } ++ *pcount = 0; ++ return nullptr; ++} ++ ++#endif ++ ++// Here, we only have to provide a callback to iterate across all the ++// loaded libraries. gcc_eh does the rest. ++int do_dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data) { ++ int rv = 0; ++ for (soinfo* si = solist; si != nullptr; si = si->next) { ++ dl_phdr_info dl_info; ++ dl_info.dlpi_addr = si->link_map_head.l_addr; ++ dl_info.dlpi_name = si->link_map_head.l_name; ++ dl_info.dlpi_phdr = si->phdr; ++ dl_info.dlpi_phnum = si->phnum; ++ rv = cb(&dl_info, sizeof(dl_phdr_info), data); ++ if (rv != 0) { ++ break; ++ } ++ } ++ return rv; ++} ++ ++const ElfW(Versym)* soinfo::get_versym(size_t n) const { ++ if (has_min_version(2) && versym_ != nullptr) { ++ return versym_ + n; ++ } ++ ++ return nullptr; ++} ++ ++ElfW(Addr) soinfo::get_verneed_ptr() const { ++ if (has_min_version(2)) { ++ return verneed_ptr_; ++ } ++ ++ return 0; ++} ++ ++size_t soinfo::get_verneed_cnt() const { ++ if (has_min_version(2)) { ++ return verneed_cnt_; ++ } ++ ++ return 0; ++} ++ ++ElfW(Addr) soinfo::get_verdef_ptr() const { ++ if (has_min_version(2)) { ++ return verdef_ptr_; ++ } ++ ++ return 0; ++} ++ ++size_t soinfo::get_verdef_cnt() const { ++ if (has_min_version(2)) { ++ return verdef_cnt_; ++ } ++ ++ return 0; ++} ++ ++template ++static bool for_each_verdef(const soinfo* si, F functor) { ++ if (!si->has_min_version(2)) { ++ return true; ++ } ++ ++ uintptr_t verdef_ptr = si->get_verdef_ptr(); ++ if (verdef_ptr == 0) { ++ return true; ++ } ++ ++ size_t offset = 0; ++ ++ size_t verdef_cnt = si->get_verdef_cnt(); ++ for (size_t i = 0; i(verdef_ptr + offset); ++ size_t verdaux_offset = offset + verdef->vd_aux; ++ offset += verdef->vd_next; ++ ++ if (verdef->vd_version != 1) { ++ DL_ERR("unsupported verdef[%zd] vd_version: %d (expected 1) library: %s", ++ i, verdef->vd_version, si->get_realpath()); ++ return false; ++ } ++ ++ if ((verdef->vd_flags & VER_FLG_BASE) != 0) { ++ // "this is the version of the file itself. It must not be used for ++ // matching a symbol. It can be used to match references." ++ // ++ // http://www.akkadia.org/drepper/symbol-versioning ++ continue; ++ } ++ ++ if (verdef->vd_cnt == 0) { ++ DL_ERR("invalid verdef[%zd] vd_cnt == 0 (version without a name)", i); ++ return false; ++ } ++ ++ const ElfW(Verdaux)* verdaux = reinterpret_cast(verdef_ptr + verdaux_offset); ++ ++ if (functor(i, verdef, verdaux) == true) { ++ break; ++ } ++ } ++ ++ return true; ++} ++ ++bool soinfo::find_verdef_version_index(const version_info* vi, ElfW(Versym)* versym) const { ++ if (vi == nullptr) { ++ *versym = kVersymNotNeeded; ++ return true; ++ } ++ ++ *versym = kVersymGlobal; ++ ++ return for_each_verdef(this, ++ [&](size_t, const ElfW(Verdef)* verdef, const ElfW(Verdaux)* verdaux) { ++ if (verdef->vd_hash == vi->elf_hash && ++ strcmp(vi->name, get_string(verdaux->vda_name)) == 0) { ++ *versym = verdef->vd_ndx; ++ return true; ++ } ++ ++ return false; ++ } ++ ); ++} ++ ++bool soinfo::find_symbol_by_name(SymbolName& symbol_name, ++ const version_info* vi, ++ const ElfW(Sym)** symbol) const { ++ uint32_t symbol_index; ++ bool success = ++ is_gnu_hash() ? ++ gnu_lookup(symbol_name, vi, &symbol_index) : ++ elf_lookup(symbol_name, vi, &symbol_index); ++ ++ if (success) { ++ *symbol = symbol_index == 0 ? nullptr : symtab_ + symbol_index; ++ } ++ ++ return success; ++} ++ ++static bool is_symbol_global_and_defined(const soinfo* si, const ElfW(Sym)* s) { ++ if (ELF_ST_BIND(s->st_info) == STB_GLOBAL || ++ ELF_ST_BIND(s->st_info) == STB_WEAK) { ++ return s->st_shndx != SHN_UNDEF; ++ } else if (ELF_ST_BIND(s->st_info) != STB_LOCAL) { ++ DL_WARN("unexpected ST_BIND value: %d for '%s' in '%s'", ++ ELF_ST_BIND(s->st_info), si->get_string(s->st_name), si->get_realpath()); ++ } ++ ++ return false; ++} ++ ++static const ElfW(Versym) kVersymHiddenBit = 0x8000; ++ ++static inline bool is_versym_hidden(const ElfW(Versym)* versym) { ++ // the symbol is hidden if bit 15 of versym is set. ++ return versym != nullptr && (*versym & kVersymHiddenBit) != 0; ++} ++ ++static inline bool check_symbol_version(const ElfW(Versym) verneed, ++ const ElfW(Versym)* verdef) { ++ return verneed == kVersymNotNeeded || ++ verdef == nullptr || ++ verneed == (*verdef & ~kVersymHiddenBit); ++} ++ ++bool soinfo::gnu_lookup(SymbolName& symbol_name, ++ const version_info* vi, ++ uint32_t* symbol_index) const { ++ uint32_t hash = symbol_name.gnu_hash(); ++ uint32_t h2 = hash >> gnu_shift2_; ++ ++ uint32_t bloom_mask_bits = sizeof(ElfW(Addr))*8; ++ uint32_t word_num = (hash / bloom_mask_bits) & gnu_maskwords_; ++ ElfW(Addr) bloom_word = gnu_bloom_filter_[word_num]; ++ ++ *symbol_index = 0; ++ ++ TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p (gnu)", ++ symbol_name.get_name(), get_realpath(), reinterpret_cast(base)); ++ ++ // test against bloom filter ++ if ((1 & (bloom_word >> (hash % bloom_mask_bits)) & (bloom_word >> (h2 % bloom_mask_bits))) == 0) { ++ TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p", ++ symbol_name.get_name(), get_realpath(), reinterpret_cast(base)); ++ ++ return true; ++ } ++ ++ // bloom test says "probably yes"... ++ uint32_t n = gnu_bucket_[hash % gnu_nbucket_]; ++ ++ if (n == 0) { ++ TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p", ++ symbol_name.get_name(), get_realpath(), reinterpret_cast(base)); ++ ++ return true; ++ } ++ ++ // lookup versym for the version definition in this library ++ // note the difference between "version is not requested" (vi == nullptr) ++ // and "version not found". In the first case verneed is kVersymNotNeeded ++ // which implies that the default version can be accepted; the second case results in ++ // verneed = 1 (kVersymGlobal) and implies that we should ignore versioned symbols ++ // for this library and consider only *global* ones. ++ ElfW(Versym) verneed = 0; ++ if (!find_verdef_version_index(vi, &verneed)) { ++ return false; ++ } ++ ++ do { ++ ElfW(Sym)* s = symtab_ + n; ++ const ElfW(Versym)* verdef = get_versym(n); ++ // skip hidden versions when verneed == kVersymNotNeeded (0) ++ if (verneed == kVersymNotNeeded && is_versym_hidden(verdef)) { ++ continue; ++ } ++ if (((gnu_chain_[n] ^ hash) >> 1) == 0 && ++ check_symbol_version(verneed, verdef) && ++ strcmp(get_string(s->st_name), symbol_name.get_name()) == 0 && ++ is_symbol_global_and_defined(this, s)) { ++ TRACE_TYPE(LOOKUP, "FOUND %s in %s (%p) %zd", ++ symbol_name.get_name(), get_realpath(), reinterpret_cast(s->st_value), ++ static_cast(s->st_size)); ++ *symbol_index = n; ++ return true; ++ } ++ } while ((gnu_chain_[n++] & 1) == 0); ++ ++ TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p", ++ symbol_name.get_name(), get_realpath(), reinterpret_cast(base)); ++ ++ return true; ++} ++ ++bool soinfo::elf_lookup(SymbolName& symbol_name, ++ const version_info* vi, ++ uint32_t* symbol_index) const { ++ uint32_t hash = symbol_name.elf_hash(); ++ ++ TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p h=%x(elf) %zd", ++ symbol_name.get_name(), get_realpath(), ++ reinterpret_cast(base), hash, hash % nbucket_); ++ ++ ElfW(Versym) verneed = 0; ++ if (!find_verdef_version_index(vi, &verneed)) { ++ return false; ++ } ++ ++ for (uint32_t n = bucket_[hash % nbucket_]; n != 0; n = chain_[n]) { ++ ElfW(Sym)* s = symtab_ + n; ++ const ElfW(Versym)* verdef = get_versym(n); ++ ++ // skip hidden versions when verneed == 0 ++ if (verneed == kVersymNotNeeded && is_versym_hidden(verdef)) { ++ continue; ++ } ++ ++ if (check_symbol_version(verneed, verdef) && ++ strcmp(get_string(s->st_name), symbol_name.get_name()) == 0 && ++ is_symbol_global_and_defined(this, s)) { ++ TRACE_TYPE(LOOKUP, "FOUND %s in %s (%p) %zd", ++ symbol_name.get_name(), get_realpath(), ++ reinterpret_cast(s->st_value), ++ static_cast(s->st_size)); ++ *symbol_index = n; ++ return true; ++ } ++ } ++ ++ TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p %x %zd", ++ symbol_name.get_name(), get_realpath(), ++ reinterpret_cast(base), hash, hash % nbucket_); ++ ++ *symbol_index = 0; ++ return true; ++} ++ ++soinfo::soinfo(const char* realpath, const struct stat* file_stat, ++ off64_t file_offset, int rtld_flags) { ++ ++ if (realpath != nullptr) { ++ realpath_ = realpath; ++ } ++ ++ flags_ = FLAG_NEW_SOINFO; ++ version_ = SOINFO_VERSION; ++ ++ if (file_stat != nullptr) { ++ this->st_dev_ = file_stat->st_dev; ++ this->st_ino_ = file_stat->st_ino; ++ this->file_offset_ = file_offset; ++ } ++ ++ this->rtld_flags_ = rtld_flags; ++} ++ ++ ++uint32_t SymbolName::elf_hash() { ++ if (!has_elf_hash_) { ++ const uint8_t* name = reinterpret_cast(name_); ++ uint32_t h = 0, g; ++ ++ while (*name) { ++ h = (h << 4) + *name++; ++ g = h & 0xf0000000; ++ h ^= g; ++ h ^= g >> 24; ++ } ++ ++ elf_hash_ = h; ++ has_elf_hash_ = true; ++ } ++ ++ return elf_hash_; ++} ++ ++uint32_t SymbolName::gnu_hash() { ++ if (!has_gnu_hash_) { ++ uint32_t h = 5381; ++ const uint8_t* name = reinterpret_cast(name_); ++ while (*name != 0) { ++ h += (h << 5) + *name++; // h*33 + c = h + h * 32 + c = h + h << 5 + c ++ } ++ ++ gnu_hash_ = h; ++ has_gnu_hash_ = true; ++ } ++ ++ return gnu_hash_; ++} ++ ++bool soinfo_do_lookup(soinfo* si_from, const char* name, const version_info* vi, ++ soinfo** si_found_in, const soinfo::soinfo_list_t& global_group, ++ const soinfo::soinfo_list_t& local_group, const ElfW(Sym)** symbol) { ++ SymbolName symbol_name(name); ++ const ElfW(Sym)* s = nullptr; ++ ++ /* "This element's presence in a shared object library alters the dynamic linker's ++ * symbol resolution algorithm for references within the library. Instead of starting ++ * a symbol search with the executable file, the dynamic linker starts from the shared ++ * object itself. If the shared object fails to supply the referenced symbol, the ++ * dynamic linker then searches the executable file and other shared objects as usual." ++ * ++ * http://www.sco.com/developers/gabi/2012-12-31/ch5.dynamic.html ++ * ++ * Note that this is unlikely since static linker avoids generating ++ * relocations for -Bsymbolic linked dynamic executables. ++ */ ++ if (si_from->has_DT_SYMBOLIC) { ++ DEBUG("%s: looking up %s in local scope (DT_SYMBOLIC)", si_from->get_realpath(), name); ++ if (!si_from->find_symbol_by_name(symbol_name, vi, &s)) { ++ return false; ++ } ++ ++ if (s != nullptr) { ++ *si_found_in = si_from; ++ } ++ } ++ ++ // 1. Look for it in global_group ++ if (s == nullptr) { ++ bool error = false; ++ global_group.visit([&](soinfo* global_si) { ++ DEBUG("%s: looking up %s in %s (from global group)", ++ si_from->get_realpath(), name, global_si->get_realpath()); ++ if (!global_si->find_symbol_by_name(symbol_name, vi, &s)) { ++ error = true; ++ return false; ++ } ++ ++ if (s != nullptr) { ++ *si_found_in = global_si; ++ return false; ++ } ++ ++ return true; ++ }); ++ ++ if (error) { ++ return false; ++ } ++ } ++ ++ // 2. Look for it in the local group ++ if (s == nullptr) { ++ bool error = false; ++ local_group.visit([&](soinfo* local_si) { ++ if (local_si == si_from && si_from->has_DT_SYMBOLIC) { ++ // we already did this - skip ++ return true; ++ } ++ ++ DEBUG("%s: looking up %s in %s (from local group)", ++ si_from->get_realpath(), name, local_si->get_realpath()); ++ if (!local_si->find_symbol_by_name(symbol_name, vi, &s)) { ++ error = true; ++ return false; ++ } ++ ++ if (s != nullptr) { ++ *si_found_in = local_si; ++ return false; ++ } ++ ++ return true; ++ }); ++ ++ if (error) { ++ return false; ++ } ++ } ++ ++ if (s != nullptr) { ++ TRACE_TYPE(LOOKUP, "si %s sym %s s->st_value = %p, " ++ "found in %s, base = %p, load bias = %p", ++ si_from->get_realpath(), name, reinterpret_cast(s->st_value), ++ (*si_found_in)->get_realpath(), reinterpret_cast((*si_found_in)->base), ++ reinterpret_cast((*si_found_in)->load_bias)); ++ } ++ ++ *symbol = s; ++ return true; ++} ++ ++class ProtectedDataGuard { ++ public: ++ ProtectedDataGuard() { ++ if (ref_count_++ == 0) { ++ protect_data(PROT_READ | PROT_WRITE); ++ } ++ } ++ ++ ~ProtectedDataGuard() { ++ if (ref_count_ == 0) { // overflow ++ __libc_fatal("Too many nested calls to dlopen()"); ++ } ++ ++ if (--ref_count_ == 0) { ++ protect_data(PROT_READ); ++ } ++ } ++ private: ++ void protect_data(int protection) { ++ g_soinfo_allocator.protect_all(protection); ++ g_soinfo_links_allocator.protect_all(protection); ++ } ++ ++ static size_t ref_count_; ++}; ++ ++size_t ProtectedDataGuard::ref_count_ = 0; ++ ++// Each size has it's own allocator. ++template ++class SizeBasedAllocator { ++ public: ++ static void* alloc() { ++ return allocator_.alloc(); ++ } ++ ++ static void free(void* ptr) { ++ allocator_.free(ptr); ++ } ++ ++ private: ++ static LinkerBlockAllocator allocator_; ++}; ++ ++template ++LinkerBlockAllocator SizeBasedAllocator::allocator_(size); ++ ++template ++class TypeBasedAllocator { ++ public: ++ static T* alloc() { ++ return reinterpret_cast(SizeBasedAllocator::alloc()); ++ } ++ ++ static void free(T* ptr) { ++ SizeBasedAllocator::free(ptr); ++ } ++}; ++ ++class LoadTask { ++ public: ++ struct deleter_t { ++ void operator()(LoadTask* t) { ++ TypeBasedAllocator::free(t); ++ } ++ }; ++ ++ typedef UniquePtr unique_ptr; ++ ++ static deleter_t deleter; ++ ++ static LoadTask* create(const char* name, soinfo* needed_by) { ++ LoadTask* ptr = TypeBasedAllocator::alloc(); ++ return new (ptr) LoadTask(name, needed_by); ++ } ++ ++ const char* get_name() const { ++ return name_; ++ } ++ ++ soinfo* get_needed_by() const { ++ return needed_by_; ++ } ++ private: ++ LoadTask(const char* name, soinfo* needed_by) ++ : name_(name), needed_by_(needed_by) {} ++ ++ const char* name_; ++ soinfo* needed_by_; ++ ++ DISALLOW_IMPLICIT_CONSTRUCTORS(LoadTask); ++}; ++ ++LoadTask::deleter_t LoadTask::deleter; ++ ++template ++using linked_list_t = LinkedList>>; ++ ++typedef linked_list_t SoinfoLinkedList; ++typedef linked_list_t StringLinkedList; ++typedef linked_list_t LoadTaskList; ++ ++ ++// This function walks down the tree of soinfo dependencies ++// in breadth-first order and ++// * calls action(soinfo* si) for each node, and ++// * terminates walk if action returns false. ++// ++// walk_dependencies_tree returns false if walk was terminated ++// by the action and true otherwise. ++template ++static bool walk_dependencies_tree(soinfo* root_soinfos[], size_t root_soinfos_size, F action) { ++ SoinfoLinkedList visit_list; ++ SoinfoLinkedList visited; ++ ++ for (size_t i = 0; i < root_soinfos_size; ++i) { ++ visit_list.push_back(root_soinfos[i]); ++ } ++ ++ soinfo* si; ++ while ((si = visit_list.pop_front()) != nullptr) { ++ if (visited.contains(si)) { ++ continue; ++ } ++ ++ if (!action(si)) { ++ return false; ++ } ++ ++ visited.push_back(si); ++ ++ si->get_children().for_each([&](soinfo* child) { ++ visit_list.push_back(child); ++ }); ++ } ++ ++ return true; ++} ++ ++ ++static const ElfW(Sym)* dlsym_handle_lookup(soinfo* root, soinfo* skip_until, ++ soinfo** found, SymbolName& symbol_name) { ++ const ElfW(Sym)* result = nullptr; ++ bool skip_lookup = skip_until != nullptr; ++ ++ walk_dependencies_tree(&root, 1, [&](soinfo* current_soinfo) { ++ if (skip_lookup) { ++ skip_lookup = current_soinfo != skip_until; ++ return true; ++ } ++ ++ if (!current_soinfo->find_symbol_by_name(symbol_name, nullptr, &result)) { ++ result = nullptr; ++ return false; ++ } ++ ++ if (result != nullptr) { ++ *found = current_soinfo; ++ return false; ++ } ++ ++ return true; ++ }); ++ ++ return result; ++} ++ ++// This is used by dlsym(3). It performs symbol lookup only within the ++// specified soinfo object and its dependencies in breadth first order. ++const ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name) { ++ // According to man dlopen(3) and posix docs in the case when si is handle ++ // of the main executable we need to search not only in the executable and its ++ // dependencies but also in all libraries loaded with RTLD_GLOBAL. ++ // ++ // Since RTLD_GLOBAL is always set for the main executable and all dt_needed shared ++ // libraries and they are loaded in breath-first (correct) order we can just execute ++ // dlsym(RTLD_DEFAULT, ...); instead of doing two stage lookup. ++ if (si == somain) { ++ return dlsym_linear_lookup(name, found, nullptr, RTLD_DEFAULT); ++ } ++ ++ SymbolName symbol_name(name); ++ return dlsym_handle_lookup(si, nullptr, found, symbol_name); ++} ++ ++/* This is used by dlsym(3) to performs a global symbol lookup. If the ++ start value is null (for RTLD_DEFAULT), the search starts at the ++ beginning of the global solist. Otherwise the search starts at the ++ specified soinfo (for RTLD_NEXT). ++ */ ++const ElfW(Sym)* dlsym_linear_lookup(const char* name, ++ soinfo** found, ++ soinfo* caller, ++ void* handle) { ++ SymbolName symbol_name(name); ++ ++ soinfo* start = solist; ++ ++ if (handle == RTLD_NEXT) { ++ if (caller == nullptr) { ++ return nullptr; ++ } else { ++ start = caller->next; ++ } ++ } ++ ++ const ElfW(Sym)* s = nullptr; ++ for (soinfo* si = start; si != nullptr; si = si->next) { ++ // Do not skip RTLD_LOCAL libraries in dlsym(RTLD_DEFAULT, ...) ++ // if the library is opened by application with target api level <= 22 ++ // See http://b/21565766 ++ if ((si->get_rtld_flags() & RTLD_GLOBAL) == 0 && si->get_target_sdk_version() > 22) { ++ continue; ++ } ++ ++ if (!si->find_symbol_by_name(symbol_name, nullptr, &s)) { ++ return nullptr; ++ } ++ ++ if (s != nullptr) { ++ *found = si; ++ break; ++ } ++ } ++ ++ // If not found - use dlsym_handle_lookup for caller's ++ // local_group unless it is part of the global group in which ++ // case we already did it. ++ if (s == nullptr && caller != nullptr && ++ (caller->get_rtld_flags() & RTLD_GLOBAL) == 0) { ++ return dlsym_handle_lookup(caller->get_local_group_root(), ++ (handle == RTLD_NEXT) ? caller : nullptr, found, symbol_name); ++ } ++ ++ if (s != nullptr) { ++ TRACE_TYPE(LOOKUP, "%s s->st_value = %p, found->base = %p", ++ name, reinterpret_cast(s->st_value), reinterpret_cast((*found)->base)); ++ } ++ ++ return s; ++} ++ ++soinfo* find_containing_library(const void* p) { ++ ElfW(Addr) address = reinterpret_cast(p); ++ for (soinfo* si = solist; si != nullptr; si = si->next) { ++ if (address >= si->base && address - si->base < si->size) { ++ return si; ++ } ++ } ++ return nullptr; ++} ++ ++ElfW(Sym)* soinfo::find_symbol_by_address(const void* addr) { ++ return is_gnu_hash() ? gnu_addr_lookup(addr) : elf_addr_lookup(addr); ++} ++ ++static bool symbol_matches_soaddr(const ElfW(Sym)* sym, ElfW(Addr) soaddr) { ++ return sym->st_shndx != SHN_UNDEF && ++ soaddr >= sym->st_value && ++ soaddr < sym->st_value + sym->st_size; ++} ++ ++ElfW(Sym)* soinfo::gnu_addr_lookup(const void* addr) { ++ ElfW(Addr) soaddr = reinterpret_cast(addr) - load_bias; ++ ++ for (size_t i = 0; i < gnu_nbucket_; ++i) { ++ uint32_t n = gnu_bucket_[i]; ++ ++ if (n == 0) { ++ continue; ++ } ++ ++ do { ++ ElfW(Sym)* sym = symtab_ + n; ++ if (symbol_matches_soaddr(sym, soaddr)) { ++ return sym; ++ } ++ } while ((gnu_chain_[n++] & 1) == 0); ++ } ++ ++ return nullptr; ++} ++ ++ElfW(Sym)* soinfo::elf_addr_lookup(const void* addr) { ++ ElfW(Addr) soaddr = reinterpret_cast(addr) - load_bias; ++ ++ // Search the library's symbol table for any defined symbol which ++ // contains this address. ++ for (size_t i = 0; i < nchain_; ++i) { ++ ElfW(Sym)* sym = symtab_ + i; ++ if (symbol_matches_soaddr(sym, soaddr)) { ++ return sym; ++ } ++ } ++ ++ return nullptr; ++} ++ ++static bool format_path(char* buf, size_t buf_size, const char* path, const char* name) { ++ int n = snprintf(buf, buf_size, "%s/%s", path, name); ++ if (n < 0 || n >= static_cast(buf_size)) { ++ PRINT("Warning: ignoring very long library path: %s/%s", path, name); ++ return false; ++ } ++ ++ return true; ++} ++ ++static int open_library_on_default_path(const char* name, off64_t* file_offset) { ++ for (size_t i = 0; kDefaultLdPaths[i] != nullptr; ++i) { ++ char buf[512]; ++ if (!format_path(buf, sizeof(buf), kDefaultLdPaths[i], name)) { ++ continue; ++ } ++ ++ int fd = TEMP_FAILURE_RETRY(open(buf, O_RDONLY | O_CLOEXEC)); ++ if (fd != -1) { ++ *file_offset = 0; ++ return fd; ++ } ++ } ++ ++ return -1; ++} ++ ++static int open_library_on_ld_library_path(const char* name, off64_t* file_offset) { ++ for (const auto& path_str : g_ld_library_paths) { ++ char buf[512]; ++ const char* const path = path_str.c_str(); ++ if (!format_path(buf, sizeof(buf), path, name)) { ++ continue; ++ } ++ ++ int fd = -1; ++ if (fd == -1) { ++ fd = TEMP_FAILURE_RETRY(open(buf, O_RDONLY | O_CLOEXEC)); ++ if (fd != -1) { ++ *file_offset = 0; ++ } ++ } ++ ++ if (fd != -1) { ++ return fd; ++ } ++ } ++ ++ return -1; ++} ++ ++static int open_library(const char* name, off64_t* file_offset) { ++ TRACE("[ opening %s ]", name); ++ ++ // If the name contains a slash, we should attempt to open it directly and not search the paths. ++ if (strchr(name, '/') != nullptr) { ++ int fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY | O_CLOEXEC)); ++ if (fd != -1) { ++ *file_offset = 0; ++ } ++ return fd; ++ } ++ ++ // Otherwise we try LD_LIBRARY_PATH first, and fall back to the built-in well known paths. ++ int fd = open_library_on_ld_library_path(name, file_offset); ++ if (fd == -1) { ++ fd = open_library_on_default_path(name, file_offset); ++ } ++ return fd; ++} ++ ++static const char* fix_dt_needed(const char* dt_needed, const char* sopath) { ++ (void) sopath; ++#if !defined(__LP64__) ++ // Work around incorrect DT_NEEDED entries for old apps: http://b/21364029 ++ if (get_application_target_sdk_version() <= 22) { ++ const char* bname = basename(dt_needed); ++ if (bname != dt_needed) { ++ DL_WARN("'%s' library has invalid DT_NEEDED entry '%s'", sopath, dt_needed); ++ } ++ ++ return bname; ++ } ++#endif ++ return dt_needed; ++} ++ ++template ++static void for_each_dt_needed(const soinfo* si, F action) { ++ for (ElfW(Dyn)* d = si->dynamic; d->d_tag != DT_NULL; ++d) { ++ if (d->d_tag == DT_NEEDED) { ++ action(fix_dt_needed(si->get_string(d->d_un.d_val), si->get_realpath())); ++ } ++ } ++} ++ ++static soinfo* load_library(int fd, off64_t file_offset, ++ LoadTaskList& load_tasks, ++ const char* name, int rtld_flags, ++ const android_dlextinfo* extinfo) { ++ if ((file_offset % PAGE_SIZE) != 0) { ++ DL_ERR("file offset for the library \"%s\" is not page-aligned: %" PRId64, name, file_offset); ++ return nullptr; ++ } ++ if (file_offset < 0) { ++ DL_ERR("file offset for the library \"%s\" is negative: %" PRId64, name, file_offset); ++ return nullptr; ++ } ++ ++ struct stat file_stat; ++ if (TEMP_FAILURE_RETRY(fstat(fd, &file_stat)) != 0) { ++ DL_ERR("unable to stat file for the library \"%s\": %s", name, strerror(errno)); ++ return nullptr; ++ } ++ if (file_offset >= file_stat.st_size) { ++ DL_ERR("file offset for the library \"%s\" >= file size: %" PRId64 " >= %" PRId64, ++ name, file_offset, file_stat.st_size); ++ return nullptr; ++ } ++ ++ // Check for symlink and other situations where ++ // file can have different names, unless ANDROID_DLEXT_FORCE_LOAD is set ++ if (extinfo == nullptr || (extinfo->flags & ANDROID_DLEXT_FORCE_LOAD) == 0) { ++ for (soinfo* si = solist; si != nullptr; si = si->next) { ++ if (si->get_st_dev() != 0 && ++ si->get_st_ino() != 0 && ++ si->get_st_dev() == file_stat.st_dev && ++ si->get_st_ino() == file_stat.st_ino && ++ si->get_file_offset() == file_offset) { ++ TRACE("library \"%s\" is already loaded under different name/path \"%s\" - " ++ "will return existing soinfo", name, si->get_realpath()); ++ return si; ++ } ++ } ++ } ++ ++ if ((rtld_flags & RTLD_NOLOAD) != 0) { ++ DL_ERR("library \"%s\" wasn't loaded and RTLD_NOLOAD prevented it", name); ++ return nullptr; ++ } ++ ++ std::string realpath = name; ++ if (!realpath_fd(fd, &realpath)) { ++ PRINT("warning: unable to get realpath for the library \"%s\". Will use given name.", name); ++ realpath = name; ++ } ++ ++ // Read the ELF header and load the segments. ++ ElfReader elf_reader(realpath.c_str(), fd, file_offset, file_stat.st_size); ++ if (!elf_reader.Load(extinfo)) { ++ return nullptr; ++ } ++ ++ soinfo* si = soinfo_alloc(realpath.c_str(), &file_stat, file_offset, rtld_flags); ++ if (si == nullptr) { ++ return nullptr; ++ } ++ si->base = elf_reader.load_start(); ++ si->size = elf_reader.load_size(); ++ si->load_bias = elf_reader.load_bias(); ++ si->phnum = elf_reader.phdr_count(); ++ si->phdr = elf_reader.loaded_phdr(); ++ ++ if (!si->prelink_image()) { ++ soinfo_free(si); ++ return nullptr; ++ } ++ ++ for_each_dt_needed(si, [&] (const char* name) { ++ load_tasks.push_back(LoadTask::create(name, si)); ++ }); ++ ++ return si; ++} ++ ++static soinfo* load_library(LoadTaskList& load_tasks, ++ const char* name, int rtld_flags, ++ const android_dlextinfo* extinfo) { ++ if (extinfo != nullptr && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) { ++ off64_t file_offset = 0; ++ if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) { ++ file_offset = extinfo->library_fd_offset; ++ } ++ return load_library(extinfo->library_fd, file_offset, load_tasks, name, rtld_flags, extinfo); ++ } ++ ++ // Open the file. ++ off64_t file_offset; ++ int fd = open_library(name, &file_offset); ++ if (fd == -1) { ++ DL_ERR("library \"%s\" not found", name); ++ return nullptr; ++ } ++ soinfo* result = load_library(fd, file_offset, load_tasks, name, rtld_flags, extinfo); ++ close(fd); ++ return result; ++} ++ ++// Returns true if library was found and false in 2 cases ++// 1. The library was found but loaded under different target_sdk_version ++// (*candidate != nullptr) ++// 2. The library was not found by soname (*candidate is nullptr) ++static bool find_loaded_library_by_soname(const char* name, soinfo** candidate) { ++ *candidate = nullptr; ++ ++ // Ignore filename with path. ++ if (strchr(name, '/') != nullptr) { ++ return false; ++ } ++ ++ uint32_t target_sdk_version = get_application_target_sdk_version(); ++ ++ for (soinfo* si = solist; si != nullptr; si = si->next) { ++ const char* soname = si->get_soname(); ++ if (soname != nullptr && (strcmp(name, soname) == 0)) { ++ // If the library was opened under different target sdk version ++ // skip this step and try to reopen it. The exceptions are ++ // "libdl.so" and global group. There is no point in skipping ++ // them because relocation process is going to use them ++ // in any case. ++ bool is_libdl = si == solist; ++ if (is_libdl || (si->get_dt_flags_1() & DF_1_GLOBAL) != 0 || ++ !si->is_linked() || si->get_target_sdk_version() == target_sdk_version) { ++ *candidate = si; ++ return true; ++ } else if (*candidate == nullptr) { ++ // for the different sdk version - remember the first library. ++ *candidate = si; ++ } ++ } ++ } ++ ++ return false; ++} ++ ++static soinfo* find_library_internal(LoadTaskList& load_tasks, const char* name, ++ int rtld_flags, const android_dlextinfo* extinfo) { ++ soinfo* candidate; ++ ++ if (find_loaded_library_by_soname(name, &candidate)) { ++ return candidate; ++ } ++ ++ // Library might still be loaded, the accurate detection ++ // of this fact is done by load_library. ++ TRACE("[ '%s' find_loaded_library_by_soname returned false (*candidate=%s@%p). Trying harder...]", ++ name, candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate); ++ ++ soinfo* si = load_library(load_tasks, name, rtld_flags, extinfo); ++ ++ // In case we were unable to load the library but there ++ // is a candidate loaded under the same soname but different ++ // sdk level - return it anyways. ++ if (si == nullptr && candidate != nullptr) { ++ si = candidate; ++ } ++ ++ return si; ++} ++ ++static void soinfo_unload(soinfo* si); ++ ++// TODO: this is slightly unusual way to construct ++// the global group for relocation. Not every RTLD_GLOBAL ++// library is included in this group for backwards-compatibility ++// reasons. ++// ++// This group consists of the main executable, LD_PRELOADs ++// and libraries with the DF_1_GLOBAL flag set. ++static soinfo::soinfo_list_t make_global_group() { ++ soinfo::soinfo_list_t global_group; ++ for (soinfo* si = somain; si != nullptr; si = si->next) { ++ if ((si->get_dt_flags_1() & DF_1_GLOBAL) != 0) { ++ global_group.push_back(si); ++ } ++ } ++ ++ return global_group; ++} ++ ++static bool find_libraries(soinfo* start_with, const char* const library_names[], ++ size_t library_names_count, soinfo* soinfos[], std::vector* ld_preloads, ++ size_t ld_preloads_count, int rtld_flags, const android_dlextinfo* extinfo) { ++ // Step 0: prepare. ++ LoadTaskList load_tasks; ++ for (size_t i = 0; i < library_names_count; ++i) { ++ const char* name = library_names[i]; ++ load_tasks.push_back(LoadTask::create(name, start_with)); ++ } ++ ++ // Construct global_group. ++ soinfo::soinfo_list_t global_group = make_global_group(); ++ ++ // If soinfos array is null allocate one on stack. ++ // The array is needed in case of failure; for example ++ // when library_names[] = {libone.so, libtwo.so} and libone.so ++ // is loaded correctly but libtwo.so failed for some reason. ++ // In this case libone.so should be unloaded on return. ++ // See also implementation of failure_guard below. ++ ++ if (soinfos == nullptr) { ++ size_t soinfos_size = sizeof(soinfo*)*library_names_count; ++ soinfos = reinterpret_cast(alloca(soinfos_size)); ++ memset(soinfos, 0, soinfos_size); ++ } ++ ++ // list of libraries to link - see step 2. ++ size_t soinfos_count = 0; ++ ++ auto failure_guard = make_scope_guard([&]() { ++ // Housekeeping ++ load_tasks.for_each([] (LoadTask* t) { ++ LoadTask::deleter(t); ++ }); ++ ++ for (size_t i = 0; iget_name(), rtld_flags, extinfo); ++ if (si == nullptr) { ++ return false; ++ } ++ ++ soinfo* needed_by = task->get_needed_by(); ++ ++ if (needed_by != nullptr) { ++ needed_by->add_child(si); ++ } ++ ++ if (si->is_linked()) { ++ si->increment_ref_count(); ++ } ++ ++ // When ld_preloads is not null, the first ++ // ld_preloads_count libs are in fact ld_preloads. ++ if (ld_preloads != nullptr && soinfos_count < ld_preloads_count) { ++ // Add LD_PRELOADed libraries to the global group for future runs. ++ // There is no need to explicitly add them to the global group ++ // for this run because they are going to appear in the local ++ // group in the correct order. ++ si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL); ++ ld_preloads->push_back(si); ++ } ++ ++ if (soinfos_count < library_names_count) { ++ soinfos[soinfos_count++] = si; ++ } ++ } ++ ++ // Step 2: link libraries. ++ soinfo::soinfo_list_t local_group; ++ walk_dependencies_tree( ++ start_with == nullptr ? soinfos : &start_with, ++ start_with == nullptr ? soinfos_count : 1, ++ [&] (soinfo* si) { ++ local_group.push_back(si); ++ return true; ++ }); ++ ++ // We need to increment ref_count in case ++ // the root of the local group was not linked. ++ bool was_local_group_root_linked = local_group.front()->is_linked(); ++ ++ bool linked = local_group.visit([&](soinfo* si) { ++ if (!si->is_linked()) { ++ if (!si->link_image(global_group, local_group, extinfo)) { ++ return false; ++ } ++ si->set_linked(); ++ } ++ ++ return true; ++ }); ++ ++ if (linked) { ++ failure_guard.disable(); ++ } ++ ++ if (!was_local_group_root_linked) { ++ local_group.front()->increment_ref_count(); ++ } ++ ++ return linked; ++} ++ ++static soinfo* find_library(const char* name, int rtld_flags, const android_dlextinfo* extinfo) { ++ soinfo* si; ++ ++ if (name == nullptr) { ++ si = somain; ++ } else if (!find_libraries(nullptr, &name, 1, &si, nullptr, 0, rtld_flags, extinfo)) { ++ return nullptr; ++ } ++ ++ return si; ++} ++ ++static void soinfo_unload(soinfo* root) { ++ // Note that the library can be loaded but not linked; ++ // in which case there is no root but we still need ++ // to walk the tree and unload soinfos involved. ++ // ++ // This happens on unsuccessful dlopen, when one of ++ // the DT_NEEDED libraries could not be linked/found. ++ if (root->is_linked()) { ++ root = root->get_local_group_root(); ++ } ++ ++ if (!root->can_unload()) { ++ TRACE("not unloading '%s' - the binary is flagged with NODELETE", root->get_realpath()); ++ return; ++ } ++ ++ size_t ref_count = root->is_linked() ? root->decrement_ref_count() : 0; ++ ++ if (ref_count == 0) { ++ soinfo::soinfo_list_t local_unload_list; ++ soinfo::soinfo_list_t external_unload_list; ++ soinfo::soinfo_list_t depth_first_list; ++ depth_first_list.push_back(root); ++ soinfo* si = nullptr; ++ ++ while ((si = depth_first_list.pop_front()) != nullptr) { ++ if (local_unload_list.contains(si)) { ++ continue; ++ } ++ ++ local_unload_list.push_back(si); ++ ++ if (si->has_min_version(0)) { ++ soinfo* child = nullptr; ++ while ((child = si->get_children().pop_front()) != nullptr) { ++ TRACE("%s@%p needs to unload %s@%p", si->get_realpath(), si, ++ child->get_realpath(), child); ++ ++ if (local_unload_list.contains(child)) { ++ continue; ++ } else if (child->is_linked() && child->get_local_group_root() != root) { ++ external_unload_list.push_back(child); ++ } else { ++ depth_first_list.push_front(child); ++ } ++ } ++ } else { ++#if !defined(__work_around_b_19059885__) ++ __libc_fatal("soinfo for \"%s\"@%p has no version", si->get_realpath(), si); ++#else ++ PRINT("warning: soinfo for \"%s\"@%p has no version", si->get_realpath(), si); ++ for_each_dt_needed(si, [&] (const char* library_name) { ++ TRACE("deprecated (old format of soinfo): %s needs to unload %s", ++ si->get_realpath(), library_name); ++ ++ soinfo* needed = find_library(library_name, RTLD_NOLOAD, nullptr); ++ if (needed != nullptr) { ++ // Not found: for example if symlink was deleted between dlopen and dlclose ++ // Since we cannot really handle errors at this point - print and continue. ++ PRINT("warning: couldn't find %s needed by %s on unload.", ++ library_name, si->get_realpath()); ++ return; ++ } else if (local_unload_list.contains(needed)) { ++ // already visited ++ return; ++ } else if (needed->is_linked() && needed->get_local_group_root() != root) { ++ // external group ++ external_unload_list.push_back(needed); ++ } else { ++ // local group ++ depth_first_list.push_front(needed); ++ } ++ }); ++#endif ++ } ++ } ++ ++ local_unload_list.for_each([](soinfo* si) { ++ si->call_destructors(); ++ }); ++ ++ while ((si = local_unload_list.pop_front()) != nullptr) { ++ notify_gdb_of_unload(si); ++ soinfo_free(si); ++ } ++ ++ while ((si = external_unload_list.pop_front()) != nullptr) { ++ soinfo_unload(si); ++ } ++ } else { ++ TRACE("not unloading '%s' group, decrementing ref_count to %zd", ++ root->get_realpath(), ref_count); ++ } ++} ++ ++void do_android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) { ++ // Use basic string manipulation calls to avoid snprintf. ++ // snprintf indirectly calls pthread_getspecific to get the size of a buffer. ++ // When debug malloc is enabled, this call returns 0. This in turn causes ++ // snprintf to do nothing, which causes libraries to fail to load. ++ // See b/17302493 for further details. ++ // Once the above bug is fixed, this code can be modified to use ++ // snprintf again. ++ size_t required_len = strlen(kDefaultLdPaths[0]) + strlen(kDefaultLdPaths[1]) + 2; ++ if (buffer_size < required_len) { ++ __libc_fatal("android_get_LD_LIBRARY_PATH failed, buffer too small: " ++ "buffer len %zu, required len %zu", buffer_size, required_len); ++ } ++ char* end = stpcpy(buffer, kDefaultLdPaths[0]); ++ *end = ':'; ++ strcpy(end + 1, kDefaultLdPaths[1]); ++} ++ ++void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path) { ++ parse_LD_LIBRARY_PATH(ld_library_path); ++} ++ ++soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo) { ++ if ((flags & ~(RTLD_NOW|RTLD_LAZY|RTLD_LOCAL|RTLD_GLOBAL|RTLD_NODELETE|RTLD_NOLOAD)) != 0) { ++ DL_ERR("invalid flags to dlopen: %x", flags); ++ return nullptr; ++ } ++ if (extinfo != nullptr) { ++ if ((extinfo->flags & ~(ANDROID_DLEXT_VALID_FLAG_BITS)) != 0) { ++ DL_ERR("invalid extended flags to android_dlopen_ext: 0x%" PRIx64, extinfo->flags); ++ return nullptr; ++ } ++ if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) == 0 && ++ (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) { ++ DL_ERR("invalid extended flag combination (ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET without " ++ "ANDROID_DLEXT_USE_LIBRARY_FD): 0x%" PRIx64, extinfo->flags); ++ return nullptr; ++ } ++ } ++ ++ ProtectedDataGuard guard; ++ soinfo* si = find_library(name, flags, extinfo); ++ if (si != nullptr) { ++ si->call_constructors(); ++ } ++ return si; ++} ++ ++void do_dlclose(soinfo* si) { ++ ProtectedDataGuard guard; ++ soinfo_unload(si); ++} ++ ++static ElfW(Addr) call_ifunc_resolver(ElfW(Addr) resolver_addr) { ++ typedef ElfW(Addr) (*ifunc_resolver_t)(void); ++ ifunc_resolver_t ifunc_resolver = reinterpret_cast(resolver_addr); ++ ElfW(Addr) ifunc_addr = ifunc_resolver(); ++ TRACE_TYPE(RELO, "Called ifunc_resolver@%p. The result is %p", ++ ifunc_resolver, reinterpret_cast(ifunc_addr)); ++ ++ return ifunc_addr; ++} ++ ++const version_info* VersionTracker::get_version_info(ElfW(Versym) source_symver) const { ++ if (source_symver < 2 || ++ source_symver >= version_infos.size() || ++ version_infos[source_symver].name == nullptr) { ++ return nullptr; ++ } ++ ++ return &version_infos[source_symver]; ++} ++ ++void VersionTracker::add_version_info(size_t source_index, ++ ElfW(Word) elf_hash, ++ const char* ver_name, ++ const soinfo* target_si) { ++ if (source_index >= version_infos.size()) { ++ version_infos.resize(source_index+1); ++ } ++ ++ version_infos[source_index].elf_hash = elf_hash; ++ version_infos[source_index].name = ver_name; ++ version_infos[source_index].target_si = target_si; ++} ++ ++bool VersionTracker::init_verneed(const soinfo* si_from) { ++ uintptr_t verneed_ptr = si_from->get_verneed_ptr(); ++ ++ if (verneed_ptr == 0) { ++ return true; ++ } ++ ++ size_t verneed_cnt = si_from->get_verneed_cnt(); ++ ++ for (size_t i = 0, offset = 0; i(verneed_ptr + offset); ++ size_t vernaux_offset = offset + verneed->vn_aux; ++ offset += verneed->vn_next; ++ ++ if (verneed->vn_version != 1) { ++ DL_ERR("unsupported verneed[%zd] vn_version: %d (expected 1)", i, verneed->vn_version); ++ return false; ++ } ++ ++ const char* target_soname = si_from->get_string(verneed->vn_file); ++ // find it in dependencies ++ soinfo* target_si = si_from->get_children().find_if([&](const soinfo* si) { ++ return si->get_soname() != nullptr && strcmp(si->get_soname(), target_soname) == 0; ++ }); ++ ++ if (target_si == nullptr) { ++ DL_ERR("cannot find \"%s\" from verneed[%zd] in DT_NEEDED list for \"%s\"", ++ target_soname, i, si_from->get_realpath()); ++ return false; ++ } ++ ++ for (size_t j = 0; jvn_cnt; ++j) { ++ const ElfW(Vernaux)* vernaux = reinterpret_cast(verneed_ptr + vernaux_offset); ++ vernaux_offset += vernaux->vna_next; ++ ++ const ElfW(Word) elf_hash = vernaux->vna_hash; ++ const char* ver_name = si_from->get_string(vernaux->vna_name); ++ ElfW(Half) source_index = vernaux->vna_other; ++ ++ add_version_info(source_index, elf_hash, ver_name, target_si); ++ } ++ } ++ ++ return true; ++} ++ ++bool VersionTracker::init_verdef(const soinfo* si_from) { ++ return for_each_verdef(si_from, ++ [&](size_t, const ElfW(Verdef)* verdef, const ElfW(Verdaux)* verdaux) { ++ add_version_info(verdef->vd_ndx, verdef->vd_hash, ++ si_from->get_string(verdaux->vda_name), si_from); ++ return false; ++ } ++ ); ++} ++ ++bool VersionTracker::init(const soinfo* si_from) { ++ if (!si_from->has_min_version(2)) { ++ return true; ++ } ++ ++ return init_verneed(si_from) && init_verdef(si_from); ++} ++ ++bool soinfo::lookup_version_info(const VersionTracker& version_tracker, ElfW(Word) sym, ++ const char* sym_name, const version_info** vi) { ++ const ElfW(Versym)* sym_ver_ptr = get_versym(sym); ++ ElfW(Versym) sym_ver = sym_ver_ptr == nullptr ? 0 : *sym_ver_ptr; ++ ++ if (sym_ver != VER_NDX_LOCAL && sym_ver != VER_NDX_GLOBAL) { ++ *vi = version_tracker.get_version_info(sym_ver); ++ ++ if (*vi == nullptr) { ++ DL_ERR("cannot find verneed/verdef for version index=%d " ++ "referenced by symbol \"%s\" at \"%s\"", sym_ver, sym_name, get_realpath()); ++ return false; ++ } ++ } else { ++ // there is no version info ++ *vi = nullptr; ++ } ++ ++ return true; ++} ++ ++#if !defined(__mips__) ++#if defined(USE_RELA) ++static ElfW(Addr) get_addend(ElfW(Rela)* rela, ElfW(Addr) reloc_addr ) { ++ return rela->r_addend; ++} ++#else ++static ElfW(Addr) get_addend(ElfW(Rel)* rel, ElfW(Addr) reloc_addr) { ++ if (ELFW(R_TYPE)(rel->r_info) == R_GENERIC_RELATIVE || ++ ELFW(R_TYPE)(rel->r_info) == R_GENERIC_IRELATIVE) { ++ return *reinterpret_cast(reloc_addr); ++ } ++ return 0; ++} ++#endif ++ ++template ++bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& rel_iterator, ++ const soinfo_list_t& global_group, const soinfo_list_t& local_group) { ++ for (size_t idx = 0; rel_iterator.has_next(); ++idx) { ++ const auto rel = rel_iterator.next(); ++ if (rel == nullptr) { ++ return false; ++ } ++ ++ ElfW(Word) type = ELFW(R_TYPE)(rel->r_info); ++ ElfW(Word) sym = ELFW(R_SYM)(rel->r_info); ++ ++ ElfW(Addr) reloc = static_cast(rel->r_offset + load_bias); ++ ElfW(Addr) sym_addr = 0; ++ const char* sym_name = nullptr; ++ ElfW(Addr) addend = get_addend(rel, reloc); ++ ++ DEBUG("Processing '%s' relocation at index %zd", get_realpath(), idx); ++ if (type == R_GENERIC_NONE) { ++ continue; ++ } ++ ++ const ElfW(Sym)* s = nullptr; ++ soinfo* lsi = nullptr; ++ ++ if (sym != 0) { ++ sym_name = get_string(symtab_[sym].st_name); ++ const version_info* vi = nullptr; ++ ++ sym_addr = reinterpret_cast(_get_hooked_symbol(sym_name, get_realpath())); ++ if (!sym_addr) { ++ if (!lookup_version_info(version_tracker, sym, sym_name, &vi)) { ++ return false; ++ } ++ ++ if (!soinfo_do_lookup(this, sym_name, vi, &lsi, global_group, local_group, &s)) { ++ return false; ++ } ++ } ++ ++ if (sym_addr == 0 && s == nullptr) { ++ // We only allow an undefined symbol if this is a weak reference... ++ s = &symtab_[sym]; ++ if (ELF_ST_BIND(s->st_info) != STB_WEAK) { ++ DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...", sym_name, get_realpath()); ++ return false; ++ } ++ ++ /* IHI0044C AAELF 4.5.1.1: ++ ++ Libraries are not searched to resolve weak references. ++ It is not an error for a weak reference to remain unsatisfied. ++ ++ During linking, the value of an undefined weak reference is: ++ - Zero if the relocation type is absolute ++ - The address of the place if the relocation is pc-relative ++ - The address of nominal base address if the relocation ++ type is base-relative. ++ */ ++ ++ switch (type) { ++ case R_GENERIC_JUMP_SLOT: ++ case R_GENERIC_GLOB_DAT: ++ case R_GENERIC_RELATIVE: ++ case R_GENERIC_IRELATIVE: ++#if defined(__aarch64__) ++ case R_AARCH64_ABS64: ++ case R_AARCH64_ABS32: ++ case R_AARCH64_ABS16: ++#elif defined(__x86_64__) ++ case R_X86_64_32: ++ case R_X86_64_64: ++#elif defined(__arm__) ++ case R_ARM_ABS32: ++#elif defined(__i386__) ++ case R_386_32: ++#endif ++ /* ++ * The sym_addr was initialized to be zero above, or the relocation ++ * code below does not care about value of sym_addr. ++ * No need to do anything. ++ */ ++ break; +#if defined(__x86_64__) -+typedef Elf64_Ehdr Elf_Ehdr; -+typedef Elf64_Shdr Elf_Shdr; -+typedef Elf64_Sym Elf_Sym; -+typedef Elf64_Addr Elf_Addr; -+typedef Elf64_Phdr Elf_Phdr; -+typedef Elf64_Half Elf_Half; -+typedef Elf64_Rel Elf_Rel; -+typedef Elf64_Rela Elf_Rela; ++ case R_X86_64_PC32: ++ sym_addr = reloc; ++ break; ++#elif defined(__i386__) ++ case R_386_PC32: ++ sym_addr = reloc; ++ break; ++#endif ++ default: ++ DL_ERR("unknown weak reloc type %d @ %p (%zu)", type, rel, idx); ++ return false; ++ } ++ } else if (sym_addr == 0) { // We got a definition. ++#if !defined(__LP64__) ++ // When relocating dso with text_relocation .text segment is ++ // not executable. We need to restore elf flags before resolving ++ // STT_GNU_IFUNC symbol. ++ bool protect_segments = has_text_relocations && ++ lsi == this && ++ ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC; ++ if (protect_segments) { ++ if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) { ++ DL_ERR("can't protect segments for \"%s\": %s", ++ get_realpath(), strerror(errno)); ++ return false; ++ } ++ } ++#endif ++ sym_addr = lsi->resolve_symbol_address(s); ++#if !defined(__LP64__) ++ if (protect_segments) { ++ if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) { ++ DL_ERR("can't unprotect loadable segments for \"%s\": %s", ++ get_realpath(), strerror(errno)); ++ return false; ++ } ++ } ++#endif ++ } ++ count_relocation(kRelocSymbol); ++ } ++ ++ switch (type) { ++ case R_GENERIC_JUMP_SLOT: ++ count_relocation(kRelocAbsolute); ++ MARK(rel->r_offset); ++ TRACE_TYPE(RELO, "RELO JMP_SLOT %16p <- %16p %s\n", ++ reinterpret_cast(reloc), ++ reinterpret_cast(sym_addr + addend), sym_name); ++ ++ *reinterpret_cast(reloc) = (sym_addr + addend); ++ break; ++ case R_GENERIC_GLOB_DAT: ++ count_relocation(kRelocAbsolute); ++ MARK(rel->r_offset); ++ TRACE_TYPE(RELO, "RELO GLOB_DAT %16p <- %16p %s\n", ++ reinterpret_cast(reloc), ++ reinterpret_cast(sym_addr + addend), sym_name); ++ *reinterpret_cast(reloc) = (sym_addr + addend); ++ break; ++ case R_GENERIC_RELATIVE: ++ count_relocation(kRelocRelative); ++ MARK(rel->r_offset); ++ TRACE_TYPE(RELO, "RELO RELATIVE %16p <- %16p\n", ++ reinterpret_cast(reloc), ++ reinterpret_cast(load_bias + addend)); ++ *reinterpret_cast(reloc) = (load_bias + addend); ++ break; ++ case R_GENERIC_IRELATIVE: ++ count_relocation(kRelocRelative); ++ MARK(rel->r_offset); ++ TRACE_TYPE(RELO, "RELO IRELATIVE %16p <- %16p\n", ++ reinterpret_cast(reloc), ++ reinterpret_cast(load_bias + addend)); ++ { ++#if !defined(__LP64__) ++ // When relocating dso with text_relocation .text segment is ++ // not executable. We need to restore elf flags for this ++ // particular call. ++ if (has_text_relocations) { ++ if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) { ++ DL_ERR("can't protect segments for \"%s\": %s", ++ get_realpath(), strerror(errno)); ++ return false; ++ } ++ } ++#endif ++ ElfW(Addr) ifunc_addr = call_ifunc_resolver(load_bias + addend); ++#if !defined(__LP64__) ++ // Unprotect it afterwards... ++ if (has_text_relocations) { ++ if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) { ++ DL_ERR("can't unprotect loadable segments for \"%s\": %s", ++ get_realpath(), strerror(errno)); ++ return false; ++ } ++ } ++#endif ++ *reinterpret_cast(reloc) = ifunc_addr; ++ } ++ break; ++ ++#if defined(__aarch64__) ++ case R_AARCH64_ABS64: ++ count_relocation(kRelocAbsolute); ++ MARK(rel->r_offset); ++ TRACE_TYPE(RELO, "RELO ABS64 %16llx <- %16llx %s\n", ++ reloc, (sym_addr + addend), sym_name); ++ *reinterpret_cast(reloc) += (sym_addr + addend); ++ break; ++ case R_AARCH64_ABS32: ++ count_relocation(kRelocAbsolute); ++ MARK(rel->r_offset); ++ TRACE_TYPE(RELO, "RELO ABS32 %16llx <- %16llx %s\n", ++ reloc, (sym_addr + addend), sym_name); ++ { ++ const ElfW(Addr) reloc_value = *reinterpret_cast(reloc); ++ const ElfW(Addr) min_value = static_cast(INT32_MIN); ++ const ElfW(Addr) max_value = static_cast(UINT32_MAX); ++ if ((min_value <= (reloc_value + (sym_addr + addend))) && ++ ((reloc_value + (sym_addr + addend)) <= max_value)) { ++ *reinterpret_cast(reloc) += (sym_addr + addend); ++ } else { ++ DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx", ++ (reloc_value + (sym_addr + addend)), min_value, max_value); ++ return false; ++ } ++ } ++ break; ++ case R_AARCH64_ABS16: ++ count_relocation(kRelocAbsolute); ++ MARK(rel->r_offset); ++ TRACE_TYPE(RELO, "RELO ABS16 %16llx <- %16llx %s\n", ++ reloc, (sym_addr + addend), sym_name); ++ { ++ const ElfW(Addr) reloc_value = *reinterpret_cast(reloc); ++ const ElfW(Addr) min_value = static_cast(INT16_MIN); ++ const ElfW(Addr) max_value = static_cast(UINT16_MAX); ++ if ((min_value <= (reloc_value + (sym_addr + addend))) && ++ ((reloc_value + (sym_addr + addend)) <= max_value)) { ++ *reinterpret_cast(reloc) += (sym_addr + addend); ++ } else { ++ DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx", ++ reloc_value + (sym_addr + addend), min_value, max_value); ++ return false; ++ } ++ } ++ break; ++ case R_AARCH64_PREL64: ++ count_relocation(kRelocRelative); ++ MARK(rel->r_offset); ++ TRACE_TYPE(RELO, "RELO REL64 %16llx <- %16llx - %16llx %s\n", ++ reloc, (sym_addr + addend), rel->r_offset, sym_name); ++ *reinterpret_cast(reloc) += (sym_addr + addend) - rel->r_offset; ++ break; ++ case R_AARCH64_PREL32: ++ count_relocation(kRelocRelative); ++ MARK(rel->r_offset); ++ TRACE_TYPE(RELO, "RELO REL32 %16llx <- %16llx - %16llx %s\n", ++ reloc, (sym_addr + addend), rel->r_offset, sym_name); ++ { ++ const ElfW(Addr) reloc_value = *reinterpret_cast(reloc); ++ const ElfW(Addr) min_value = static_cast(INT32_MIN); ++ const ElfW(Addr) max_value = static_cast(UINT32_MAX); ++ if ((min_value <= (reloc_value + ((sym_addr + addend) - rel->r_offset))) && ++ ((reloc_value + ((sym_addr + addend) - rel->r_offset)) <= max_value)) { ++ *reinterpret_cast(reloc) += ((sym_addr + addend) - rel->r_offset); ++ } else { ++ DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx", ++ reloc_value + ((sym_addr + addend) - rel->r_offset), min_value, max_value); ++ return false; ++ } ++ } ++ break; ++ case R_AARCH64_PREL16: ++ count_relocation(kRelocRelative); ++ MARK(rel->r_offset); ++ TRACE_TYPE(RELO, "RELO REL16 %16llx <- %16llx - %16llx %s\n", ++ reloc, (sym_addr + addend), rel->r_offset, sym_name); ++ { ++ const ElfW(Addr) reloc_value = *reinterpret_cast(reloc); ++ const ElfW(Addr) min_value = static_cast(INT16_MIN); ++ const ElfW(Addr) max_value = static_cast(UINT16_MAX); ++ if ((min_value <= (reloc_value + ((sym_addr + addend) - rel->r_offset))) && ++ ((reloc_value + ((sym_addr + addend) - rel->r_offset)) <= max_value)) { ++ *reinterpret_cast(reloc) += ((sym_addr + addend) - rel->r_offset); ++ } else { ++ DL_ERR("0x%016llx out of range 0x%016llx to 0x%016llx", ++ reloc_value + ((sym_addr + addend) - rel->r_offset), min_value, max_value); ++ return false; ++ } ++ } ++ break; ++ ++ case R_AARCH64_COPY: ++ /* ++ * ET_EXEC is not supported so this should not happen. ++ * ++ * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf ++ * ++ * Section 4.6.11 "Dynamic relocations" ++ * R_AARCH64_COPY may only appear in executable objects where e_type is ++ * set to ET_EXEC. ++ */ ++ DL_ERR("%s R_AARCH64_COPY relocations are not supported", get_realpath()); ++ return false; ++ case R_AARCH64_TLS_TPREL: ++ TRACE_TYPE(RELO, "RELO TLS_TPREL *** %16llx <- %16llx - %16llx\n", ++ reloc, (sym_addr + addend), rel->r_offset); ++ break; ++ case R_AARCH64_TLS_DTPREL: ++ TRACE_TYPE(RELO, "RELO TLS_DTPREL *** %16llx <- %16llx - %16llx\n", ++ reloc, (sym_addr + addend), rel->r_offset); ++ break; ++#elif defined(__x86_64__) ++ case R_X86_64_32: ++ count_relocation(kRelocRelative); ++ MARK(rel->r_offset); ++ TRACE_TYPE(RELO, "RELO R_X86_64_32 %08zx <- +%08zx %s", static_cast(reloc), ++ static_cast(sym_addr), sym_name); ++ *reinterpret_cast(reloc) = sym_addr + addend; ++ break; ++ case R_X86_64_64: ++ count_relocation(kRelocRelative); ++ MARK(rel->r_offset); ++ TRACE_TYPE(RELO, "RELO R_X86_64_64 %08zx <- +%08zx %s", static_cast(reloc), ++ static_cast(sym_addr), sym_name); ++ *reinterpret_cast(reloc) = sym_addr + addend; ++ break; ++ case R_X86_64_PC32: ++ count_relocation(kRelocRelative); ++ MARK(rel->r_offset); ++ TRACE_TYPE(RELO, "RELO R_X86_64_PC32 %08zx <- +%08zx (%08zx - %08zx) %s", ++ static_cast(reloc), static_cast(sym_addr - reloc), ++ static_cast(sym_addr), static_cast(reloc), sym_name); ++ *reinterpret_cast(reloc) = sym_addr + addend - reloc; ++ break; ++#elif defined(__arm__) ++ case R_ARM_ABS32: ++ count_relocation(kRelocAbsolute); ++ MARK(rel->r_offset); ++ TRACE_TYPE(RELO, "RELO ABS %08x <- %08x %s", reloc, sym_addr, sym_name); ++ *reinterpret_cast(reloc) += sym_addr; ++ break; ++ case R_ARM_REL32: ++ count_relocation(kRelocRelative); ++ MARK(rel->r_offset); ++ TRACE_TYPE(RELO, "RELO REL32 %08x <- %08x - %08x %s", ++ reloc, sym_addr, rel->r_offset, sym_name); ++ *reinterpret_cast(reloc) += sym_addr - rel->r_offset; ++ break; ++ case R_ARM_COPY: ++ /* ++ * ET_EXEC is not supported so this should not happen. ++ * ++ * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044d/IHI0044D_aaelf.pdf ++ * ++ * Section 4.6.1.10 "Dynamic relocations" ++ * R_ARM_COPY may only appear in executable objects where e_type is ++ * set to ET_EXEC. ++ */ ++ DL_ERR("%s R_ARM_COPY relocations are not supported", get_realpath()); ++ return false; ++#elif defined(__i386__) ++ case R_386_32: ++ count_relocation(kRelocRelative); ++ MARK(rel->r_offset); ++ TRACE_TYPE(RELO, "RELO R_386_32 %08x <- +%08x %s", reloc, sym_addr, sym_name); ++ *reinterpret_cast(reloc) += sym_addr; ++ break; ++ case R_386_PC32: ++ count_relocation(kRelocRelative); ++ MARK(rel->r_offset); ++ TRACE_TYPE(RELO, "RELO R_386_PC32 %08x <- +%08x (%08x - %08x) %s", ++ reloc, (sym_addr - reloc), sym_addr, reloc, sym_name); ++ *reinterpret_cast(reloc) += (sym_addr - reloc); ++ break; ++#endif ++ default: ++ DL_ERR("unknown reloc type %d @ %p (%zu)", type, rel, idx); ++ return false; ++ } ++ } ++ return true; ++} ++#endif // !defined(__mips__) ++ ++void soinfo::call_array(const char* array_name , linker_function_t* functions, ++ size_t count, bool reverse) { ++ if (functions == nullptr) { ++ return; ++ } ++ ++ TRACE("[ Calling %s (size %zd) @ %p for '%s' ]", array_name, count, functions, get_realpath()); ++ ++ int begin = reverse ? (count - 1) : 0; ++ int end = reverse ? -1 : count; ++ int step = reverse ? -1 : 1; ++ ++ for (int i = begin; i != end; i += step) { ++ TRACE("[ %s[%d] == %p ]", array_name, i, functions[i]); ++ call_function("function", functions[i]); ++ } ++ ++ TRACE("[ Done calling %s for '%s' ]", array_name, get_realpath()); ++} ++ ++void soinfo::call_function(const char* function_name , linker_function_t function) { ++ if (function == nullptr || reinterpret_cast(function) == static_cast(-1)) { ++ return; ++ } ++ ++ TRACE("[ Calling %s @ %p for '%s' ]", function_name, function, get_realpath()); ++ function(); ++ TRACE("[ Done calling %s @ %p for '%s' ]", function_name, function, get_realpath()); ++} ++ ++void soinfo::call_pre_init_constructors() { ++ // DT_PREINIT_ARRAY functions are called before any other constructors for executables, ++ // but ignored in a shared library. ++ call_array("DT_PREINIT_ARRAY", preinit_array_, preinit_array_count_, false); ++} ++ ++void soinfo::call_constructors() { ++ if (constructors_called) { ++ return; ++ } ++ ++ if (strcmp(soname_, "libc.so") == 0) { ++ DEBUG("HYBRIS: =============> Skipping libc.so\n"); ++ return; ++ } ++ ++ // We set constructors_called before actually calling the constructors, otherwise it doesn't ++ // protect against recursive constructor calls. One simple example of constructor recursion ++ // is the libc debug malloc, which is implemented in libc_malloc_debug_leak.so: ++ // 1. The program depends on libc, so libc's constructor is called here. ++ // 2. The libc constructor calls dlopen() to load libc_malloc_debug_leak.so. ++ // 3. dlopen() calls the constructors on the newly created ++ // soinfo for libc_malloc_debug_leak.so. ++ // 4. The debug .so depends on libc, so CallConstructors is ++ // called again with the libc soinfo. If it doesn't trigger the early- ++ // out above, the libc constructor will be called again (recursively!). ++ constructors_called = true; ++ ++ if (!is_main_executable() && preinit_array_ != nullptr) { ++ // The GNU dynamic linker silently ignores these, but we warn the developer. ++ PRINT("\"%s\": ignoring %zd-entry DT_PREINIT_ARRAY in shared library!", ++ get_realpath(), preinit_array_count_); ++ } ++ ++ get_children().for_each([] (soinfo* si) { ++ si->call_constructors(); ++ }); ++ ++ TRACE("\"%s\": calling constructors", get_realpath()); ++ ++ // DT_INIT should be called before DT_INIT_ARRAY if both are present. ++ call_function("DT_INIT", init_func_); ++ call_array("DT_INIT_ARRAY", init_array_, init_array_count_, false); ++} ++ ++void soinfo::call_destructors() { ++ if (!constructors_called) { ++ return; ++ } ++ TRACE("\"%s\": calling destructors", get_realpath()); ++ ++ // DT_FINI_ARRAY must be parsed in reverse order. ++ call_array("DT_FINI_ARRAY", fini_array_, fini_array_count_, true); ++ ++ // DT_FINI should be called after DT_FINI_ARRAY if both are present. ++ call_function("DT_FINI", fini_func_); ++ ++ // This is needed on second call to dlopen ++ // after library has been unloaded with RTLD_NODELETE ++ constructors_called = false; ++} ++ ++void soinfo::add_child(soinfo* child) { ++ if (has_min_version(0)) { ++ child->parents_.push_back(this); ++ this->children_.push_back(child); ++ } ++} ++ ++void soinfo::remove_all_links() { ++ if (!has_min_version(0)) { ++ return; ++ } ++ ++ // 1. Untie connected soinfos from 'this'. ++ children_.for_each([&] (soinfo* child) { ++ child->parents_.remove_if([&] (const soinfo* parent) { ++ return parent == this; ++ }); ++ }); ++ ++ parents_.for_each([&] (soinfo* parent) { ++ parent->children_.remove_if([&] (const soinfo* child) { ++ return child == this; ++ }); ++ }); ++ ++ // 2. Once everything untied - clear local lists. ++ parents_.clear(); ++ children_.clear(); ++} ++ ++dev_t soinfo::get_st_dev() const { ++ if (has_min_version(0)) { ++ return st_dev_; ++ } ++ ++ return 0; ++}; ++ ++ino_t soinfo::get_st_ino() const { ++ if (has_min_version(0)) { ++ return st_ino_; ++ } ++ ++ return 0; ++} ++ ++off64_t soinfo::get_file_offset() const { ++ if (has_min_version(1)) { ++ return file_offset_; ++ } ++ ++ return 0; ++} ++ ++uint32_t soinfo::get_rtld_flags() const { ++ if (has_min_version(1)) { ++ return rtld_flags_; ++ } ++ ++ return 0; ++} ++ ++uint32_t soinfo::get_dt_flags_1() const { ++ if (has_min_version(1)) { ++ return dt_flags_1_; ++ } ++ ++ return 0; ++} ++ ++void soinfo::set_dt_flags_1(uint32_t dt_flags_1) { ++ if (has_min_version(1)) { ++ if ((dt_flags_1 & DF_1_GLOBAL) != 0) { ++ rtld_flags_ |= RTLD_GLOBAL; ++ } ++ ++ if ((dt_flags_1 & DF_1_NODELETE) != 0) { ++ rtld_flags_ |= RTLD_NODELETE; ++ } ++ ++ dt_flags_1_ = dt_flags_1; ++ } ++} ++ ++const char* soinfo::get_realpath() const { ++#if defined(__work_around_b_19059885__) ++ if (has_min_version(2)) { ++ return realpath_.c_str(); ++ } else { ++ return old_name_; ++ } ++#else ++ return realpath_.c_str(); ++#endif ++} ++ ++const char* soinfo::get_soname() const { ++#if defined(__work_around_b_19059885__) ++ if (has_min_version(2)) { ++ return soname_; ++ } else { ++ return old_name_; ++ } ++#else ++ return soname_; ++#endif ++} ++ ++// This is a return on get_children()/get_parents() if ++// 'this->flags' does not have FLAG_NEW_SOINFO set. ++static soinfo::soinfo_list_t g_empty_list; ++ ++soinfo::soinfo_list_t& soinfo::get_children() { ++ if (has_min_version(0)) { ++ return children_; ++ } ++ ++ return g_empty_list; ++} ++ ++const soinfo::soinfo_list_t& soinfo::get_children() const { ++ if (has_min_version(0)) { ++ return children_; ++ } ++ ++ return g_empty_list; ++} ++ ++soinfo::soinfo_list_t& soinfo::get_parents() { ++ if (has_min_version(0)) { ++ return parents_; ++ } ++ ++ return g_empty_list; ++} ++ ++ElfW(Addr) soinfo::resolve_symbol_address(const ElfW(Sym)* s) const { ++ if (ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC) { ++ return call_ifunc_resolver(s->st_value + load_bias); ++ } ++ ++ return static_cast(s->st_value + load_bias); ++} ++ ++const char* soinfo::get_string(ElfW(Word) index) const { ++ if (has_min_version(1) && (index >= strtab_size_)) { ++ __libc_fatal("%s: strtab out of bounds error; STRSZ=%zd, name=%d", ++ get_realpath(), strtab_size_, index); ++ } ++ ++ return strtab_ + index; ++} ++ ++bool soinfo::is_gnu_hash() const { ++ return (flags_ & FLAG_GNU_HASH) != 0; ++} ++ ++bool soinfo::can_unload() const { ++ return (get_rtld_flags() & (RTLD_NODELETE | RTLD_GLOBAL)) == 0; ++} ++ ++bool soinfo::is_linked() const { ++ return (flags_ & FLAG_LINKED) != 0; ++} ++ ++bool soinfo::is_main_executable() const { ++ return (flags_ & FLAG_EXE) != 0; ++} ++ ++void soinfo::set_linked() { ++ flags_ |= FLAG_LINKED; ++} ++ ++void soinfo::set_linker_flag() { ++ flags_ |= FLAG_LINKER; ++} ++ ++void soinfo::set_main_executable() { ++ flags_ |= FLAG_EXE; ++} ++ ++void soinfo::increment_ref_count() { ++ local_group_root_->ref_count_++; ++} ++ ++size_t soinfo::decrement_ref_count() { ++ return --local_group_root_->ref_count_; ++} ++ ++soinfo* soinfo::get_local_group_root() const { ++ return local_group_root_; ++} ++ ++// This function returns api-level at the time of ++// dlopen/load. Note that libraries opened by system ++// will always have 'current' api level. ++uint32_t soinfo::get_target_sdk_version() const { ++ if (!has_min_version(2)) { ++ return __ANDROID_API__; ++ } ++ ++ return local_group_root_->target_sdk_version_; ++} ++ ++bool soinfo::prelink_image() { ++ /* Extract dynamic section */ ++ ElfW(Word) dynamic_flags = 0; ++ phdr_table_get_dynamic_section(phdr, phnum, load_bias, &dynamic, &dynamic_flags); ++ ++ /* We can't log anything until the linker is relocated */ ++ bool relocating_linker = (flags_ & FLAG_LINKER) != 0; ++ if (!relocating_linker) { ++ INFO("[ linking %s ]", get_realpath()); ++ DEBUG("si->base = %p si->flags = 0x%08x", reinterpret_cast(base), flags_); ++ } ++ ++ if (dynamic == nullptr) { ++ if (!relocating_linker) { ++ DL_ERR("missing PT_DYNAMIC in \"%s\"", get_realpath()); ++ } ++ return false; ++ } else { ++ if (!relocating_linker) { ++ DEBUG("dynamic = %p", dynamic); ++ } ++ } ++ ++#if defined(__arm__) ++ (void) phdr_table_get_arm_exidx(phdr, phnum, load_bias, ++ &ARM_exidx, &ARM_exidx_count); ++#endif ++ ++ // Extract useful information from dynamic section. ++ // Note that: "Except for the DT_NULL element at the end of the array, ++ // and the relative order of DT_NEEDED elements, entries may appear in any order." ++ // ++ // source: http://www.sco.com/developers/gabi/1998-04-29/ch5.dynamic.html ++ uint32_t needed_count = 0; ++ for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) { ++ DEBUG("d = %p, d[0](tag) = %p d[1](val) = %p", ++ d, reinterpret_cast(d->d_tag), reinterpret_cast(d->d_un.d_val)); ++ switch (d->d_tag) { ++ case DT_SONAME: ++ // this is parsed after we have strtab initialized (see below). ++ break; ++ ++ case DT_HASH: ++ nbucket_ = reinterpret_cast(load_bias + d->d_un.d_ptr)[0]; ++ nchain_ = reinterpret_cast(load_bias + d->d_un.d_ptr)[1]; ++ bucket_ = reinterpret_cast(load_bias + d->d_un.d_ptr + 8); ++ chain_ = reinterpret_cast(load_bias + d->d_un.d_ptr + 8 + nbucket_ * 4); ++ break; ++ ++ case DT_GNU_HASH: ++ gnu_nbucket_ = reinterpret_cast(load_bias + d->d_un.d_ptr)[0]; ++ // skip symndx ++ gnu_maskwords_ = reinterpret_cast(load_bias + d->d_un.d_ptr)[2]; ++ gnu_shift2_ = reinterpret_cast(load_bias + d->d_un.d_ptr)[3]; ++ ++ gnu_bloom_filter_ = reinterpret_cast(load_bias + d->d_un.d_ptr + 16); ++ gnu_bucket_ = reinterpret_cast(gnu_bloom_filter_ + gnu_maskwords_); ++ // amend chain for symndx = header[1] ++ gnu_chain_ = gnu_bucket_ + gnu_nbucket_ - ++ reinterpret_cast(load_bias + d->d_un.d_ptr)[1]; ++ ++ if (!powerof2(gnu_maskwords_)) { ++ DL_ERR("invalid maskwords for gnu_hash = 0x%x, in \"%s\" expecting power to two", ++ gnu_maskwords_, get_realpath()); ++ return false; ++ } ++ --gnu_maskwords_; ++ ++ flags_ |= FLAG_GNU_HASH; ++ break; ++ ++ case DT_STRTAB: ++ strtab_ = reinterpret_cast(load_bias + d->d_un.d_ptr); ++ break; ++ ++ case DT_STRSZ: ++ strtab_size_ = d->d_un.d_val; ++ break; ++ ++ case DT_SYMTAB: ++ symtab_ = reinterpret_cast(load_bias + d->d_un.d_ptr); ++ break; ++ ++ case DT_SYMENT: ++ if (d->d_un.d_val != sizeof(ElfW(Sym))) { ++ DL_ERR("invalid DT_SYMENT: %zd in \"%s\"", ++ static_cast(d->d_un.d_val), get_realpath()); ++ return false; ++ } ++ break; ++ ++ case DT_PLTREL: ++#if defined(USE_RELA) ++ if (d->d_un.d_val != DT_RELA) { ++ DL_ERR("unsupported DT_PLTREL in \"%s\"; expected DT_RELA", get_realpath()); ++ return false; ++ } ++#else ++ if (d->d_un.d_val != DT_REL) { ++ DL_ERR("unsupported DT_PLTREL in \"%s\"; expected DT_REL", get_realpath()); ++ return false; ++ } ++#endif ++ break; ++ ++ case DT_JMPREL: ++#if defined(USE_RELA) ++ plt_rela_ = reinterpret_cast(load_bias + d->d_un.d_ptr); ++#else ++ plt_rel_ = reinterpret_cast(load_bias + d->d_un.d_ptr); ++#endif ++ break; ++ ++ case DT_PLTRELSZ: ++#if defined(USE_RELA) ++ plt_rela_count_ = d->d_un.d_val / sizeof(ElfW(Rela)); ++#else ++ plt_rel_count_ = d->d_un.d_val / sizeof(ElfW(Rel)); ++#endif ++ break; ++ ++ case DT_PLTGOT: ++#if defined(__mips__) ++ // Used by mips and mips64. ++ plt_got_ = reinterpret_cast(load_bias + d->d_un.d_ptr); ++#endif ++ // Ignore for other platforms... (because RTLD_LAZY is not supported) ++ break; ++ ++ case DT_DEBUG: ++ // Set the DT_DEBUG entry to the address of _r_debug for GDB ++ // if the dynamic table is writable ++// FIXME: not working currently for N64 ++// The flags for the LOAD and DYNAMIC program headers do not agree. ++// The LOAD section containing the dynamic table has been mapped as ++// read-only, but the DYNAMIC header claims it is writable. ++#if !(defined(__mips__) && defined(__LP64__)) ++ if ((dynamic_flags & PF_W) != 0) { ++ d->d_un.d_val = reinterpret_cast(&_r_debug); ++ } ++#endif ++ break; ++#if defined(USE_RELA) ++ case DT_RELA: ++ rela_ = reinterpret_cast(load_bias + d->d_un.d_ptr); ++ break; ++ ++ case DT_RELASZ: ++ rela_count_ = d->d_un.d_val / sizeof(ElfW(Rela)); ++ break; ++ ++ case DT_ANDROID_RELA: ++ android_relocs_ = reinterpret_cast(load_bias + d->d_un.d_ptr); ++ break; ++ ++ case DT_ANDROID_RELASZ: ++ android_relocs_size_ = d->d_un.d_val; ++ break; ++ ++ case DT_ANDROID_REL: ++ DL_ERR("unsupported DT_ANDROID_REL in \"%s\"", get_realpath()); ++ return false; ++ ++ case DT_ANDROID_RELSZ: ++ DL_ERR("unsupported DT_ANDROID_RELSZ in \"%s\"", get_realpath()); ++ return false; ++ ++ case DT_RELAENT: ++ if (d->d_un.d_val != sizeof(ElfW(Rela))) { ++ DL_ERR("invalid DT_RELAENT: %zd", static_cast(d->d_un.d_val)); ++ return false; ++ } ++ break; ++ ++ // ignored (see DT_RELCOUNT comments for details) ++ case DT_RELACOUNT: ++ break; ++ ++ case DT_REL: ++ DL_ERR("unsupported DT_REL in \"%s\"", get_realpath()); ++ return false; ++ ++ case DT_RELSZ: ++ DL_ERR("unsupported DT_RELSZ in \"%s\"", get_realpath()); ++ return false; ++ ++#else ++ case DT_REL: ++ rel_ = reinterpret_cast(load_bias + d->d_un.d_ptr); ++ break; ++ ++ case DT_RELSZ: ++ rel_count_ = d->d_un.d_val / sizeof(ElfW(Rel)); ++ break; ++ ++ case DT_RELENT: ++ if (d->d_un.d_val != sizeof(ElfW(Rel))) { ++ DL_ERR("invalid DT_RELENT: %zd", static_cast(d->d_un.d_val)); ++ return false; ++ } ++ break; ++ ++ case DT_ANDROID_REL: ++ android_relocs_ = reinterpret_cast(load_bias + d->d_un.d_ptr); ++ break; ++ ++ case DT_ANDROID_RELSZ: ++ android_relocs_size_ = d->d_un.d_val; ++ break; ++ ++ case DT_ANDROID_RELA: ++ DL_ERR("unsupported DT_ANDROID_RELA in \"%s\"", get_realpath()); ++ return false; ++ ++ case DT_ANDROID_RELASZ: ++ DL_ERR("unsupported DT_ANDROID_RELASZ in \"%s\"", get_realpath()); ++ return false; ++ ++ // "Indicates that all RELATIVE relocations have been concatenated together, ++ // and specifies the RELATIVE relocation count." ++ // ++ // TODO: Spec also mentions that this can be used to optimize relocation process; ++ // Not currently used by bionic linker - ignored. ++ case DT_RELCOUNT: ++ break; ++ ++ case DT_RELA: ++ DL_ERR("unsupported DT_RELA in \"%s\"", get_realpath()); ++ return false; ++ ++ case DT_RELASZ: ++ DL_ERR("unsupported DT_RELASZ in \"%s\"", get_realpath()); ++ return false; ++ ++#endif ++ case DT_INIT: ++ init_func_ = reinterpret_cast(load_bias + d->d_un.d_ptr); ++ DEBUG("%s constructors (DT_INIT) found at %p", get_realpath(), init_func_); ++ break; ++ ++ case DT_FINI: ++ fini_func_ = reinterpret_cast(load_bias + d->d_un.d_ptr); ++ DEBUG("%s destructors (DT_FINI) found at %p", get_realpath(), fini_func_); ++ break; ++ ++ case DT_INIT_ARRAY: ++ init_array_ = reinterpret_cast(load_bias + d->d_un.d_ptr); ++ DEBUG("%s constructors (DT_INIT_ARRAY) found at %p", get_realpath(), init_array_); ++ break; ++ ++ case DT_INIT_ARRAYSZ: ++ init_array_count_ = static_cast(d->d_un.d_val) / sizeof(ElfW(Addr)); ++ break; ++ ++ case DT_FINI_ARRAY: ++ fini_array_ = reinterpret_cast(load_bias + d->d_un.d_ptr); ++ DEBUG("%s destructors (DT_FINI_ARRAY) found at %p", get_realpath(), fini_array_); ++ break; ++ ++ case DT_FINI_ARRAYSZ: ++ fini_array_count_ = static_cast(d->d_un.d_val) / sizeof(ElfW(Addr)); ++ break; ++ ++ case DT_PREINIT_ARRAY: ++ preinit_array_ = reinterpret_cast(load_bias + d->d_un.d_ptr); ++ DEBUG("%s constructors (DT_PREINIT_ARRAY) found at %p", get_realpath(), preinit_array_); ++ break; ++ ++ case DT_PREINIT_ARRAYSZ: ++ preinit_array_count_ = static_cast(d->d_un.d_val) / sizeof(ElfW(Addr)); ++ break; ++ ++ case DT_TEXTREL: ++#if defined(__LP64__) ++ DL_ERR("text relocations (DT_TEXTREL) found in 64-bit ELF file \"%s\"", get_realpath()); ++ return false; ++#else ++ has_text_relocations = true; ++ break; ++#endif ++ ++ case DT_SYMBOLIC: ++ has_DT_SYMBOLIC = true; ++ break; ++ ++ case DT_NEEDED: ++ ++needed_count; ++ break; ++ ++ case DT_FLAGS: ++ if (d->d_un.d_val & DF_TEXTREL) { ++#if defined(__LP64__) ++ DL_ERR("text relocations (DF_TEXTREL) found in 64-bit ELF file \"%s\"", get_realpath()); ++ return false; ++#else ++ has_text_relocations = true; ++#endif ++ } ++ if (d->d_un.d_val & DF_SYMBOLIC) { ++ has_DT_SYMBOLIC = true; ++ } ++ break; ++ ++ case DT_FLAGS_1: ++ set_dt_flags_1(d->d_un.d_val); ++ ++ if ((d->d_un.d_val & ~SUPPORTED_DT_FLAGS_1) != 0) { ++ DL_WARN("%s: unsupported flags DT_FLAGS_1=%p", get_realpath(), reinterpret_cast(d->d_un.d_val)); ++ } ++ break; ++#if defined(__mips__) ++ case DT_MIPS_RLD_MAP: ++ // Set the DT_MIPS_RLD_MAP entry to the address of _r_debug for GDB. ++ { ++ r_debug** dp = reinterpret_cast(load_bias + d->d_un.d_ptr); ++ *dp = &_r_debug; ++ } ++ break; ++ case DT_MIPS_RLD_MAP2: ++ // Set the DT_MIPS_RLD_MAP2 entry to the address of _r_debug for GDB. ++ { ++ r_debug** dp = reinterpret_cast( ++ reinterpret_cast(d) + d->d_un.d_val); ++ *dp = &_r_debug; ++ } ++ break; ++ ++ case DT_MIPS_RLD_VERSION: ++ case DT_MIPS_FLAGS: ++ case DT_MIPS_BASE_ADDRESS: ++ case DT_MIPS_UNREFEXTNO: ++ break; ++ ++ case DT_MIPS_SYMTABNO: ++ mips_symtabno_ = d->d_un.d_val; ++ break; ++ ++ case DT_MIPS_LOCAL_GOTNO: ++ mips_local_gotno_ = d->d_un.d_val; ++ break; ++ ++ case DT_MIPS_GOTSYM: ++ mips_gotsym_ = d->d_un.d_val; ++ break; ++#endif ++ // Ignored: "Its use has been superseded by the DF_BIND_NOW flag" ++ case DT_BIND_NOW: ++ break; ++ ++ case DT_VERSYM: ++ versym_ = reinterpret_cast(load_bias + d->d_un.d_ptr); ++ break; ++ ++ case DT_VERDEF: ++ verdef_ptr_ = load_bias + d->d_un.d_ptr; ++ break; ++ case DT_VERDEFNUM: ++ verdef_cnt_ = d->d_un.d_val; ++ break; ++ ++ case DT_VERNEED: ++ verneed_ptr_ = load_bias + d->d_un.d_ptr; ++ break; ++ ++ case DT_VERNEEDNUM: ++ verneed_cnt_ = d->d_un.d_val; ++ break; ++ ++ default: ++ if (!relocating_linker) { ++ DL_WARN("%s: unused DT entry: type %p arg %p", get_realpath(), ++ reinterpret_cast(d->d_tag), reinterpret_cast(d->d_un.d_val)); ++ } ++ break; ++ } ++ } ++ ++ DEBUG("si->base = %p, si->strtab = %p, si->symtab = %p", ++ reinterpret_cast(base), strtab_, symtab_); ++ ++ // Sanity checks. ++ if (relocating_linker && needed_count != 0) { ++ DL_ERR("linker cannot have DT_NEEDED dependencies on other libraries"); ++ return false; ++ } ++ if (nbucket_ == 0 && gnu_nbucket_ == 0) { ++ DL_ERR("empty/missing DT_HASH/DT_GNU_HASH in \"%s\" " ++ "(new hash type from the future?)", get_realpath()); ++ return false; ++ } ++ if (strtab_ == 0) { ++ DL_ERR("empty/missing DT_STRTAB in \"%s\"", get_realpath()); ++ return false; ++ } ++ if (symtab_ == 0) { ++ DL_ERR("empty/missing DT_SYMTAB in \"%s\"", get_realpath()); ++ return false; ++ } ++ ++ // second pass - parse entries relying on strtab ++ for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) { ++ if (d->d_tag == DT_SONAME) { ++ soname_ = get_string(d->d_un.d_val); ++#if defined(__work_around_b_19059885__) ++ strlcpy(old_name_, soname_, sizeof(old_name_)); ++#endif ++ break; ++ } ++ } ++ ++ // Before M release linker was using basename in place of soname. ++ // In the case when dt_soname is absent some apps stop working ++ // because they can't find dt_needed library by soname. ++ // This workaround should keep them working. (applies only ++ // for apps targeting sdk version <=22). Make an exception for ++ // the main executable and linker; they do not need to have dt_soname ++ if (soname_ == nullptr && this != somain && (flags_ & FLAG_LINKER) == 0 && ++ get_application_target_sdk_version() <= 22) { ++ soname_ = basename(realpath_.c_str()); ++ DL_WARN("%s: is missing DT_SONAME will use basename as a replacement: \"%s\"", ++ get_realpath(), soname_); ++ } ++ return true; ++} ++ ++bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t& local_group, ++ const android_dlextinfo* extinfo) { ++ ++ local_group_root_ = local_group.front(); ++ if (local_group_root_ == nullptr) { ++ local_group_root_ = this; ++ } ++ ++ if ((flags_ & FLAG_LINKER) == 0 && local_group_root_ == this) { ++ target_sdk_version_ = get_application_target_sdk_version(); ++ } ++ ++ VersionTracker version_tracker; ++ ++ if (!version_tracker.init(this)) { ++ return false; ++ } ++ ++#if !defined(__LP64__) ++ if (has_text_relocations) { ++ // Fail if app is targeting sdk version > 22 ++ // TODO (dimitry): remove != __ANDROID_API__ check once http://b/20020312 is fixed ++ if (get_application_target_sdk_version() != __ANDROID_API__ ++ && get_application_target_sdk_version() > 22) { ++ DL_ERR("%s: has text relocations", get_realpath()); ++ return false; ++ } ++ // Make segments writable to allow text relocations to work properly. We will later call ++ // phdr_table_protect_segments() after all of them are applied and all constructors are run. ++ DL_WARN("%s has text relocations. This is wasting memory and prevents " ++ "security hardening. Please fix.", get_realpath()); ++ if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) { ++ DL_ERR("can't unprotect loadable segments for \"%s\": %s", ++ get_realpath(), strerror(errno)); ++ return false; ++ } ++ } ++#endif ++ ++ if (android_relocs_ != nullptr) { ++ // check signature ++ if (android_relocs_size_ > 3 && ++ android_relocs_[0] == 'A' && ++ android_relocs_[1] == 'P' && ++ android_relocs_[2] == 'S' && ++ android_relocs_[3] == '2') { ++ DEBUG("[ android relocating %s ]", get_realpath()); ++ ++ bool relocated = false; ++ const uint8_t* packed_relocs = android_relocs_ + 4; ++ const size_t packed_relocs_size = android_relocs_size_ - 4; ++ ++ relocated = relocate( ++ version_tracker, ++ packed_reloc_iterator( ++ sleb128_decoder(packed_relocs, packed_relocs_size)), ++ global_group, local_group); ++ ++ if (!relocated) { ++ return false; ++ } ++ } else { ++ DL_ERR("bad android relocation header."); ++ return false; ++ } ++ } ++ ++#if defined(USE_RELA) ++ if (rela_ != nullptr) { ++ DEBUG("[ relocating %s ]", get_realpath()); ++ if (!relocate(version_tracker, ++ plain_reloc_iterator(rela_, rela_count_), global_group, local_group)) { ++ return false; ++ } ++ } ++ if (plt_rela_ != nullptr) { ++ DEBUG("[ relocating %s plt ]", get_realpath()); ++ if (!relocate(version_tracker, ++ plain_reloc_iterator(plt_rela_, plt_rela_count_), global_group, local_group)) { ++ return false; ++ } ++ } +#else -+typedef Elf32_Ehdr Elf_Ehdr; -+typedef Elf32_Shdr Elf_Shdr; -+typedef Elf32_Sym Elf_Sym; -+typedef Elf32_Addr Elf_Addr; -+typedef Elf32_Phdr Elf_Phdr; -+typedef Elf32_Half Elf_Half; -+typedef Elf32_Rel Elf_Rel; -+typedef Elf32_Rela Elf_Rela; ++ if (rel_ != nullptr) { ++ DEBUG("[ relocating %s ]", get_realpath()); ++ if (!relocate(version_tracker, ++ plain_reloc_iterator(rel_, rel_count_), global_group, local_group)) { ++ return false; ++ } ++ } ++ if (plt_rel_ != nullptr) { ++ DEBUG("[ relocating %s plt ]", get_realpath()); ++ if (!relocate(version_tracker, ++ plain_reloc_iterator(plt_rel_, plt_rel_count_), global_group, local_group)) { ++ return false; ++ } ++ } ++#endif ++ ++#if defined(__mips__) ++ if (!mips_relocate_got(version_tracker, global_group, local_group)) { ++ return false; ++ } ++#endif ++ ++ DEBUG("[ finished linking %s ]", get_realpath()); ++ ++#if !defined(__LP64__) ++ if (has_text_relocations) { ++ // All relocations are done, we can protect our segments back to read-only. ++ if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) { ++ DL_ERR("can't protect segments for \"%s\": %s", ++ get_realpath(), strerror(errno)); ++ return false; ++ } ++ } ++#endif ++ ++ /* We can also turn on GNU RELRO protection */ ++ if (phdr_table_protect_gnu_relro(phdr, phnum, load_bias) < 0) { ++ DL_ERR("can't enable GNU RELRO protection for \"%s\": %s", ++ get_realpath(), strerror(errno)); ++ return false; ++ } ++ ++ /* Handle serializing/sharing the RELRO segment */ ++ if (extinfo && (extinfo->flags & ANDROID_DLEXT_WRITE_RELRO)) { ++ if (phdr_table_serialize_gnu_relro(phdr, phnum, load_bias, ++ extinfo->relro_fd) < 0) { ++ DL_ERR("failed serializing GNU RELRO section for \"%s\": %s", ++ get_realpath(), strerror(errno)); ++ return false; ++ } ++ } else if (extinfo && (extinfo->flags & ANDROID_DLEXT_USE_RELRO)) { ++ if (phdr_table_map_gnu_relro(phdr, phnum, load_bias, ++ extinfo->relro_fd) < 0) { ++ DL_ERR("failed mapping GNU RELRO section for \"%s\": %s", ++ get_realpath(), strerror(errno)); ++ return false; ++ } ++ } ++ ++ notify_gdb_of_load(this); ++ return true; ++} ++ ++/* ++ * This function add vdso to internal dso list. ++ * It helps to stack unwinding through signal handlers. ++ * Also, it makes bionic more like glibc. ++ */ ++static void add_vdso(KernelArgumentBlock& args) { ++#if defined(AT_SYSINFO_EHDR) ++ ElfW(Ehdr)* ehdr_vdso = reinterpret_cast(args.getauxval(AT_SYSINFO_EHDR)); ++ if (ehdr_vdso == nullptr) { ++ return; ++ } ++ ++ soinfo* si = soinfo_alloc("[vdso]", nullptr, 0, 0); ++ ++ si->phdr = reinterpret_cast(reinterpret_cast(ehdr_vdso) + ehdr_vdso->e_phoff); ++ si->phnum = ehdr_vdso->e_phnum; ++ si->base = reinterpret_cast(ehdr_vdso); ++ si->size = phdr_table_get_load_size(si->phdr, si->phnum); ++ si->load_bias = get_elf_exec_load_bias(ehdr_vdso); ++ ++ si->prelink_image(); ++ si->link_image(g_empty_list, soinfo::soinfo_list_t::make_list(si), nullptr); ++#endif ++} ++ ++/* ++ * This is linker soinfo for GDB. See details below. ++ */ ++#if defined(__LP64__) ++#define LINKER_PATH "/system/bin/linker64" ++#else ++#define LINKER_PATH "/system/bin/linker" ++#endif ++ ++// This is done to avoid calling c-tor prematurely ++// because soinfo c-tor needs memory allocator ++// which might be initialized after global variables. ++static uint8_t linker_soinfo_for_gdb_buf[sizeof(soinfo)] __attribute__((aligned(8))); ++static soinfo* linker_soinfo_for_gdb = nullptr; ++ ++/* gdb expects the linker to be in the debug shared object list. ++ * Without this, gdb has trouble locating the linker's ".text" ++ * and ".plt" sections. Gdb could also potentially use this to ++ * relocate the offset of our exported 'rtld_db_dlactivity' symbol. ++ * Don't use soinfo_alloc(), because the linker shouldn't ++ * be on the soinfo list. ++ */ ++static void init_linker_info_for_gdb(ElfW(Addr) linker_base) { ++ linker_soinfo_for_gdb = new (linker_soinfo_for_gdb_buf) soinfo(LINKER_PATH, nullptr, 0, 0); ++ ++ linker_soinfo_for_gdb->load_bias = linker_base; ++ ++ /* ++ * Set the dynamic field in the link map otherwise gdb will complain with ++ * the following: ++ * warning: .dynamic section for "/system/bin/linker" is not at the ++ * expected address (wrong library or version mismatch?) ++ */ ++ ElfW(Ehdr)* elf_hdr = reinterpret_cast(linker_base); ++ ElfW(Phdr)* phdr = reinterpret_cast(linker_base + elf_hdr->e_phoff); ++ phdr_table_get_dynamic_section(phdr, elf_hdr->e_phnum, linker_base, ++ &linker_soinfo_for_gdb->dynamic, nullptr); ++ insert_soinfo_into_debug_map(linker_soinfo_for_gdb); ++} ++ ++extern "C" int __system_properties_init(void); ++ ++/* ++ * This code is called after the linker has linked itself and ++ * fixed it's own GOT. It is safe to make references to externs ++ * and other non-local data at this point. ++ */ ++static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(Addr) linker_base) { ++#if TIMING ++ struct timeval t0, t1; ++ gettimeofday(&t0, 0); ++#endif ++ ++#ifdef DISABLED_FOR_HYBRIS_SUPPORT ++ // Sanitize the environment. ++ __libc_init_AT_SECURE(args); ++ ++ // Initialize system properties ++ __system_properties_init(); // may use 'environ' ++#endif ++ ++#ifdef DISABLED_FOR_HYBRIS_SUPPORT ++ debuggerd_init(); ++#endif ++ ++ // Get a few environment variables. ++ const char* LD_DEBUG = getenv("HYBRIS_LD_DEBUG"); ++ if (LD_DEBUG != nullptr) { ++ g_ld_debug_verbosity = atoi(LD_DEBUG); ++ } ++ ++ // These should have been sanitized by __libc_init_AT_SECURE, but the test ++ // doesn't cost us anything. ++ const char* ldpath_env = nullptr; ++ const char* ldpreload_env = nullptr; ++ if (!getauxval(AT_SECURE)) { ++ ldpath_env = getenv("HYBRIS_LD_LIBRARY_PATH"); ++ ldpreload_env = getenv("HYBRIS_LD_PRELOAD"); ++ } ++ ++ INFO("[ android linker & debugger ]"); ++ ++ soinfo* si = soinfo_alloc(args.argv[0], nullptr, 0, RTLD_GLOBAL); ++ if (si == nullptr) { ++ exit(EXIT_FAILURE); ++ } ++ ++ /* bootstrap the link map, the main exe always needs to be first */ ++ si->set_main_executable(); ++ link_map* map = &(si->link_map_head); ++ ++ map->l_addr = 0; ++ map->l_name = args.argv[0]; ++ map->l_prev = nullptr; ++ map->l_next = nullptr; ++ ++ _r_debug.r_map = map; ++ r_debug_tail = map; ++ ++ init_linker_info_for_gdb(linker_base); ++ ++ // Extract information passed from the kernel. ++ si->phdr = reinterpret_cast(args.getauxval(AT_PHDR)); ++ si->phnum = args.getauxval(AT_PHNUM); ++ si->entry = args.getauxval(AT_ENTRY); ++ ++ /* Compute the value of si->base. We can't rely on the fact that ++ * the first entry is the PHDR because this will not be true ++ * for certain executables (e.g. some in the NDK unit test suite) ++ */ ++ si->base = 0; ++ si->size = phdr_table_get_load_size(si->phdr, si->phnum); ++ si->load_bias = 0; ++ for (size_t i = 0; i < si->phnum; ++i) { ++ if (si->phdr[i].p_type == PT_PHDR) { ++ si->load_bias = reinterpret_cast(si->phdr) - si->phdr[i].p_vaddr; ++ si->base = reinterpret_cast(si->phdr) - si->phdr[i].p_offset; ++ break; ++ } ++ } ++ si->dynamic = nullptr; ++ ++ ElfW(Ehdr)* elf_hdr = reinterpret_cast(si->base); ++ if (elf_hdr->e_type != ET_DYN) { ++ fprintf(stderr, "error: only position independent executables (PIE) are supported.\n"); ++ exit(EXIT_FAILURE); ++ } ++ ++ // Use LD_LIBRARY_PATH and LD_PRELOAD (but only if we aren't setuid/setgid). ++ if (DEFAULT_HYBRIS_LD_LIBRARY_PATH) ++ parse_LD_LIBRARY_PATH(DEFAULT_HYBRIS_LD_LIBRARY_PATH); ++ else ++ parse_LD_LIBRARY_PATH(ldpath_env); ++ parse_LD_PRELOAD(ldpreload_env); ++ ++ somain = si; ++ ++ if (!si->prelink_image()) { ++ fprintf(stderr, "CANNOT LINK EXECUTABLE: %s\n", linker_get_error_buffer()); ++ exit(EXIT_FAILURE); ++ } ++ ++ // add somain to global group ++ si->set_dt_flags_1(si->get_dt_flags_1() | DF_1_GLOBAL); ++ ++ // Load ld_preloads and dependencies. ++ StringLinkedList needed_library_name_list; ++ size_t needed_libraries_count = 0; ++ size_t ld_preloads_count = 0; ++ ++ for (const auto& ld_preload_name : g_ld_preload_names) { ++ needed_library_name_list.push_back(ld_preload_name.c_str()); ++ ++needed_libraries_count; ++ ++ld_preloads_count; ++ } ++ ++ for_each_dt_needed(si, [&](const char* name) { ++ needed_library_name_list.push_back(name); ++ ++needed_libraries_count; ++ }); ++ ++ const char* needed_library_names[needed_libraries_count]; ++ ++ memset(needed_library_names, 0, sizeof(needed_library_names)); ++ needed_library_name_list.copy_to_array(needed_library_names, needed_libraries_count); ++ ++ if (needed_libraries_count > 0 && ++ !find_libraries(si, needed_library_names, needed_libraries_count, nullptr, ++ &g_ld_preloads, ld_preloads_count, RTLD_GLOBAL, nullptr)) { ++ fprintf(stderr, "CANNOT LINK EXECUTABLE: %s\n", linker_get_error_buffer()); ++ exit(EXIT_FAILURE); ++ } else if (needed_libraries_count == 0) { ++ if (!si->link_image(g_empty_list, soinfo::soinfo_list_t::make_list(si), nullptr)) { ++ fprintf(stderr, "CANNOT LINK EXECUTABLE: %s\n", linker_get_error_buffer()); ++ exit(EXIT_FAILURE); ++ } ++ si->increment_ref_count(); ++ } ++ ++ add_vdso(args); ++ ++ { ++ ProtectedDataGuard guard; ++ ++ si->call_pre_init_constructors(); ++ ++ /* After the prelink_image, the si->load_bias is initialized. ++ * For so lib, the map->l_addr will be updated in notify_gdb_of_load. ++ * We need to update this value for so exe here. So Unwind_Backtrace ++ * for some arch like x86 could work correctly within so exe. ++ */ ++ map->l_addr = si->load_bias; ++ si->call_constructors(); ++ } ++ ++#if TIMING ++ gettimeofday(&t1, nullptr); ++ PRINT("LINKER TIME: %s: %d microseconds", args.argv[0], (int) ( ++ (((long long)t1.tv_sec * 1000000LL) + (long long)t1.tv_usec) - ++ (((long long)t0.tv_sec * 1000000LL) + (long long)t0.tv_usec))); ++#endif ++#if STATS ++ PRINT("RELO STATS: %s: %d abs, %d rel, %d copy, %d symbol", args.argv[0], ++ linker_stats.count[kRelocAbsolute], ++ linker_stats.count[kRelocRelative], ++ linker_stats.count[kRelocCopy], ++ linker_stats.count[kRelocSymbol]); ++#endif ++#if COUNT_PAGES ++ { ++ unsigned n; ++ unsigned i; ++ unsigned count = 0; ++ for (n = 0; n < 4096; n++) { ++ if (bitmask[n]) { ++ unsigned x = bitmask[n]; ++#if defined(__LP64__) ++ for (i = 0; i < 32; i++) { ++#else ++ for (i = 0; i < 8; i++) { ++#endif ++ if (x & 1) { ++ count++; ++ } ++ x >>= 1; ++ } ++ } ++ } ++ PRINT("PAGES MODIFIED: %s: %d (%dKB)", args.argv[0], count, count * 4); ++ } ++#endif ++ ++#if TIMING || STATS || COUNT_PAGES ++ fflush(stdout); ++#endif ++ ++ TRACE("[ Ready to execute '%s' @ %p ]", si->get_realpath(), reinterpret_cast(si->entry)); ++ return si->entry; ++} ++ ++/* Compute the load-bias of an existing executable. This shall only ++ * be used to compute the load bias of an executable or shared library ++ * that was loaded by the kernel itself. ++ * ++ * Input: ++ * elf -> address of ELF header, assumed to be at the start of the file. ++ * Return: ++ * load bias, i.e. add the value of any p_vaddr in the file to get ++ * the corresponding address in memory. ++ */ ++static ElfW(Addr) get_elf_exec_load_bias(const ElfW(Ehdr)* elf) { ++ ElfW(Addr) offset = elf->e_phoff; ++ const ElfW(Phdr)* phdr_table = ++ reinterpret_cast(reinterpret_cast(elf) + offset); ++ const ElfW(Phdr)* phdr_end = phdr_table + elf->e_phnum; ++ ++ for (const ElfW(Phdr)* phdr = phdr_table; phdr < phdr_end; phdr++) { ++ if (phdr->p_type == PT_LOAD) { ++ return reinterpret_cast(elf) + phdr->p_offset - phdr->p_vaddr; ++ } ++ } ++ return 0; ++} ++ ++extern "C" void android_linker_init(int sdk_version, void* (*get_hooked_symbol)(const char*, const char*)) { ++ // Get a few environment variables. ++ const char* LD_DEBUG = getenv("HYBRIS_LD_DEBUG"); ++ if (LD_DEBUG != nullptr) { ++ g_ld_debug_verbosity = atoi(LD_DEBUG); ++ } ++ ++ if (sdk_version > 0) ++ set_application_target_sdk_version(sdk_version); ++ ++ _get_hooked_symbol = get_hooked_symbol; ++} ++ ++#ifdef DISABLED_FOR_HYBRIS_SUPPORT ++extern "C" void _start(); ++ ++/* ++ * This is the entry point for the linker, called from begin.S. This ++ * method is responsible for fixing the linker's own relocations, and ++ * then calling __linker_init_post_relocation(). ++ * ++ * Because this method is called before the linker has fixed it's own ++ * relocations, any attempt to reference an extern variable, extern ++ * function, or other GOT reference will generate a segfault. ++ */ ++extern "C" ElfW(Addr) __linker_init(void* raw_args) { ++ KernelArgumentBlock args(raw_args); ++ ++ ElfW(Addr) linker_addr = args.getauxval(AT_BASE); ++ ElfW(Addr) entry_point = args.getauxval(AT_ENTRY); ++ ElfW(Ehdr)* elf_hdr = reinterpret_cast(linker_addr); ++ ElfW(Phdr)* phdr = reinterpret_cast(linker_addr + elf_hdr->e_phoff); ++ ++ soinfo linker_so(nullptr, nullptr, 0, 0); ++ ++ // If the linker is not acting as PT_INTERP entry_point is equal to ++ // _start. Which means that the linker is running as an executable and ++ // already linked by PT_INTERP. ++ // ++ // This happens when user tries to run 'adb shell /system/bin/linker' ++ // see also https://code.google.com/p/android/issues/detail?id=63174 ++ if (reinterpret_cast(&_start) == entry_point) { ++ __libc_fatal("This is %s, the helper program for shared library executables.\n", args.argv[0]); ++ } ++ ++ linker_so.base = linker_addr; ++ linker_so.size = phdr_table_get_load_size(phdr, elf_hdr->e_phnum); ++ linker_so.load_bias = get_elf_exec_load_bias(elf_hdr); ++ linker_so.dynamic = nullptr; ++ linker_so.phdr = phdr; ++ linker_so.phnum = elf_hdr->e_phnum; ++ linker_so.set_linker_flag(); ++ ++ // This might not be obvious... The reasons why we pass g_empty_list ++ // in place of local_group here are (1) we do not really need it, because ++ // linker is built with DT_SYMBOLIC and therefore relocates its symbols against ++ // itself without having to look into local_group and (2) allocators ++ // are not yet initialized, and therefore we cannot use linked_list.push_* ++ // functions at this point. ++ if (!(linker_so.prelink_image() && linker_so.link_image(g_empty_list, g_empty_list, nullptr))) { ++ // It would be nice to print an error message, but if the linker ++ // can't link itself, there's no guarantee that we'll be able to ++ // call write() (because it involves a GOT reference). We may as ++ // well try though... ++ const char* msg = "CANNOT LINK EXECUTABLE: "; ++ int unused __attribute__((unused)); ++ unused = write(2, msg, strlen(msg)); ++ unused = write(2, __linker_dl_err_buf, strlen(__linker_dl_err_buf)); ++ unused = write(2, "\n", 1); ++ _exit(EXIT_FAILURE); ++ } ++ ++#ifdef DISABLED_FOR_HYBRIS_SUPPORT ++ __libc_init_tls(args); ++#endif ++ ++ // Initialize the linker's own global variables ++ linker_so.call_constructors(); ++ ++ // Initialize static variables. Note that in order to ++ // get correct libdl_info we need to call constructors ++ // before get_libdl_info(). ++ solist = get_libdl_info(); ++ sonext = get_libdl_info(); ++ ++ // We have successfully fixed our own relocations. It's safe to run ++ // the main part of the linker now. ++ args.abort_message_ptr = &g_abort_message; ++ ElfW(Addr) start_address = __linker_init_post_relocation(args, linker_addr); ++ ++ INFO("[ jumping to _start ]"); ++ ++ // Return the address that the calling assembly stub should jump to. ++ return start_address; ++} ++ ++#endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker.h +@@ -0,0 +1,441 @@ ++/* ++ * Copyright (C) 2008 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++#ifndef _LINKER_H_ ++#define _LINKER_H_ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "private/libc_logging.h" ++#include "linked_list.h" ++ ++#include ++#include ++ ++#define DL_ERR(fmt, x...) \ ++ do { \ ++ fprintf(stderr, fmt, ##x); \ ++ fprintf(stderr, "\n"); \ ++ /* If LD_DEBUG is set high enough, log every dlerror(3) message. */ \ ++ DEBUG("%s\n", linker_get_error_buffer()); \ ++ } while (false) ++ ++#define DL_WARN(fmt, x...) \ ++ do { \ ++ fprintf(stderr, "WARNING: linker " fmt, ##x); \ ++ fprintf(stderr, "\n"); \ ++ } while (false) ++ ++#if defined(__LP64__) ++#define ELFW(what) ELF64_ ## what ++#else ++#define ELFW(what) ELF32_ ## what ++#endif ++ ++// mips64 interprets Elf64_Rel structures' r_info field differently. ++// bionic (like other C libraries) has macros that assume regular ELF files, ++// but the dynamic linker needs to be able to load mips64 ELF files. ++#if defined(__mips__) && defined(__LP64__) ++#undef ELF64_R_SYM ++#undef ELF64_R_TYPE ++#undef ELF64_R_INFO ++#define ELF64_R_SYM(info) (((info) >> 0) & 0xffffffff) ++#define ELF64_R_SSYM(info) (((info) >> 32) & 0xff) ++#define ELF64_R_TYPE3(info) (((info) >> 40) & 0xff) ++#define ELF64_R_TYPE2(info) (((info) >> 48) & 0xff) ++#define ELF64_R_TYPE(info) (((info) >> 56) & 0xff) ++#endif ++ ++// Returns the address of the page containing address 'x'. ++#define PAGE_START(x) ((x) & PAGE_MASK) ++ ++// Returns the offset of address 'x' in its page. ++#define PAGE_OFFSET(x) ((x) & ~PAGE_MASK) ++ ++// Returns the address of the next page after address 'x', unless 'x' is ++// itself at the start of a page. ++#define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE-1)) ++ ++#define FLAG_LINKED 0x00000001 ++#define FLAG_EXE 0x00000004 // The main executable ++#define FLAG_LINKER 0x00000010 // The linker itself ++#define FLAG_GNU_HASH 0x00000040 // uses gnu hash ++#define FLAG_NEW_SOINFO 0x40000000 // new soinfo format ++ ++#define SUPPORTED_DT_FLAGS_1 (DF_1_NOW | DF_1_GLOBAL | DF_1_NODELETE) ++ ++#define SOINFO_VERSION 2 ++ ++#if defined(__work_around_b_19059885__) ++#define SOINFO_NAME_LEN 128 ++#endif ++ ++typedef void (*linker_function_t)(); ++ ++// Android uses RELA for aarch64 and x86_64. mips64 still uses REL. ++#if defined(__aarch64__) || defined(__x86_64__) ++#define USE_RELA 1 ++#endif ++ ++struct soinfo; ++ ++class SoinfoListAllocator { ++ public: ++ static LinkedListEntry* alloc(); ++ static void free(LinkedListEntry* entry); ++ ++ private: ++ // unconstructable ++ DISALLOW_IMPLICIT_CONSTRUCTORS(SoinfoListAllocator); ++}; ++ ++class SymbolName { ++ public: ++ explicit SymbolName(const char* name) ++ : name_(name), has_elf_hash_(false), has_gnu_hash_(false), ++ elf_hash_(0), gnu_hash_(0) { } ++ ++ const char* get_name() { ++ return name_; ++ } ++ ++ uint32_t elf_hash(); ++ uint32_t gnu_hash(); ++ ++ private: ++ const char* name_; ++ bool has_elf_hash_; ++ bool has_gnu_hash_; ++ uint32_t elf_hash_; ++ uint32_t gnu_hash_; ++ ++ DISALLOW_IMPLICIT_CONSTRUCTORS(SymbolName); ++}; ++ ++struct version_info { ++ version_info() : elf_hash(0), name(nullptr), target_si(nullptr) {} ++ ++ uint32_t elf_hash; ++ const char* name; ++ const soinfo* target_si; ++}; ++ ++// Class used construct version dependency graph. ++class VersionTracker { ++ public: ++ VersionTracker() = default; ++ bool init(const soinfo* si_from); ++ ++ const version_info* get_version_info(ElfW(Versym) source_symver) const; ++ private: ++ bool init_verneed(const soinfo* si_from); ++ bool init_verdef(const soinfo* si_from); ++ void add_version_info(size_t source_index, ElfW(Word) elf_hash, ++ const char* ver_name, const soinfo* target_si); ++ ++ std::vector version_infos; ++ ++ DISALLOW_COPY_AND_ASSIGN(VersionTracker); ++}; ++ ++struct soinfo { ++ public: ++ typedef LinkedList soinfo_list_t; ++#if defined(__work_around_b_19059885__) ++ private: ++ char old_name_[SOINFO_NAME_LEN]; ++#endif ++ public: ++ const ElfW(Phdr)* phdr; ++ size_t phnum; ++ ElfW(Addr) entry; ++ ElfW(Addr) base; ++ size_t size; ++ ++#if defined(__work_around_b_19059885__) ++ uint32_t unused1; // DO NOT USE, maintained for compatibility. ++#endif ++ ++ ElfW(Dyn)* dynamic; ++ ++#if defined(__work_around_b_19059885__) ++ uint32_t unused2; // DO NOT USE, maintained for compatibility ++ uint32_t unused3; // DO NOT USE, maintained for compatibility ++#endif ++ ++ soinfo* next; ++ private: ++ uint32_t flags_; ++ ++ const char* strtab_; ++ ElfW(Sym)* symtab_; ++ ++ size_t nbucket_; ++ size_t nchain_; ++ uint32_t* bucket_; ++ uint32_t* chain_; ++ ++#if defined(__mips__) || !defined(__LP64__) ++ // This is only used by mips and mips64, but needs to be here for ++ // all 32-bit architectures to preserve binary compatibility. ++ ElfW(Addr)** plt_got_; ++#endif ++ ++#if defined(USE_RELA) ++ ElfW(Rela)* plt_rela_; ++ size_t plt_rela_count_; ++ ++ ElfW(Rela)* rela_; ++ size_t rela_count_; ++#else ++ ElfW(Rel)* plt_rel_; ++ size_t plt_rel_count_; ++ ++ ElfW(Rel)* rel_; ++ size_t rel_count_; ++#endif ++ ++ linker_function_t* preinit_array_; ++ size_t preinit_array_count_; ++ ++ linker_function_t* init_array_; ++ size_t init_array_count_; ++ linker_function_t* fini_array_; ++ size_t fini_array_count_; ++ ++ linker_function_t init_func_; ++ linker_function_t fini_func_; ++ ++#if defined(__arm__) ++ public: ++ // ARM EABI section used for stack unwinding. ++ uint32_t* ARM_exidx; ++ size_t ARM_exidx_count; ++ private: ++#elif defined(__mips__) ++ uint32_t mips_symtabno_; ++ uint32_t mips_local_gotno_; ++ uint32_t mips_gotsym_; ++ bool mips_relocate_got(const VersionTracker& version_tracker, ++ const soinfo_list_t& global_group, ++ const soinfo_list_t& local_group); ++ ++#endif ++ size_t ref_count_; ++ public: ++ link_map link_map_head; ++ ++ bool constructors_called; ++ ++ // When you read a virtual address from the ELF file, add this ++ // value to get the corresponding address in the process' address space. ++ ElfW(Addr) load_bias; ++ ++#if !defined(__LP64__) ++ bool has_text_relocations; ++#endif ++ bool has_DT_SYMBOLIC; ++ ++ public: ++ soinfo(const char* name, const struct stat* file_stat, off64_t file_offset, int rtld_flags); ++ ++ void call_constructors(); ++ void call_destructors(); ++ void call_pre_init_constructors(); ++ bool prelink_image(); ++ bool link_image(const soinfo_list_t& global_group, const soinfo_list_t& local_group, ++ const android_dlextinfo* extinfo); ++ ++ void add_child(soinfo* child); ++ void remove_all_links(); ++ ++ ino_t get_st_ino() const; ++ dev_t get_st_dev() const; ++ off64_t get_file_offset() const; ++ ++ uint32_t get_rtld_flags() const; ++ uint32_t get_dt_flags_1() const; ++ void set_dt_flags_1(uint32_t dt_flags_1); ++ ++ soinfo_list_t& get_children(); ++ const soinfo_list_t& get_children() const; ++ ++ soinfo_list_t& get_parents(); ++ ++ bool find_symbol_by_name(SymbolName& symbol_name, ++ const version_info* vi, ++ const ElfW(Sym)** symbol) const; ++ ++ ElfW(Sym)* find_symbol_by_address(const void* addr); ++ ElfW(Addr) resolve_symbol_address(const ElfW(Sym)* s) const; ++ ++ const char* get_string(ElfW(Word) index) const; ++ bool can_unload() const; ++ bool is_gnu_hash() const; ++ ++ bool inline has_min_version(uint32_t min_version) const { ++#if defined(__work_around_b_19059885__) ++ (void) min_version; ++ return (flags_ & FLAG_NEW_SOINFO) != 0 && version_ >= min_version; ++#else ++ return true; ++#endif ++ } ++ ++ bool is_linked() const; ++ bool is_main_executable() const; ++ ++ void set_linked(); ++ void set_linker_flag(); ++ void set_main_executable(); ++ ++ void increment_ref_count(); ++ size_t decrement_ref_count(); ++ ++ soinfo* get_local_group_root() const; ++ ++ const char* get_soname() const; ++ const char* get_realpath() const; ++ const ElfW(Versym)* get_versym(size_t n) const; ++ ElfW(Addr) get_verneed_ptr() const; ++ size_t get_verneed_cnt() const; ++ ElfW(Addr) get_verdef_ptr() const; ++ size_t get_verdef_cnt() const; ++ ++ bool find_verdef_version_index(const version_info* vi, ElfW(Versym)* versym) const; ++ ++ uint32_t get_target_sdk_version() const; ++ ++ private: ++ bool elf_lookup(SymbolName& symbol_name, const version_info* vi, uint32_t* symbol_index) const; ++ ElfW(Sym)* elf_addr_lookup(const void* addr); ++ bool gnu_lookup(SymbolName& symbol_name, const version_info* vi, uint32_t* symbol_index) const; ++ ElfW(Sym)* gnu_addr_lookup(const void* addr); ++ ++ bool lookup_version_info(const VersionTracker& version_tracker, ElfW(Word) sym, ++ const char* sym_name, const version_info** vi); ++ ++ void call_array(const char* array_name, linker_function_t* functions, size_t count, bool reverse); ++ void call_function(const char* function_name, linker_function_t function); ++ template ++ bool relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& rel_iterator, ++ const soinfo_list_t& global_group, const soinfo_list_t& local_group); ++ ++ private: ++ // This part of the structure is only available ++ // when FLAG_NEW_SOINFO is set in this->flags. ++ uint32_t version_; ++ ++ // version >= 0 ++ dev_t st_dev_; ++ ino_t st_ino_; ++ ++ // dependency graph ++ soinfo_list_t children_; ++ soinfo_list_t parents_; ++ ++ // version >= 1 ++ off64_t file_offset_; ++ uint32_t rtld_flags_; ++ uint32_t dt_flags_1_; ++ size_t strtab_size_; ++ ++ // version >= 2 ++ ++ size_t gnu_nbucket_; ++ uint32_t* gnu_bucket_; ++ uint32_t* gnu_chain_; ++ uint32_t gnu_maskwords_; ++ uint32_t gnu_shift2_; ++ ElfW(Addr)* gnu_bloom_filter_; ++ ++ soinfo* local_group_root_; ++ ++ uint8_t* android_relocs_; ++ size_t android_relocs_size_; ++ ++ const char* soname_; ++ std::string realpath_; ++ ++ const ElfW(Versym)* versym_; ++ ++ ElfW(Addr) verdef_ptr_; ++ size_t verdef_cnt_; ++ ++ ElfW(Addr) verneed_ptr_; ++ size_t verneed_cnt_; ++ ++ uint32_t target_sdk_version_; ++ ++ friend soinfo* get_libdl_info(); ++}; ++ ++bool soinfo_do_lookup(soinfo* si_from, const char* name, const version_info* vi, ++ soinfo** si_found_in, const soinfo::soinfo_list_t& global_group, ++ const soinfo::soinfo_list_t& local_group, const ElfW(Sym)** symbol); ++ ++enum RelocationKind { ++ kRelocAbsolute = 0, ++ kRelocRelative, ++ kRelocCopy, ++ kRelocSymbol, ++ kRelocMax ++}; ++ ++void count_relocation(RelocationKind kind); ++ ++soinfo* get_libdl_info(); ++ ++void do_android_get_LD_LIBRARY_PATH(char*, size_t); ++void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path); ++soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo); ++void do_dlclose(soinfo* si); ++ ++int do_dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data); ++ ++const ElfW(Sym)* dlsym_linear_lookup(const char* name, soinfo** found, soinfo* caller, void* handle); ++soinfo* find_containing_library(const void* addr); ++ ++const ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name); ++ ++void debuggerd_init(); ++extern "C" abort_msg_t* g_abort_message; ++extern "C" void notify_gdb_of_libraries(); ++ ++char* linker_get_error_buffer(); ++size_t linker_get_error_buffer_size(); ++ ++void set_application_target_sdk_version(uint32_t target); ++uint32_t get_application_target_sdk_version(); ++ +#endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_allocator.cpp +@@ -0,0 +1,350 @@ ++/* ++ * Copyright (C) 2015 The Android Open Source Project ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++#include "linker_allocator.h" ++#include "linker.h" ++ ++#include ++#include ++ ++#include ++#include ++#include ++ ++#include ++ ++#include "private/bionic_prctl.h" ++ ++#include "hybris_compat.h" ++ ++// ++// LinkerMemeoryAllocator is general purpose allocator ++// designed to provide the same functionality as the malloc/free/realloc ++// libc functions. ++// ++// On alloc: ++// If size is >= 1k allocator proxies malloc call directly to mmap ++// If size < 1k allocator uses SmallObjectAllocator for the size ++// rounded up to the nearest power of two. ++// ++// On free: ++// ++// For a pointer allocated using proxy-to-mmap allocator unmaps ++// the memory. ++// ++// For a pointer allocated using SmallObjectAllocator it adds ++// the block to free_blocks_list_. If the number of free pages reaches 2, ++// SmallObjectAllocator munmaps one of the pages keeping the other one ++// in reserve. ++ ++static const char kSignature[4] = {'L', 'M', 'A', 1}; ++ ++static const size_t kSmallObjectMaxSize = 1 << kSmallObjectMaxSizeLog2; ++ ++// This type is used for large allocations (with size >1k) ++static const uint32_t kLargeObject = 111; ++ ++bool operator<(const small_object_page_record& one, const small_object_page_record& two) { ++ return one.page_addr < two.page_addr; ++} ++ ++static inline uint16_t log2(size_t number) { ++ uint16_t result = 0; ++ number--; ++ ++ while (number != 0) { ++ result++; ++ number >>= 1; ++ } ++ ++ return result; ++} ++ ++LinkerSmallObjectAllocator::LinkerSmallObjectAllocator() ++ : type_(0), name_(nullptr), block_size_(0), free_pages_cnt_(0), free_blocks_list_(nullptr) {} ++ ++void* LinkerSmallObjectAllocator::alloc() { ++ if (free_blocks_list_ == nullptr) { ++ alloc_page(); ++ } ++ ++ small_object_block_record* block_record = free_blocks_list_; ++ if (block_record->free_blocks_cnt > 1) { ++ small_object_block_record* next_free = reinterpret_cast( ++ reinterpret_cast(block_record) + block_size_); ++ next_free->next = block_record->next; ++ next_free->free_blocks_cnt = block_record->free_blocks_cnt - 1; ++ free_blocks_list_ = next_free; ++ } else { ++ free_blocks_list_ = block_record->next; ++ } ++ ++ // bookkeeping... ++ auto page_record = find_page_record(block_record); ++ ++ if (page_record->allocated_blocks_cnt == 0) { ++ free_pages_cnt_--; ++ } ++ ++ page_record->free_blocks_cnt--; ++ page_record->allocated_blocks_cnt++; ++ ++ memset(block_record, 0, block_size_); ++ ++ return block_record; ++} ++ ++void LinkerSmallObjectAllocator::free_page(linker_vector_t::iterator page_record) { ++ void* page_start = reinterpret_cast(page_record->page_addr); ++ void* page_end = reinterpret_cast(reinterpret_cast(page_start) + PAGE_SIZE); ++ ++ while (free_blocks_list_ != nullptr && ++ free_blocks_list_ > page_start && ++ free_blocks_list_ < page_end) { ++ free_blocks_list_ = free_blocks_list_->next; ++ } ++ ++ small_object_block_record* current = free_blocks_list_; ++ ++ while (current != nullptr) { ++ while (current->next > page_start && current->next < page_end) { ++ current->next = current->next->next; ++ } ++ ++ current = current->next; ++ } ++ ++ munmap(page_start, PAGE_SIZE); ++ page_records_.erase(page_record); ++ free_pages_cnt_--; ++} ++ ++void LinkerSmallObjectAllocator::free(void* ptr) { ++ auto page_record = find_page_record(ptr); ++ ++ ssize_t offset = reinterpret_cast(ptr) - sizeof(page_info); ++ ++ if (offset % block_size_ != 0) { ++ __libc_fatal("invalid pointer: %p (block_size=%zd)", ptr, block_size_); ++ } ++ ++ memset(ptr, 0, block_size_); ++ small_object_block_record* block_record = reinterpret_cast(ptr); + - void debugger_init(); - const char *addr_to_name(unsigned addr); - -@@ -55,10 +75,10 @@ struct link_map - /* needed for dl_iterate_phdr to be passed to the callbacks provided */ - struct dl_phdr_info - { -- Elf32_Addr dlpi_addr; -+ Elf_Addr dlpi_addr; - const char *dlpi_name; -- const Elf32_Phdr *dlpi_phdr; -- Elf32_Half dlpi_phnum; -+ const Elf_Phdr *dlpi_phdr; -+ Elf_Half dlpi_phnum; - }; - - -@@ -90,7 +110,7 @@ typedef struct soinfo soinfo; - struct soinfo - { - const char name[SOINFO_NAME_LEN]; -- Elf32_Phdr *phdr; -+ Elf_Phdr *phdr; - int phnum; - unsigned entry; - unsigned base; -@@ -107,7 +127,7 @@ struct soinfo - unsigned flags; - - const char *strtab; -- Elf32_Sym *symtab; -+ Elf_Sym *symtab; - - unsigned nbucket; - unsigned nchain; -@@ -116,10 +136,10 @@ struct soinfo - - unsigned *plt_got; - -- Elf32_Rel *plt_rel; -+ Elf_Rel *plt_rel; - unsigned plt_rel_count; - -- Elf32_Rel *rel; -+ Elf_Rel *rel; - unsigned rel_count; - - unsigned *preinit_array; -@@ -144,7 +164,7 @@ struct soinfo - - int constructors_called; - -- Elf32_Addr gnu_relro_start; -+ Elf_Addr gnu_relro_start; - unsigned gnu_relro_len; - - }; -@@ -202,18 +222,17 @@ extern soinfo libdl_info; - - soinfo *find_library(const char *name); - unsigned unload_library(soinfo *si); --Elf32_Sym *lookup_in_library(soinfo *si, const char *name); --Elf32_Sym *lookup(const char *name, soinfo **found, soinfo *start); -+Elf_Sym *lookup_in_library(soinfo *si, const char *name); -+Elf_Sym *lookup(const char *name, soinfo **found, soinfo *start); - soinfo *find_containing_library(const void *addr); --Elf32_Sym *find_containing_symbol(const void *addr, soinfo *si); -+Elf_Sym *find_containing_symbol(const void *addr, soinfo *si); - const char *linker_get_error(void); - void call_constructors_recursive(soinfo *si); - -+int dl_iterate_phdr(int (*cb)(struct dl_phdr_info *, size_t, void *), void *); - #ifdef ANDROID_ARM_LINKER - typedef long unsigned int *_Unwind_Ptr; - _Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount); --#elif defined(ANDROID_X86_LINKER) --int dl_iterate_phdr(int (*cb)(struct dl_phdr_info *, size_t, void *), void *); - #endif - - #endif ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/common/jb/linker_format.c -+++ libhybris-0.1.0+git20131207+e452e83/hybris/common/jb/linker_format.c -@@ -268,7 +268,7 @@ static int log_vprint(int prio, const ch - result = vformat_buffer(buf, sizeof buf, fmt, args); - - if (log_fd < 0) { -- log_fd = open("/dev/log/main", O_WRONLY); -+ log_fd = open("/dev/alog/main", O_WRONLY); - if (log_fd < 0) { - log_fd = fileno(stdout); // kernel doesn't have android log - return result; ++ block_record->next = free_blocks_list_; ++ block_record->free_blocks_cnt = 1; ++ ++ free_blocks_list_ = block_record; ++ ++ page_record->free_blocks_cnt++; ++ page_record->allocated_blocks_cnt--; ++ ++ if (page_record->allocated_blocks_cnt == 0) { ++ if (free_pages_cnt_++ > 1) { ++ // if we already have a free page - unmap this one. ++ free_page(page_record); ++ } ++ } ++} ++ ++void LinkerSmallObjectAllocator::init(uint32_t type, size_t block_size, const char* name) { ++ type_ = type; ++ block_size_ = block_size; ++ name_ = name; ++} ++ ++linker_vector_t::iterator LinkerSmallObjectAllocator::find_page_record(void* ptr) { ++ void* addr = reinterpret_cast(PAGE_START(reinterpret_cast(ptr))); ++ small_object_page_record boundary; ++ boundary.page_addr = addr; ++ linker_vector_t::iterator it = std::lower_bound( ++ page_records_.begin(), page_records_.end(), boundary); ++ ++ if (it == page_records_.end() || it->page_addr != addr) { ++ // not found... ++ __libc_fatal("page record for %p was not found (block_size=%zd)", ptr, block_size_); ++ } ++ ++ return it; ++} ++ ++void LinkerSmallObjectAllocator::create_page_record(void* page_addr, size_t free_blocks_cnt) { ++ small_object_page_record record; ++ record.page_addr = page_addr; ++ record.free_blocks_cnt = free_blocks_cnt; ++ record.allocated_blocks_cnt = 0; ++ ++ linker_vector_t::iterator it = std::lower_bound( ++ page_records_.begin(), page_records_.end(), record); ++ page_records_.insert(it, record); ++} ++ ++void LinkerSmallObjectAllocator::alloc_page() { ++ void* map_ptr = mmap(nullptr, PAGE_SIZE, ++ PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); ++ if (map_ptr == MAP_FAILED) { ++ __libc_fatal("mmap failed"); ++ } ++ ++ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map_ptr, PAGE_SIZE, name_); ++ ++ memset(map_ptr, 0, PAGE_SIZE); ++ ++ page_info* info = reinterpret_cast(map_ptr); ++ memcpy(info->signature, kSignature, sizeof(kSignature)); ++ info->type = type_; ++ info->allocator_addr = this; ++ ++ size_t free_blocks_cnt = (PAGE_SIZE - sizeof(page_info))/block_size_; ++ ++ create_page_record(map_ptr, free_blocks_cnt); ++ ++ small_object_block_record* first_block = reinterpret_cast(info + 1); ++ ++ first_block->next = free_blocks_list_; ++ first_block->free_blocks_cnt = free_blocks_cnt; ++ ++ free_blocks_list_ = first_block; ++} ++ ++ ++LinkerMemoryAllocator::LinkerMemoryAllocator() { ++ static const char* allocator_names[kSmallObjectAllocatorsCount] = { ++ "linker_alloc_16", // 2^4 ++ "linker_alloc_32", // 2^5 ++ "linker_alloc_64", // and so on... ++ "linker_alloc_128", ++ "linker_alloc_256", ++ "linker_alloc_512", ++ "linker_alloc_1024", // 2^10 ++ }; ++ ++ for (size_t i = 0; i < kSmallObjectAllocatorsCount; ++i) { ++ uint32_t type = i + kSmallObjectMinSizeLog2; ++ allocators_[i].init(type, 1 << type, allocator_names[i]); ++ } ++} ++ ++void* LinkerMemoryAllocator::alloc_mmap(size_t size) { ++ size_t allocated_size = PAGE_END(size + sizeof(page_info)); ++ void* map_ptr = mmap(nullptr, allocated_size, ++ PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); ++ ++ if (map_ptr == MAP_FAILED) { ++ __libc_fatal("mmap failed"); ++ } ++ ++ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, map_ptr, allocated_size, "linker_alloc_lob"); ++ ++ memset(map_ptr, 0, allocated_size); ++ ++ page_info* info = reinterpret_cast(map_ptr); ++ memcpy(info->signature, kSignature, sizeof(kSignature)); ++ info->type = kLargeObject; ++ info->allocated_size = allocated_size; ++ ++ return info + 1; ++} ++ ++void* LinkerMemoryAllocator::alloc(size_t size) { ++ // treat alloc(0) as alloc(1) ++ if (size == 0) { ++ size = 1; ++ } ++ ++ if (size > kSmallObjectMaxSize) { ++ return alloc_mmap(size); ++ } ++ ++ uint16_t log2_size = log2(size); ++ ++ if (log2_size < kSmallObjectMinSizeLog2) { ++ log2_size = kSmallObjectMinSizeLog2; ++ } ++ ++ return get_small_object_allocator(log2_size)->alloc(); ++} ++ ++page_info* LinkerMemoryAllocator::get_page_info(void* ptr) { ++ page_info* info = reinterpret_cast(PAGE_START(reinterpret_cast(ptr))); ++ if (memcmp(info->signature, kSignature, sizeof(kSignature)) != 0) { ++ __libc_fatal("invalid pointer %p (page signature mismatch)", ptr); ++ } ++ ++ return info; ++} ++ ++void* LinkerMemoryAllocator::realloc(void* ptr, size_t size) { ++ if (ptr == nullptr) { ++ return alloc(size); ++ } ++ ++ if (size == 0) { ++ free(ptr); ++ return nullptr; ++ } ++ ++ page_info* info = get_page_info(ptr); ++ ++ size_t old_size = 0; ++ ++ if (info->type == kLargeObject) { ++ old_size = info->allocated_size - sizeof(page_info); ++ } else { ++ LinkerSmallObjectAllocator* allocator = get_small_object_allocator(info->type); ++ if (allocator != info->allocator_addr) { ++ __libc_fatal("invalid pointer %p (page signature mismatch)", ptr); ++ } ++ ++ old_size = allocator->get_block_size(); ++ } ++ ++ if (old_size < size) { ++ void *result = alloc(size); ++ memcpy(result, ptr, old_size); ++ free(ptr); ++ return result; ++ } ++ ++ return ptr; ++} ++ ++void LinkerMemoryAllocator::free(void* ptr) { ++ if (ptr == nullptr) { ++ return; ++ } ++ ++ page_info* info = get_page_info(ptr); ++ ++ if (info->type == kLargeObject) { ++ munmap(info, info->allocated_size); ++ } else { ++ LinkerSmallObjectAllocator* allocator = get_small_object_allocator(info->type); ++ if (allocator != info->allocator_addr) { ++ __libc_fatal("invalid pointer %p (invalid allocator address for the page)", ptr); ++ } ++ ++ allocator->free(ptr); ++ } ++} ++ ++LinkerSmallObjectAllocator* LinkerMemoryAllocator::get_small_object_allocator(uint32_t type) { ++ if (type < kSmallObjectMinSizeLog2 || type > kSmallObjectMaxSizeLog2) { ++ __libc_fatal("invalid type: %u", type); ++ } ++ ++ return &allocators_[type - kSmallObjectMinSizeLog2]; ++} +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_allocator.h +@@ -0,0 +1,143 @@ ++/* ++ * Copyright (C) 2015 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 __LINKER_ALLOCATOR_H ++#define __LINKER_ALLOCATOR_H ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#include "private/bionic_prctl.h" ++#include "private/libc_logging.h" ++ ++const uint32_t kSmallObjectMaxSizeLog2 = 10; ++const uint32_t kSmallObjectMinSizeLog2 = 4; ++const uint32_t kSmallObjectAllocatorsCount = kSmallObjectMaxSizeLog2 - kSmallObjectMinSizeLog2 + 1; ++ ++class LinkerSmallObjectAllocator; ++ ++// This structure is placed at the beginning of each addressable page ++// and has all information we need to find the corresponding memory allocator. ++struct page_info { ++ char signature[4]; ++ uint32_t type; ++ union { ++ // we use allocated_size for large objects allocator ++ size_t allocated_size; ++ // and allocator_addr for small ones. ++ LinkerSmallObjectAllocator* allocator_addr; ++ }; ++}; ++ ++struct small_object_page_record { ++ void* page_addr; ++ size_t free_blocks_cnt; ++ size_t allocated_blocks_cnt; ++}; ++ ++// for lower_bound... ++bool operator<(const small_object_page_record& one, const small_object_page_record& two); ++ ++struct small_object_block_record { ++ small_object_block_record* next; ++ size_t free_blocks_cnt; ++}; ++ ++// This is implementation for std::vector allocator ++template ++class linker_vector_allocator { ++ public: ++ typedef T value_type; ++ typedef T* pointer; ++ typedef const T* const_pointer; ++ typedef T& reference; ++ typedef const T& const_reference; ++ typedef size_t size_type; ++ typedef ptrdiff_t difference_type; ++ ++ T* allocate(size_t n, const T* hint = nullptr) { ++ size_t size = n * sizeof(T); ++ void* ptr = mmap(const_cast(hint), size, ++ PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0); ++ if (ptr == MAP_FAILED) { ++ // Spec says we need to throw std::bad_alloc here but because our ++ // code does not support exception handling anyways - we are going to abort. ++ __libc_fatal("mmap failed"); ++ } ++ ++ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, ptr, size, "linker_alloc_vector"); ++ ++ return reinterpret_cast(ptr); ++ } ++ ++ void deallocate(T* ptr, size_t n) { ++ munmap(ptr, n * sizeof(T)); ++ } ++}; ++ ++typedef ++ std::vector> ++ linker_vector_t; ++ ++ ++class LinkerSmallObjectAllocator { ++ public: ++ LinkerSmallObjectAllocator(); ++ void init(uint32_t type, size_t block_size, const char* name); ++ void* alloc(); ++ void free(void* ptr); ++ ++ size_t get_block_size() const { return block_size_; } ++ private: ++ void alloc_page(); ++ void free_page(linker_vector_t::iterator page_record); ++ linker_vector_t::iterator find_page_record(void* ptr); ++ void create_page_record(void* page_addr, size_t free_blocks_cnt); ++ ++ uint32_t type_; ++ const char* name_; ++ size_t block_size_; ++ ++ size_t free_pages_cnt_; ++ small_object_block_record* free_blocks_list_; ++ ++ // sorted vector of page records ++ linker_vector_t page_records_; ++}; ++ ++class LinkerMemoryAllocator { ++ public: ++ LinkerMemoryAllocator(); ++ void* alloc(size_t size); ++ ++ // Note that this implementation of realloc never shrinks allocation ++ void* realloc(void* ptr, size_t size); ++ void free(void* ptr); ++ private: ++ void* alloc_mmap(size_t size); ++ page_info* get_page_info(void* ptr); ++ LinkerSmallObjectAllocator* get_small_object_allocator(uint32_t type); ++ ++ LinkerSmallObjectAllocator allocators_[kSmallObjectAllocatorsCount]; ++}; ++ ++ ++#endif /* __LINKER_ALLOCATOR_H */ --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/hybris/common/sysconf.c -@@ -0,0 +1,376 @@ ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_block_allocator.cpp +@@ -0,0 +1,137 @@ ++/* ++ * Copyright (C) 2014 The Android Open Source Project ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++#include "linker_block_allocator.h" ++#include ++#include ++#include +#include + ++#include "private/bionic_prctl.h" ++ ++#include "hybris_compat.h" ++ ++struct LinkerBlockAllocatorPage { ++ LinkerBlockAllocatorPage* next; ++ uint8_t bytes[PAGE_SIZE-sizeof(LinkerBlockAllocatorPage*)]; ++}; ++ ++struct FreeBlockInfo { ++ void* next_block; ++ size_t num_free_blocks; ++}; ++ ++LinkerBlockAllocator::LinkerBlockAllocator(size_t block_size) ++ : block_size_(block_size < sizeof(FreeBlockInfo) ? sizeof(FreeBlockInfo) : block_size), ++ page_list_(nullptr), ++ free_block_list_(nullptr) ++{} ++ ++void* LinkerBlockAllocator::alloc() { ++ if (free_block_list_ == nullptr) { ++ create_new_page(); ++ } ++ ++ FreeBlockInfo* block_info = reinterpret_cast(free_block_list_); ++ if (block_info->num_free_blocks > 1) { ++ FreeBlockInfo* next_block_info = reinterpret_cast( ++ reinterpret_cast(free_block_list_) + block_size_); ++ next_block_info->next_block = block_info->next_block; ++ next_block_info->num_free_blocks = block_info->num_free_blocks - 1; ++ free_block_list_ = next_block_info; ++ } else { ++ free_block_list_ = block_info->next_block; ++ } ++ ++ memset(block_info, 0, block_size_); ++ ++ return block_info; ++} ++ ++void LinkerBlockAllocator::free(void* block) { ++ if (block == nullptr) { ++ return; ++ } ++ ++ LinkerBlockAllocatorPage* page = find_page(block); ++ ++ if (page == nullptr) { ++ abort(); ++ } ++ ++ ssize_t offset = reinterpret_cast(block) - page->bytes; ++ ++ if (offset % block_size_ != 0) { ++ abort(); ++ } ++ ++ memset(block, 0, block_size_); ++ ++ FreeBlockInfo* block_info = reinterpret_cast(block); ++ ++ block_info->next_block = free_block_list_; ++ block_info->num_free_blocks = 1; ++ ++ free_block_list_ = block_info; ++} ++ ++void LinkerBlockAllocator::protect_all(int prot) { ++ for (LinkerBlockAllocatorPage* page = page_list_; page != nullptr; page = page->next) { ++ if (mprotect(page, PAGE_SIZE, prot) == -1) { ++ abort(); ++ } ++ } ++} ++ ++void LinkerBlockAllocator::create_new_page() { ++ LinkerBlockAllocatorPage* page = reinterpret_cast( ++ mmap(nullptr, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0)); ++ ++ if (page == MAP_FAILED) { ++ abort(); // oom ++ } ++ ++ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, page, PAGE_SIZE, "linker_alloc"); ++ ++ memset(page, 0, PAGE_SIZE); ++ ++ FreeBlockInfo* first_block = reinterpret_cast(page->bytes); ++ first_block->next_block = free_block_list_; ++ first_block->num_free_blocks = (PAGE_SIZE - sizeof(LinkerBlockAllocatorPage*))/block_size_; ++ ++ free_block_list_ = first_block; ++ ++ page->next = page_list_; ++ page_list_ = page; ++} ++ ++LinkerBlockAllocatorPage* LinkerBlockAllocator::find_page(void* block) { ++ if (block == nullptr) { ++ abort(); ++ } ++ ++ LinkerBlockAllocatorPage* page = page_list_; ++ while (page != nullptr) { ++ const uint8_t* page_ptr = reinterpret_cast(page); ++ if (block >= (page_ptr + sizeof(page->next)) && block < (page_ptr + PAGE_SIZE)) { ++ return page; ++ } ++ ++ page = page->next; ++ } ++ ++ abort(); ++} +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_block_allocator.h +@@ -0,0 +1,81 @@ ++/* ++ * Copyright (C) 2014 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 __LINKER_BLOCK_ALLOCATOR_H ++#define __LINKER_BLOCK_ALLOCATOR_H ++ ++#include ++#include ++#include "private/bionic_macros.h" ++ ++struct LinkerBlockAllocatorPage; ++ +/* -+ * bionic/libc/include/sys/sysconf.h processed with s/define _\(\w*\)\(.*\)/define \1\2\r#ifdef _\1\rMAP_TO_UNISTD(\1),\r#endif/g ++ * This class is a non-template version of the LinkerTypeAllocator ++ * It keeps code inside .cpp file by keeping the interface ++ * template-free. ++ * ++ * Please use LinkerTypeAllocator where possible (everywhere). + */ -+#define MAP_TO_UNISTD(a) [a]=_##a -+static int sysconf_map[]= { -+#define SC_ARG_MAX 0x0000 -+#ifdef _SC_ARG_MAX -+MAP_TO_UNISTD(SC_ARG_MAX), -+#endif -+#define SC_BC_BASE_MAX 0x0001 -+#ifdef _SC_BC_BASE_MAX -+MAP_TO_UNISTD(SC_BC_BASE_MAX), -+#endif -+#define SC_BC_DIM_MAX 0x0002 -+#ifdef _SC_BC_DIM_MAX -+MAP_TO_UNISTD(SC_BC_DIM_MAX), -+#endif -+#define SC_BC_SCALE_MAX 0x0003 -+#ifdef _SC_BC_SCALE_MAX -+MAP_TO_UNISTD(SC_BC_SCALE_MAX), -+#endif -+#define SC_BC_STRING_MAX 0x0004 -+#ifdef _SC_BC_STRING_MAX -+MAP_TO_UNISTD(SC_BC_STRING_MAX), -+#endif -+#define SC_CHILD_MAX 0x0005 -+#ifdef _SC_CHILD_MAX -+MAP_TO_UNISTD(SC_CHILD_MAX), -+#endif -+#define SC_CLK_TCK 0x0006 -+#ifdef _SC_CLK_TCK -+MAP_TO_UNISTD(SC_CLK_TCK), -+#endif -+#define SC_COLL_WEIGHTS_MAX 0x0007 -+#ifdef _SC_COLL_WEIGHTS_MAX -+MAP_TO_UNISTD(SC_COLL_WEIGHTS_MAX), -+#endif -+#define SC_EXPR_NEST_MAX 0x0008 -+#ifdef _SC_EXPR_NEST_MAX -+MAP_TO_UNISTD(SC_EXPR_NEST_MAX), -+#endif -+#define SC_LINE_MAX 0x0009 -+#ifdef _SC_LINE_MAX -+MAP_TO_UNISTD(SC_LINE_MAX), -+#endif -+#define SC_NGROUPS_MAX 0x000a -+#ifdef _SC_NGROUPS_MAX -+MAP_TO_UNISTD(SC_NGROUPS_MAX), -+#endif -+#define SC_OPEN_MAX 0x000b -+#ifdef _SC_OPEN_MAX -+MAP_TO_UNISTD(SC_OPEN_MAX), -+#endif -+#define SC_PASS_MAX 0x000c -+#ifdef _SC_PASS_MAX -+MAP_TO_UNISTD(SC_PASS_MAX), -+#endif -+#define SC_2_C_BIND 0x000d -+#ifdef _SC_2_C_BIND -+MAP_TO_UNISTD(SC_2_C_BIND), -+#endif -+#define SC_2_C_DEV 0x000e -+#ifdef _SC_2_C_DEV -+MAP_TO_UNISTD(SC_2_C_DEV), -+#endif -+#define SC_2_C_VERSION 0x000f -+#ifdef _SC_2_C_VERSION -+MAP_TO_UNISTD(SC_2_C_VERSION), -+#endif -+#define SC_2_CHAR_TERM 0x0010 -+#ifdef _SC_2_CHAR_TERM -+MAP_TO_UNISTD(SC_2_CHAR_TERM), -+#endif -+#define SC_2_FORT_DEV 0x0011 -+#ifdef _SC_2_FORT_DEV -+MAP_TO_UNISTD(SC_2_FORT_DEV), -+#endif -+#define SC_2_FORT_RUN 0x0012 -+#ifdef _SC_2_FORT_RUN -+MAP_TO_UNISTD(SC_2_FORT_RUN), -+#endif -+#define SC_2_LOCALEDEF 0x0013 -+#ifdef _SC_2_LOCALEDEF -+MAP_TO_UNISTD(SC_2_LOCALEDEF), -+#endif -+#define SC_2_SW_DEV 0x0014 -+#ifdef _SC_2_SW_DEV -+MAP_TO_UNISTD(SC_2_SW_DEV), -+#endif -+#define SC_2_UPE 0x0015 -+#ifdef _SC_2_UPE -+MAP_TO_UNISTD(SC_2_UPE), -+#endif -+#define SC_2_VERSION 0x0016 -+#ifdef _SC_2_VERSION -+MAP_TO_UNISTD(SC_2_VERSION), -+#endif -+#define SC_JOB_CONTROL 0x0017 -+#ifdef _SC_JOB_CONTROL -+MAP_TO_UNISTD(SC_JOB_CONTROL), -+#endif -+#define SC_SAVED_IDS 0x0018 -+#ifdef _SC_SAVED_IDS -+MAP_TO_UNISTD(SC_SAVED_IDS), -+#endif -+#define SC_VERSION 0x0019 -+#ifdef _SC_VERSION -+MAP_TO_UNISTD(SC_VERSION), -+#endif -+#define SC_RE_DUP_MAX 0x001a -+#ifdef _SC_RE_DUP_MAX -+MAP_TO_UNISTD(SC_RE_DUP_MAX), -+#endif -+#define SC_STREAM_MAX 0x001b -+#ifdef _SC_STREAM_MAX -+MAP_TO_UNISTD(SC_STREAM_MAX), -+#endif -+#define SC_TZNAME_MAX 0x001c -+#ifdef _SC_TZNAME_MAX -+MAP_TO_UNISTD(SC_TZNAME_MAX), -+#endif -+#define SC_XOPEN_CRYPT 0x001d -+#ifdef _SC_XOPEN_CRYPT -+MAP_TO_UNISTD(SC_XOPEN_CRYPT), -+#endif -+#define SC_XOPEN_ENH_I18N 0x001e -+#ifdef _SC_XOPEN_ENH_I18N -+MAP_TO_UNISTD(SC_XOPEN_ENH_I18N), -+#endif -+#define SC_XOPEN_SHM 0x001f -+#ifdef _SC_XOPEN_SHM -+MAP_TO_UNISTD(SC_XOPEN_SHM), -+#endif -+#define SC_XOPEN_VERSION 0x0020 -+#ifdef _SC_XOPEN_VERSION -+MAP_TO_UNISTD(SC_XOPEN_VERSION), -+#endif -+#define SC_XOPEN_XCU_VERSION 0x0021 -+#ifdef _SC_XOPEN_XCU_VERSION -+MAP_TO_UNISTD(SC_XOPEN_XCU_VERSION), -+#endif -+#define SC_XOPEN_REALTIME 0x0022 -+#ifdef _SC_XOPEN_REALTIME -+MAP_TO_UNISTD(SC_XOPEN_REALTIME), -+#endif -+#define SC_XOPEN_REALTIME_THREADS 0x0023 -+#ifdef _SC_XOPEN_REALTIME_THREADS -+MAP_TO_UNISTD(SC_XOPEN_REALTIME_THREADS), -+#endif -+#define SC_XOPEN_LEGACY 0x0024 -+#ifdef _SC_XOPEN_LEGACY -+MAP_TO_UNISTD(SC_XOPEN_LEGACY), -+#endif -+#define SC_ATEXIT_MAX 0x0025 -+#ifdef _SC_ATEXIT_MAX -+MAP_TO_UNISTD(SC_ATEXIT_MAX), -+#endif -+#define SC_IOV_MAX 0x0026 -+#ifdef _SC_IOV_MAX -+MAP_TO_UNISTD(SC_IOV_MAX), -+#endif -+#define SC_PAGESIZE 0x0027 -+#ifdef _SC_PAGESIZE -+MAP_TO_UNISTD(SC_PAGESIZE), -+#endif -+#define SC_PAGE_SIZE 0x0028 -+#ifdef _SC_PAGE_SIZE -+MAP_TO_UNISTD(SC_PAGE_SIZE), -+#endif -+#define SC_XOPEN_UNIX 0x0029 -+#ifdef _SC_XOPEN_UNIX -+MAP_TO_UNISTD(SC_XOPEN_UNIX), -+#endif -+#define SC_XBS5_ILP32_OFF32 0x002a -+#ifdef _SC_XBS5_ILP32_OFF32 -+MAP_TO_UNISTD(SC_XBS5_ILP32_OFF32), -+#endif -+#define SC_XBS5_ILP32_OFFBIG 0x002b -+#ifdef _SC_XBS5_ILP32_OFFBIG -+MAP_TO_UNISTD(SC_XBS5_ILP32_OFFBIG), -+#endif -+#define SC_XBS5_LP64_OFF64 0x002c -+#ifdef _SC_XBS5_LP64_OFF64 -+MAP_TO_UNISTD(SC_XBS5_LP64_OFF64), -+#endif -+#define SC_XBS5_LPBIG_OFFBIG 0x002d -+#ifdef _SC_XBS5_LPBIG_OFFBIG -+MAP_TO_UNISTD(SC_XBS5_LPBIG_OFFBIG), -+#endif -+#define SC_AIO_LISTIO_MAX 0x002e -+#ifdef _SC_AIO_LISTIO_MAX -+MAP_TO_UNISTD(SC_AIO_LISTIO_MAX), -+#endif -+#define SC_AIO_MAX 0x002f -+#ifdef _SC_AIO_MAX -+MAP_TO_UNISTD(SC_AIO_MAX), -+#endif -+#define SC_AIO_PRIO_DELTA_MAX 0x0030 -+#ifdef _SC_AIO_PRIO_DELTA_MAX -+MAP_TO_UNISTD(SC_AIO_PRIO_DELTA_MAX), -+#endif -+#define SC_DELAYTIMER_MAX 0x0031 -+#ifdef _SC_DELAYTIMER_MAX -+MAP_TO_UNISTD(SC_DELAYTIMER_MAX), -+#endif -+#define SC_MQ_OPEN_MAX 0x0032 -+#ifdef _SC_MQ_OPEN_MAX -+MAP_TO_UNISTD(SC_MQ_OPEN_MAX), -+#endif -+#define SC_MQ_PRIO_MAX 0x0033 -+#ifdef _SC_MQ_PRIO_MAX -+MAP_TO_UNISTD(SC_MQ_PRIO_MAX), -+#endif -+#define SC_RTSIG_MAX 0x0034 -+#ifdef _SC_RTSIG_MAX -+MAP_TO_UNISTD(SC_RTSIG_MAX), -+#endif -+#define SC_SEM_NSEMS_MAX 0x0035 -+#ifdef _SC_SEM_NSEMS_MAX -+MAP_TO_UNISTD(SC_SEM_NSEMS_MAX), -+#endif -+#define SC_SEM_VALUE_MAX 0x0036 -+#ifdef _SC_SEM_VALUE_MAX -+MAP_TO_UNISTD(SC_SEM_VALUE_MAX), -+#endif -+#define SC_SIGQUEUE_MAX 0x0037 -+#ifdef _SC_SIGQUEUE_MAX -+MAP_TO_UNISTD(SC_SIGQUEUE_MAX), -+#endif -+#define SC_TIMER_MAX 0x0038 -+#ifdef _SC_TIMER_MAX -+MAP_TO_UNISTD(SC_TIMER_MAX), -+#endif -+#define SC_ASYNCHRONOUS_IO 0x0039 -+#ifdef _SC_ASYNCHRONOUS_IO -+MAP_TO_UNISTD(SC_ASYNCHRONOUS_IO), -+#endif -+#define SC_FSYNC 0x003a -+#ifdef _SC_FSYNC -+MAP_TO_UNISTD(SC_FSYNC), -+#endif -+#define SC_MAPPED_FILES 0x003b -+#ifdef _SC_MAPPED_FILES -+MAP_TO_UNISTD(SC_MAPPED_FILES), -+#endif -+#define SC_MEMLOCK 0x003c -+#ifdef _SC_MEMLOCK -+MAP_TO_UNISTD(SC_MEMLOCK), -+#endif -+#define SC_MEMLOCK_RANGE 0x003d -+#ifdef _SC_MEMLOCK_RANGE -+MAP_TO_UNISTD(SC_MEMLOCK_RANGE), -+#endif -+#define SC_MEMORY_PROTECTION 0x003e -+#ifdef _SC_MEMORY_PROTECTION -+MAP_TO_UNISTD(SC_MEMORY_PROTECTION), -+#endif -+#define SC_MESSAGE_PASSING 0x003f -+#ifdef _SC_MESSAGE_PASSING -+MAP_TO_UNISTD(SC_MESSAGE_PASSING), -+#endif -+#define SC_PRIORITIZED_IO 0x0040 -+#ifdef _SC_PRIORITIZED_IO -+MAP_TO_UNISTD(SC_PRIORITIZED_IO), -+#endif -+#define SC_PRIORITY_SCHEDULING 0x0041 -+#ifdef _SC_PRIORITY_SCHEDULING -+MAP_TO_UNISTD(SC_PRIORITY_SCHEDULING), -+#endif -+#define SC_REALTIME_SIGNALS 0x0042 -+#ifdef _SC_REALTIME_SIGNALS -+MAP_TO_UNISTD(SC_REALTIME_SIGNALS), -+#endif -+#define SC_SEMAPHORES 0x0043 -+#ifdef _SC_SEMAPHORES -+MAP_TO_UNISTD(SC_SEMAPHORES), -+#endif -+#define SC_SHARED_MEMORY_OBJECTS 0x0044 -+#ifdef _SC_SHARED_MEMORY_OBJECTS -+MAP_TO_UNISTD(SC_SHARED_MEMORY_OBJECTS), -+#endif -+#define SC_SYNCHRONIZED_IO 0x0045 -+#ifdef _SC_SYNCHRONIZED_IO -+MAP_TO_UNISTD(SC_SYNCHRONIZED_IO), -+#endif -+#define SC_TIMERS 0x0046 -+#ifdef _SC_TIMERS -+MAP_TO_UNISTD(SC_TIMERS), -+#endif -+#define SC_GETGR_R_SIZE_MAX 0x0047 -+#ifdef _SC_GETGR_R_SIZE_MAX -+MAP_TO_UNISTD(SC_GETGR_R_SIZE_MAX), -+#endif -+#define SC_GETPW_R_SIZE_MAX 0x0048 -+#ifdef _SC_GETPW_R_SIZE_MAX -+MAP_TO_UNISTD(SC_GETPW_R_SIZE_MAX), -+#endif -+#define SC_LOGIN_NAME_MAX 0x0049 -+#ifdef _SC_LOGIN_NAME_MAX -+MAP_TO_UNISTD(SC_LOGIN_NAME_MAX), -+#endif -+#define SC_THREAD_DESTRUCTOR_ITERATIONS 0x004a -+#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS -+MAP_TO_UNISTD(SC_THREAD_DESTRUCTOR_ITERATIONS), -+#endif -+#define SC_THREAD_KEYS_MAX 0x004b -+#ifdef _SC_THREAD_KEYS_MAX -+MAP_TO_UNISTD(SC_THREAD_KEYS_MAX), -+#endif -+#define SC_THREAD_STACK_MIN 0x004c -+#ifdef _SC_THREAD_STACK_MIN -+MAP_TO_UNISTD(SC_THREAD_STACK_MIN), -+#endif -+#define SC_THREAD_THREADS_MAX 0x004d -+#ifdef _SC_THREAD_THREADS_MAX -+MAP_TO_UNISTD(SC_THREAD_THREADS_MAX), -+#endif -+#define SC_TTY_NAME_MAX 0x004e -+#ifdef _SC_TTY_NAME_MAX -+MAP_TO_UNISTD(SC_TTY_NAME_MAX), ++class LinkerBlockAllocator { ++ public: ++ explicit LinkerBlockAllocator(size_t block_size); ++ ++ void* alloc(); ++ void free(void* block); ++ void protect_all(int prot); ++ ++ private: ++ void create_new_page(); ++ LinkerBlockAllocatorPage* find_page(void* block); ++ ++ size_t block_size_; ++ LinkerBlockAllocatorPage* page_list_; ++ void* free_block_list_; ++ ++ DISALLOW_COPY_AND_ASSIGN(LinkerBlockAllocator); ++}; ++ ++/* ++ * A simple allocator for the dynamic linker. An allocator allocates instances ++ * of a single fixed-size type. Allocations are backed by page-sized private ++ * anonymous mmaps. ++ * ++ * The differences between this allocator and LinkerMemoryAllocator are: ++ * 1. This allocator manages space more efficiently. LinkerMemoryAllocator ++ * operates in power-of-two sized blocks up to 1k, when this implementation ++ * splits the page to aligned size of structure; For example for structures ++ * with size 513 this allocator will use 516 (520 for lp64) bytes of data ++ * where generalized implementation is going to use 1024 sized blocks. ++ * ++ * 2. This allocator does not munmap allocated memory, where LinkerMemoryAllocator does. ++ * ++ * 3. This allocator provides mprotect services to the user, where LinkerMemoryAllocator ++ * always treats it's memory as READ|WRITE. ++ */ ++template ++class LinkerTypeAllocator { ++ public: ++ LinkerTypeAllocator() : block_allocator_(sizeof(T)) {} ++ T* alloc() { return reinterpret_cast(block_allocator_.alloc()); } ++ void free(T* t) { block_allocator_.free(t); } ++ void protect_all(int prot) { block_allocator_.protect_all(prot); } ++ private: ++ LinkerBlockAllocator block_allocator_; ++ DISALLOW_COPY_AND_ASSIGN(LinkerTypeAllocator); ++}; ++ ++#endif // __LINKER_BLOCK_ALLOCATOR_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_debug.h +@@ -0,0 +1,97 @@ ++/* ++ * Copyright (C) 2008 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++#ifndef _LINKER_DEBUG_H_ ++#define _LINKER_DEBUG_H_ ++ ++// You can increase the verbosity of debug traces by defining the LD_DEBUG ++// environment variable to a numeric value from 0 to 2 (corresponding to ++// INFO, TRACE, and DEBUG calls in the source). This will only ++// affect new processes being launched. ++ ++// By default, traces are sent to logcat, with the "linker" tag. You can ++// change this to go to stdout instead by setting the definition of ++// LINKER_DEBUG_TO_LOG to 0. ++#define LINKER_DEBUG_TO_LOG 0 ++ ++#define TRACE_DEBUG 1 ++#define DO_TRACE_LOOKUP 1 ++#define DO_TRACE_RELO 1 ++#define DO_TRACE_IFUNC 1 ++#define TIMING 0 ++#define STATS 0 ++#define COUNT_PAGES 0 ++ ++/********************************************************************* ++ * You shouldn't need to modify anything below unless you are adding ++ * more debugging information. ++ * ++ * To enable/disable specific debug options, change the defines above ++ *********************************************************************/ ++ ++#include "private/libc_logging.h" ++ ++extern int g_ld_debug_verbosity; ++ ++#define _PRINTVF(v, x...) \ ++ do { \ ++ if (g_ld_debug_verbosity > (v)) { fprintf(stderr, x); fprintf(stderr, "\n"); } \ ++ } while (0) ++ ++#define PRINT(x...) _PRINTVF(-1, x) ++#define INFO(x...) _PRINTVF(0, x) ++#define TRACE(x...) _PRINTVF(1, x) ++ ++#if TRACE_DEBUG ++#define DEBUG(x...) _PRINTVF(2, "DEBUG: " x) ++#else /* !TRACE_DEBUG */ ++#define DEBUG(x...) do {} while (0) ++#endif /* TRACE_DEBUG */ ++ ++#define TRACE_TYPE(t, x...) do { if (DO_TRACE_##t) { TRACE(x); } } while (0) ++ ++#if COUNT_PAGES ++extern uint32_t bitmask[]; ++#if defined(__LP64__) ++#define MARK(offset) \ ++ do { \ ++ if ((((offset) >> 12) >> 5) < 4096) \ ++ bitmask[((offset) >> 12) >> 5] |= (1 << (((offset) >> 12) & 31)); \ ++ } while (0) ++#else ++#define MARK(offset) \ ++ do { \ ++ bitmask[((offset) >> 12) >> 3] |= (1 << (((offset) >> 12) & 7)); \ ++ } while (0) +#endif ++#else ++#define MARK(x) do {} while (0) + -+#define SC_THREADS 0x004f -+#ifdef _SC_THREADS -+MAP_TO_UNISTD(SC_THREADS), +#endif -+#define SC_THREAD_ATTR_STACKADDR 0x0050 -+#ifdef _SC_THREAD_ATTR_STACKADDR -+MAP_TO_UNISTD(SC_THREAD_ATTR_STACKADDR), ++ ++#endif /* _LINKER_DEBUG_H_ */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_libc_support.c +@@ -0,0 +1,21 @@ ++/* ++ * Copyright (C) 2014 The Android Open Source Project ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++#include "../libc/arch-common/bionic/__dso_handle.h" ++ ++int atexit(void (*function)(void) __attribute__((__unused__))) { ++ return -1; ++} +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_memory.cpp +@@ -0,0 +1,40 @@ ++/* ++ * Copyright (C) 2015 The Android Open Source Project ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++#include "linker_allocator.h" ++ ++#include ++ ++#if DISABLED_FOR_HYBRIS_SUPPORT ++static LinkerMemoryAllocator g_linker_allocator; ++ ++void* malloc(size_t byte_count) { ++ return g_linker_allocator.alloc(byte_count); ++} ++ ++void* calloc(size_t item_count, size_t item_size) { ++ return g_linker_allocator.alloc(item_count*item_size); ++} ++ ++void* realloc(void* p, size_t byte_count) { ++ return g_linker_allocator.realloc(p, byte_count); ++} ++ ++void free(void* ptr) { ++ g_linker_allocator.free(ptr); ++} +#endif -+#define SC_THREAD_ATTR_STACKSIZE 0x0051 -+#ifdef _SC_THREAD_ATTR_STACKSIZE -+MAP_TO_UNISTD(SC_THREAD_ATTR_STACKSIZE), ++ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_phdr.cpp +@@ -0,0 +1,827 @@ ++/* ++ * Copyright (C) 2012 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++#include "linker_phdr.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "linker.h" ++#include "linker_debug.h" ++ ++#include "hybris_compat.h" ++ ++static int GetTargetElfMachine() { ++#if defined(__arm__) ++ return EM_ARM; ++#elif defined(__aarch64__) ++ return EM_AARCH64; ++#elif defined(__i386__) ++ return EM_386; ++#elif defined(__mips__) ++ return EM_MIPS; ++#elif defined(__x86_64__) ++ return EM_X86_64; +#endif -+#define SC_THREAD_PRIORITY_SCHEDULING 0x0052 -+#ifdef _SC_THREAD_PRIORITY_SCHEDULING -+MAP_TO_UNISTD(SC_THREAD_PRIORITY_SCHEDULING), ++} ++ ++/** ++ TECHNICAL NOTE ON ELF LOADING. ++ ++ An ELF file's program header table contains one or more PT_LOAD ++ segments, which corresponds to portions of the file that need to ++ be mapped into the process' address space. ++ ++ Each loadable segment has the following important properties: ++ ++ p_offset -> segment file offset ++ p_filesz -> segment file size ++ p_memsz -> segment memory size (always >= p_filesz) ++ p_vaddr -> segment's virtual address ++ p_flags -> segment flags (e.g. readable, writable, executable) ++ ++ We will ignore the p_paddr and p_align fields of ElfW(Phdr) for now. ++ ++ The loadable segments can be seen as a list of [p_vaddr ... p_vaddr+p_memsz) ++ ranges of virtual addresses. A few rules apply: ++ ++ - the virtual address ranges should not overlap. ++ ++ - if a segment's p_filesz is smaller than its p_memsz, the extra bytes ++ between them should always be initialized to 0. ++ ++ - ranges do not necessarily start or end at page boundaries. Two distinct ++ segments can have their start and end on the same page. In this case, the ++ page inherits the mapping flags of the latter segment. ++ ++ Finally, the real load addrs of each segment is not p_vaddr. Instead the ++ loader decides where to load the first segment, then will load all others ++ relative to the first one to respect the initial range layout. ++ ++ For example, consider the following list: ++ ++ [ offset:0, filesz:0x4000, memsz:0x4000, vaddr:0x30000 ], ++ [ offset:0x4000, filesz:0x2000, memsz:0x8000, vaddr:0x40000 ], ++ ++ This corresponds to two segments that cover these virtual address ranges: ++ ++ 0x30000...0x34000 ++ 0x40000...0x48000 ++ ++ If the loader decides to load the first segment at address 0xa0000000 ++ then the segments' load address ranges will be: ++ ++ 0xa0030000...0xa0034000 ++ 0xa0040000...0xa0048000 ++ ++ In other words, all segments must be loaded at an address that has the same ++ constant offset from their p_vaddr value. This offset is computed as the ++ difference between the first segment's load address, and its p_vaddr value. ++ ++ However, in practice, segments do _not_ start at page boundaries. Since we ++ can only memory-map at page boundaries, this means that the bias is ++ computed as: ++ ++ load_bias = phdr0_load_address - PAGE_START(phdr0->p_vaddr) ++ ++ (NOTE: The value must be used as a 32-bit unsigned integer, to deal with ++ possible wrap around UINT32_MAX for possible large p_vaddr values). ++ ++ And that the phdr0_load_address must start at a page boundary, with ++ the segment's real content starting at: ++ ++ phdr0_load_address + PAGE_OFFSET(phdr0->p_vaddr) ++ ++ Note that ELF requires the following condition to make the mmap()-ing work: ++ ++ PAGE_OFFSET(phdr0->p_vaddr) == PAGE_OFFSET(phdr0->p_offset) ++ ++ The load_bias must be added to any p_vaddr value read from the ELF file to ++ determine the corresponding memory address. ++ ++ **/ ++ ++#define MAYBE_MAP_FLAG(x, from, to) (((x) & (from)) ? (to) : 0) ++#define PFLAGS_TO_PROT(x) (MAYBE_MAP_FLAG((x), PF_X, PROT_EXEC) | \ ++ MAYBE_MAP_FLAG((x), PF_R, PROT_READ) | \ ++ MAYBE_MAP_FLAG((x), PF_W, PROT_WRITE)) ++ ++ElfReader::ElfReader(const char* name, int fd, off64_t file_offset, off64_t file_size) ++ : name_(name), fd_(fd), file_offset_(file_offset), file_size_(file_size), ++ phdr_num_(0), phdr_mmap_(nullptr), phdr_table_(nullptr), phdr_size_(0), ++ load_start_(nullptr), load_size_(0), load_bias_(0), ++ loaded_phdr_(nullptr) { ++} ++ ++ElfReader::~ElfReader() { ++ if (phdr_mmap_ != nullptr) { ++ munmap(phdr_mmap_, phdr_size_); ++ } ++} ++ ++bool ElfReader::Load(const android_dlextinfo* extinfo) { ++ return ReadElfHeader() && ++ VerifyElfHeader() && ++ ReadProgramHeader() && ++ ReserveAddressSpace(extinfo) && ++ LoadSegments() && ++ FindPhdr(); ++} ++ ++bool ElfReader::ReadElfHeader() { ++ ssize_t rc = TEMP_FAILURE_RETRY(pread64(fd_, &header_, sizeof(header_), file_offset_)); ++ if (rc < 0) { ++ DL_ERR("can't read file \"%s\": %s", name_, strerror(errno)); ++ return false; ++ } ++ ++ if (rc != sizeof(header_)) { ++ DL_ERR("\"%s\" is too small to be an ELF executable: only found %zd bytes", name_, ++ static_cast(rc)); ++ return false; ++ } ++ return true; ++} ++ ++bool ElfReader::VerifyElfHeader() { ++ if (memcmp(header_.e_ident, ELFMAG, SELFMAG) != 0) { ++ DL_ERR("\"%s\" has bad ELF magic", name_); ++ return false; ++ } ++ ++ // Try to give a clear diagnostic for ELF class mismatches, since they're ++ // an easy mistake to make during the 32-bit/64-bit transition period. ++ int elf_class = header_.e_ident[EI_CLASS]; ++#if defined(__LP64__) ++ if (elf_class != ELFCLASS64) { ++ if (elf_class == ELFCLASS32) { ++ DL_ERR("\"%s\" is 32-bit instead of 64-bit", name_); ++ } else { ++ DL_ERR("\"%s\" has unknown ELF class: %d", name_, elf_class); ++ } ++ return false; ++ } ++#else ++ if (elf_class != ELFCLASS32) { ++ if (elf_class == ELFCLASS64) { ++ DL_ERR("\"%s\" is 64-bit instead of 32-bit", name_); ++ } else { ++ DL_ERR("\"%s\" has unknown ELF class: %d", name_, elf_class); ++ } ++ return false; ++ } +#endif -+#define SC_THREAD_PRIO_INHERIT 0x0053 -+#ifdef _SC_THREAD_PRIO_INHERIT -+MAP_TO_UNISTD(SC_THREAD_PRIO_INHERIT), ++ ++ if (header_.e_ident[EI_DATA] != ELFDATA2LSB) { ++ DL_ERR("\"%s\" not little-endian: %d", name_, header_.e_ident[EI_DATA]); ++ return false; ++ } ++ ++ if (header_.e_type != ET_DYN) { ++ DL_ERR("\"%s\" has unexpected e_type: %d", name_, header_.e_type); ++ return false; ++ } ++ ++ if (header_.e_version != EV_CURRENT) { ++ DL_ERR("\"%s\" has unexpected e_version: %d", name_, header_.e_version); ++ return false; ++ } ++ ++ if (header_.e_machine != GetTargetElfMachine()) { ++ DL_ERR("\"%s\" has unexpected e_machine: %d", name_, header_.e_machine); ++ return false; ++ } ++ ++ return true; ++} ++ ++// Loads the program header table from an ELF file into a read-only private ++// anonymous mmap-ed block. ++bool ElfReader::ReadProgramHeader() { ++ phdr_num_ = header_.e_phnum; ++ ++ // Like the kernel, we only accept program header tables that ++ // are smaller than 64KiB. ++ if (phdr_num_ < 1 || phdr_num_ > 65536/sizeof(ElfW(Phdr))) { ++ DL_ERR("\"%s\" has invalid e_phnum: %zd", name_, phdr_num_); ++ return false; ++ } ++ ++ ElfW(Addr) page_min = PAGE_START(header_.e_phoff); ++ ElfW(Addr) page_max = PAGE_END(header_.e_phoff + (phdr_num_ * sizeof(ElfW(Phdr)))); ++ ElfW(Addr) page_offset = PAGE_OFFSET(header_.e_phoff); ++ ++ phdr_size_ = page_max - page_min; ++ ++ void* mmap_result = ++ mmap64(nullptr, phdr_size_, PROT_READ, MAP_PRIVATE, fd_, file_offset_ + page_min); ++ if (mmap_result == MAP_FAILED) { ++ DL_ERR("\"%s\" phdr mmap failed: %s", name_, strerror(errno)); ++ return false; ++ } ++ ++ phdr_mmap_ = mmap_result; ++ phdr_table_ = reinterpret_cast(reinterpret_cast(mmap_result) + page_offset); ++ return true; ++} ++ ++/* Returns the size of the extent of all the possibly non-contiguous ++ * loadable segments in an ELF program header table. This corresponds ++ * to the page-aligned size in bytes that needs to be reserved in the ++ * process' address space. If there are no loadable segments, 0 is ++ * returned. ++ * ++ * If out_min_vaddr or out_max_vaddr are not null, they will be ++ * set to the minimum and maximum addresses of pages to be reserved, ++ * or 0 if there is nothing to load. ++ */ ++size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count, ++ ElfW(Addr)* out_min_vaddr, ++ ElfW(Addr)* out_max_vaddr) { ++ ElfW(Addr) min_vaddr = UINTPTR_MAX; ++ ElfW(Addr) max_vaddr = 0; ++ ++ bool found_pt_load = false; ++ for (size_t i = 0; i < phdr_count; ++i) { ++ const ElfW(Phdr)* phdr = &phdr_table[i]; ++ ++ if (phdr->p_type != PT_LOAD) { ++ continue; ++ } ++ found_pt_load = true; ++ ++ if (phdr->p_vaddr < min_vaddr) { ++ min_vaddr = phdr->p_vaddr; ++ } ++ ++ if (phdr->p_vaddr + phdr->p_memsz > max_vaddr) { ++ max_vaddr = phdr->p_vaddr + phdr->p_memsz; ++ } ++ } ++ if (!found_pt_load) { ++ min_vaddr = 0; ++ } ++ ++ min_vaddr = PAGE_START(min_vaddr); ++ max_vaddr = PAGE_END(max_vaddr); ++ ++ if (out_min_vaddr != nullptr) { ++ *out_min_vaddr = min_vaddr; ++ } ++ if (out_max_vaddr != nullptr) { ++ *out_max_vaddr = max_vaddr; ++ } ++ return max_vaddr - min_vaddr; ++} ++ ++// Reserve a virtual address range big enough to hold all loadable ++// segments of a program header table. This is done by creating a ++// private anonymous mmap() with PROT_NONE. ++bool ElfReader::ReserveAddressSpace(const android_dlextinfo* extinfo) { ++ ElfW(Addr) min_vaddr; ++ load_size_ = phdr_table_get_load_size(phdr_table_, phdr_num_, &min_vaddr); ++ if (load_size_ == 0) { ++ DL_ERR("\"%s\" has no loadable segments", name_); ++ return false; ++ } ++ ++ uint8_t* addr = reinterpret_cast(min_vaddr); ++ void* start; ++ size_t reserved_size = 0; ++ bool reserved_hint = true; ++ // Assume position independent executable by default. ++ uint8_t* mmap_hint = nullptr; ++ ++ if (extinfo != nullptr) { ++ if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS) { ++ reserved_size = extinfo->reserved_size; ++ reserved_hint = false; ++ } else if (extinfo->flags & ANDROID_DLEXT_RESERVED_ADDRESS_HINT) { ++ reserved_size = extinfo->reserved_size; ++ } ++ ++ if ((extinfo->flags & ANDROID_DLEXT_FORCE_FIXED_VADDR) != 0) { ++ mmap_hint = addr; ++ } ++ } ++ ++ if (load_size_ > reserved_size) { ++ if (!reserved_hint) { ++ DL_ERR("reserved address space %zd smaller than %zd bytes needed for \"%s\"", ++ reserved_size - load_size_, load_size_, name_); ++ return false; ++ } ++ int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS; ++ start = mmap(mmap_hint, load_size_, PROT_NONE, mmap_flags, -1, 0); ++ if (start == MAP_FAILED) { ++ DL_ERR("couldn't reserve %zd bytes of address space for \"%s\"", load_size_, name_); ++ return false; ++ } ++ } else { ++ start = extinfo->reserved_addr; ++ } ++ ++ load_start_ = start; ++ load_bias_ = reinterpret_cast(start) - addr; ++ return true; ++} ++ ++bool ElfReader::LoadSegments() { ++ for (size_t i = 0; i < phdr_num_; ++i) { ++ const ElfW(Phdr)* phdr = &phdr_table_[i]; ++ ++ if (phdr->p_type != PT_LOAD) { ++ continue; ++ } ++ ++ // Segment addresses in memory. ++ ElfW(Addr) seg_start = phdr->p_vaddr + load_bias_; ++ ElfW(Addr) seg_end = seg_start + phdr->p_memsz; ++ ++ ElfW(Addr) seg_page_start = PAGE_START(seg_start); ++ ElfW(Addr) seg_page_end = PAGE_END(seg_end); ++ ++ ElfW(Addr) seg_file_end = seg_start + phdr->p_filesz; ++ ++ // File offsets. ++ ElfW(Addr) file_start = phdr->p_offset; ++ ElfW(Addr) file_end = file_start + phdr->p_filesz; ++ ++ ElfW(Addr) file_page_start = PAGE_START(file_start); ++ ElfW(Addr) file_length = file_end - file_page_start; ++ ++ if (file_size_ <= 0) { ++ DL_ERR("\"%s\" invalid file size: %" PRId64, name_, file_size_); ++ return false; ++ } ++ ++ if (file_end >= static_cast(file_size_)) { ++ DL_ERR("invalid ELF file \"%s\" load segment[%zd]:" ++ " p_offset (%p) + p_filesz (%p) ( = %p) past end of file (0x%" PRIx64 ")", ++ name_, i, reinterpret_cast(phdr->p_offset), ++ reinterpret_cast(phdr->p_filesz), ++ reinterpret_cast(file_end), file_size_); ++ return false; ++ } ++ ++ if (file_length != 0) { ++ void* seg_addr = mmap64(reinterpret_cast(seg_page_start), ++ file_length, ++ PFLAGS_TO_PROT(phdr->p_flags), ++ MAP_FIXED|MAP_PRIVATE, ++ fd_, ++ file_offset_ + file_page_start); ++ if (seg_addr == MAP_FAILED) { ++ DL_ERR("couldn't map \"%s\" segment %zd: %s", name_, i, strerror(errno)); ++ return false; ++ } ++ } ++ ++ // if the segment is writable, and does not end on a page boundary, ++ // zero-fill it until the page limit. ++ if ((phdr->p_flags & PF_W) != 0 && PAGE_OFFSET(seg_file_end) > 0) { ++ memset(reinterpret_cast(seg_file_end), 0, PAGE_SIZE - PAGE_OFFSET(seg_file_end)); ++ } ++ ++ seg_file_end = PAGE_END(seg_file_end); ++ ++ // seg_file_end is now the first page address after the file ++ // content. If seg_end is larger, we need to zero anything ++ // between them. This is done by using a private anonymous ++ // map for all extra pages. ++ if (seg_page_end > seg_file_end) { ++ void* zeromap = mmap(reinterpret_cast(seg_file_end), ++ seg_page_end - seg_file_end, ++ PFLAGS_TO_PROT(phdr->p_flags), ++ MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, ++ -1, ++ 0); ++ if (zeromap == MAP_FAILED) { ++ DL_ERR("couldn't zero fill \"%s\" gap: %s", name_, strerror(errno)); ++ return false; ++ } ++ } ++ } ++ return true; ++} ++ ++/* Used internally. Used to set the protection bits of all loaded segments ++ * with optional extra flags (i.e. really PROT_WRITE). Used by ++ * phdr_table_protect_segments and phdr_table_unprotect_segments. ++ */ ++static int _phdr_table_set_load_prot(const ElfW(Phdr)* phdr_table, size_t phdr_count, ++ ElfW(Addr) load_bias, int extra_prot_flags) { ++ const ElfW(Phdr)* phdr = phdr_table; ++ const ElfW(Phdr)* phdr_limit = phdr + phdr_count; ++ ++ for (; phdr < phdr_limit; phdr++) { ++ if (phdr->p_type != PT_LOAD || (phdr->p_flags & PF_W) != 0) { ++ continue; ++ } ++ ++ ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias; ++ ElfW(Addr) seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias; ++ ++ int prot = PFLAGS_TO_PROT(phdr->p_flags); ++ if ((extra_prot_flags & PROT_WRITE) != 0) { ++ // make sure we're never simultaneously writable / executable ++ prot &= ~PROT_EXEC; ++ } ++ ++ int ret = mprotect(reinterpret_cast(seg_page_start), ++ seg_page_end - seg_page_start, ++ prot | extra_prot_flags); ++ if (ret < 0) { ++ return -1; ++ } ++ } ++ return 0; ++} ++ ++/* Restore the original protection modes for all loadable segments. ++ * You should only call this after phdr_table_unprotect_segments and ++ * applying all relocations. ++ * ++ * Input: ++ * phdr_table -> program header table ++ * phdr_count -> number of entries in tables ++ * load_bias -> load bias ++ * Return: ++ * 0 on error, -1 on failure (error code in errno). ++ */ ++int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table, ++ size_t phdr_count, ElfW(Addr) load_bias) { ++ return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, 0); ++} ++ ++/* Change the protection of all loaded segments in memory to writable. ++ * This is useful before performing relocations. Once completed, you ++ * will have to call phdr_table_protect_segments to restore the original ++ * protection flags on all segments. ++ * ++ * Note that some writable segments can also have their content turned ++ * to read-only by calling phdr_table_protect_gnu_relro. This is no ++ * performed here. ++ * ++ * Input: ++ * phdr_table -> program header table ++ * phdr_count -> number of entries in tables ++ * load_bias -> load bias ++ * Return: ++ * 0 on error, -1 on failure (error code in errno). ++ */ ++int phdr_table_unprotect_segments(const ElfW(Phdr)* phdr_table, ++ size_t phdr_count, ElfW(Addr) load_bias) { ++ return _phdr_table_set_load_prot(phdr_table, phdr_count, load_bias, PROT_WRITE); ++} ++ ++/* Used internally by phdr_table_protect_gnu_relro and ++ * phdr_table_unprotect_gnu_relro. ++ */ ++static int _phdr_table_set_gnu_relro_prot(const ElfW(Phdr)* phdr_table, size_t phdr_count, ++ ElfW(Addr) load_bias, int prot_flags) { ++ const ElfW(Phdr)* phdr = phdr_table; ++ const ElfW(Phdr)* phdr_limit = phdr + phdr_count; ++ ++ for (phdr = phdr_table; phdr < phdr_limit; phdr++) { ++ if (phdr->p_type != PT_GNU_RELRO) { ++ continue; ++ } ++ ++ // Tricky: what happens when the relro segment does not start ++ // or end at page boundaries? We're going to be over-protective ++ // here and put every page touched by the segment as read-only. ++ ++ // This seems to match Ian Lance Taylor's description of the ++ // feature at http://www.airs.com/blog/archives/189. ++ ++ // Extract: ++ // Note that the current dynamic linker code will only work ++ // correctly if the PT_GNU_RELRO segment starts on a page ++ // boundary. This is because the dynamic linker rounds the ++ // p_vaddr field down to the previous page boundary. If ++ // there is anything on the page which should not be read-only, ++ // the program is likely to fail at runtime. So in effect the ++ // linker must only emit a PT_GNU_RELRO segment if it ensures ++ // that it starts on a page boundary. ++ ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias; ++ ElfW(Addr) seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias; ++ ++ int ret = mprotect(reinterpret_cast(seg_page_start), ++ seg_page_end - seg_page_start, ++ prot_flags); ++ if (ret < 0) { ++ return -1; ++ } ++ } ++ return 0; ++} ++ ++/* Apply GNU relro protection if specified by the program header. This will ++ * turn some of the pages of a writable PT_LOAD segment to read-only, as ++ * specified by one or more PT_GNU_RELRO segments. This must be always ++ * performed after relocations. ++ * ++ * The areas typically covered are .got and .data.rel.ro, these are ++ * read-only from the program's POV, but contain absolute addresses ++ * that need to be relocated before use. ++ * ++ * Input: ++ * phdr_table -> program header table ++ * phdr_count -> number of entries in tables ++ * load_bias -> load bias ++ * Return: ++ * 0 on error, -1 on failure (error code in errno). ++ */ ++int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table, ++ size_t phdr_count, ElfW(Addr) load_bias) { ++ return _phdr_table_set_gnu_relro_prot(phdr_table, phdr_count, load_bias, PROT_READ); ++} ++ ++/* Serialize the GNU relro segments to the given file descriptor. This can be ++ * performed after relocations to allow another process to later share the ++ * relocated segment, if it was loaded at the same address. ++ * ++ * Input: ++ * phdr_table -> program header table ++ * phdr_count -> number of entries in tables ++ * load_bias -> load bias ++ * fd -> writable file descriptor to use ++ * Return: ++ * 0 on error, -1 on failure (error code in errno). ++ */ ++int phdr_table_serialize_gnu_relro(const ElfW(Phdr)* phdr_table, ++ size_t phdr_count, ++ ElfW(Addr) load_bias, ++ int fd) { ++ const ElfW(Phdr)* phdr = phdr_table; ++ const ElfW(Phdr)* phdr_limit = phdr + phdr_count; ++ ssize_t file_offset = 0; ++ ++ for (phdr = phdr_table; phdr < phdr_limit; phdr++) { ++ if (phdr->p_type != PT_GNU_RELRO) { ++ continue; ++ } ++ ++ ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias; ++ ElfW(Addr) seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias; ++ ssize_t size = seg_page_end - seg_page_start; ++ ++ ssize_t written = TEMP_FAILURE_RETRY(write(fd, reinterpret_cast(seg_page_start), size)); ++ if (written != size) { ++ return -1; ++ } ++ void* map = mmap(reinterpret_cast(seg_page_start), size, PROT_READ, ++ MAP_PRIVATE|MAP_FIXED, fd, file_offset); ++ if (map == MAP_FAILED) { ++ return -1; ++ } ++ file_offset += size; ++ } ++ return 0; ++} ++ ++/* Where possible, replace the GNU relro segments with mappings of the given ++ * file descriptor. This can be performed after relocations to allow a file ++ * previously created by phdr_table_serialize_gnu_relro in another process to ++ * replace the dirty relocated pages, saving memory, if it was loaded at the ++ * same address. We have to compare the data before we map over it, since some ++ * parts of the relro segment may not be identical due to other libraries in ++ * the process being loaded at different addresses. ++ * ++ * Input: ++ * phdr_table -> program header table ++ * phdr_count -> number of entries in tables ++ * load_bias -> load bias ++ * fd -> readable file descriptor to use ++ * Return: ++ * 0 on error, -1 on failure (error code in errno). ++ */ ++int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table, ++ size_t phdr_count, ++ ElfW(Addr) load_bias, ++ int fd) { ++ // Map the file at a temporary location so we can compare its contents. ++ struct stat file_stat; ++ if (TEMP_FAILURE_RETRY(fstat(fd, &file_stat)) != 0) { ++ return -1; ++ } ++ off_t file_size = file_stat.st_size; ++ void* temp_mapping = nullptr; ++ if (file_size > 0) { ++ temp_mapping = mmap(nullptr, file_size, PROT_READ, MAP_PRIVATE, fd, 0); ++ if (temp_mapping == MAP_FAILED) { ++ return -1; ++ } ++ } ++ size_t file_offset = 0; ++ ++ // Iterate over the relro segments and compare/remap the pages. ++ const ElfW(Phdr)* phdr = phdr_table; ++ const ElfW(Phdr)* phdr_limit = phdr + phdr_count; ++ ++ for (phdr = phdr_table; phdr < phdr_limit; phdr++) { ++ if (phdr->p_type != PT_GNU_RELRO) { ++ continue; ++ } ++ ++ ElfW(Addr) seg_page_start = PAGE_START(phdr->p_vaddr) + load_bias; ++ ElfW(Addr) seg_page_end = PAGE_END(phdr->p_vaddr + phdr->p_memsz) + load_bias; ++ ++ char* file_base = static_cast(temp_mapping) + file_offset; ++ char* mem_base = reinterpret_cast(seg_page_start); ++ size_t match_offset = 0; ++ size_t size = seg_page_end - seg_page_start; ++ ++ if (file_size - file_offset < size) { ++ // File is too short to compare to this segment. The contents are likely ++ // different as well (it's probably for a different library version) so ++ // just don't bother checking. ++ break; ++ } ++ ++ while (match_offset < size) { ++ // Skip over dissimilar pages. ++ while (match_offset < size && ++ memcmp(mem_base + match_offset, file_base + match_offset, PAGE_SIZE) != 0) { ++ match_offset += PAGE_SIZE; ++ } ++ ++ // Count similar pages. ++ size_t mismatch_offset = match_offset; ++ while (mismatch_offset < size && ++ memcmp(mem_base + mismatch_offset, file_base + mismatch_offset, PAGE_SIZE) == 0) { ++ mismatch_offset += PAGE_SIZE; ++ } ++ ++ // Map over similar pages. ++ if (mismatch_offset > match_offset) { ++ void* map = mmap(mem_base + match_offset, mismatch_offset - match_offset, ++ PROT_READ, MAP_PRIVATE|MAP_FIXED, fd, match_offset); ++ if (map == MAP_FAILED) { ++ munmap(temp_mapping, file_size); ++ return -1; ++ } ++ } ++ ++ match_offset = mismatch_offset; ++ } ++ ++ // Add to the base file offset in case there are multiple relro segments. ++ file_offset += size; ++ } ++ munmap(temp_mapping, file_size); ++ return 0; ++} ++ ++ ++#if defined(__arm__) ++ ++# ifndef PT_ARM_EXIDX ++# define PT_ARM_EXIDX 0x70000001 /* .ARM.exidx segment */ ++# endif ++ ++/* Return the address and size of the .ARM.exidx section in memory, ++ * if present. ++ * ++ * Input: ++ * phdr_table -> program header table ++ * phdr_count -> number of entries in tables ++ * load_bias -> load bias ++ * Output: ++ * arm_exidx -> address of table in memory (null on failure). ++ * arm_exidx_count -> number of items in table (0 on failure). ++ * Return: ++ * 0 on error, -1 on failure (_no_ error code in errno) ++ */ ++int phdr_table_get_arm_exidx(const ElfW(Phdr)* phdr_table, size_t phdr_count, ++ ElfW(Addr) load_bias, ++ ElfW(Addr)** arm_exidx, size_t* arm_exidx_count) { ++ const ElfW(Phdr)* phdr = phdr_table; ++ const ElfW(Phdr)* phdr_limit = phdr + phdr_count; ++ ++ for (phdr = phdr_table; phdr < phdr_limit; phdr++) { ++ if (phdr->p_type != PT_ARM_EXIDX) { ++ continue; ++ } ++ ++ *arm_exidx = reinterpret_cast(load_bias + phdr->p_vaddr); ++ *arm_exidx_count = phdr->p_memsz / 8; ++ return 0; ++ } ++ *arm_exidx = nullptr; ++ *arm_exidx_count = 0; ++ return -1; ++} +#endif -+#define SC_THREAD_PRIO_PROTECT 0x0054 -+#ifdef _SC_THREAD_PRIO_PROTECT -+MAP_TO_UNISTD(SC_THREAD_PRIO_PROTECT), ++ ++/* Return the address and size of the ELF file's .dynamic section in memory, ++ * or null if missing. ++ * ++ * Input: ++ * phdr_table -> program header table ++ * phdr_count -> number of entries in tables ++ * load_bias -> load bias ++ * Output: ++ * dynamic -> address of table in memory (null on failure). ++ * dynamic_flags -> protection flags for section (unset on failure) ++ * Return: ++ * void ++ */ ++void phdr_table_get_dynamic_section(const ElfW(Phdr)* phdr_table, size_t phdr_count, ++ ElfW(Addr) load_bias, ElfW(Dyn)** dynamic, ++ ElfW(Word)* dynamic_flags) { ++ *dynamic = nullptr; ++ for (size_t i = 0; i(load_bias + phdr.p_vaddr); ++ if (dynamic_flags) { ++ *dynamic_flags = phdr.p_flags; ++ } ++ return; ++ } ++ } ++} ++ ++// Sets loaded_phdr_ to the address of the program header table as it appears ++// in the loaded segments in memory. This is in contrast with phdr_table_, ++// which is temporary and will be released before the library is relocated. ++bool ElfReader::FindPhdr() { ++ const ElfW(Phdr)* phdr_limit = phdr_table_ + phdr_num_; ++ ++ // If there is a PT_PHDR, use it directly. ++ for (const ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) { ++ if (phdr->p_type == PT_PHDR) { ++ return CheckPhdr(load_bias_ + phdr->p_vaddr); ++ } ++ } ++ ++ // Otherwise, check the first loadable segment. If its file offset ++ // is 0, it starts with the ELF header, and we can trivially find the ++ // loaded program header from it. ++ for (const ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) { ++ if (phdr->p_type == PT_LOAD) { ++ if (phdr->p_offset == 0) { ++ ElfW(Addr) elf_addr = load_bias_ + phdr->p_vaddr; ++ const ElfW(Ehdr)* ehdr = reinterpret_cast(elf_addr); ++ ElfW(Addr) offset = ehdr->e_phoff; ++ return CheckPhdr(reinterpret_cast(ehdr) + offset); ++ } ++ break; ++ } ++ } ++ ++ DL_ERR("can't find loaded phdr for \"%s\"", name_); ++ return false; ++} ++ ++// Ensures that our program header is actually within a loadable ++// segment. This should help catch badly-formed ELF files that ++// would cause the linker to crash later when trying to access it. ++bool ElfReader::CheckPhdr(ElfW(Addr) loaded) { ++ const ElfW(Phdr)* phdr_limit = phdr_table_ + phdr_num_; ++ ElfW(Addr) loaded_end = loaded + (phdr_num_ * sizeof(ElfW(Phdr))); ++ for (ElfW(Phdr)* phdr = phdr_table_; phdr < phdr_limit; ++phdr) { ++ if (phdr->p_type != PT_LOAD) { ++ continue; ++ } ++ ElfW(Addr) seg_start = phdr->p_vaddr + load_bias_; ++ ElfW(Addr) seg_end = phdr->p_filesz + seg_start; ++ if (seg_start <= loaded && loaded_end <= seg_end) { ++ loaded_phdr_ = reinterpret_cast(loaded); ++ return true; ++ } ++ } ++ DL_ERR("\"%s\" loaded phdr %p not in loadable segment", name_, reinterpret_cast(loaded)); ++ return false; ++} +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_phdr.h +@@ -0,0 +1,112 @@ ++/* ++ * Copyright (C) 2012 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++#ifndef LINKER_PHDR_H ++#define LINKER_PHDR_H ++ ++/* Declarations related to the ELF program header table and segments. ++ * ++ * The design goal is to provide an API that is as close as possible ++ * to the ELF spec, and does not depend on linker-specific data ++ * structures (e.g. the exact layout of struct soinfo). ++ */ ++ ++#include "linker.h" ++ ++class ElfReader { ++ public: ++ ElfReader(const char* name, int fd, off64_t file_offset, off64_t file_size); ++ ~ElfReader(); ++ ++ bool Load(const android_dlextinfo* extinfo); ++ ++ size_t phdr_count() { return phdr_num_; } ++ ElfW(Addr) load_start() { return reinterpret_cast(load_start_); } ++ size_t load_size() { return load_size_; } ++ ElfW(Addr) load_bias() { return load_bias_; } ++ const ElfW(Phdr)* loaded_phdr() { return loaded_phdr_; } ++ ++ private: ++ bool ReadElfHeader(); ++ bool VerifyElfHeader(); ++ bool ReadProgramHeader(); ++ bool ReserveAddressSpace(const android_dlextinfo* extinfo); ++ bool LoadSegments(); ++ bool FindPhdr(); ++ bool CheckPhdr(ElfW(Addr)); ++ ++ const char* name_; ++ int fd_; ++ off64_t file_offset_; ++ off64_t file_size_; ++ ++ ElfW(Ehdr) header_; ++ size_t phdr_num_; ++ ++ void* phdr_mmap_; ++ ElfW(Phdr)* phdr_table_; ++ ElfW(Addr) phdr_size_; ++ ++ // First page of reserved address space. ++ void* load_start_; ++ // Size in bytes of reserved address space. ++ size_t load_size_; ++ // Load bias. ++ ElfW(Addr) load_bias_; ++ ++ // Loaded phdr. ++ const ElfW(Phdr)* loaded_phdr_; ++}; ++ ++size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count, ++ ElfW(Addr)* min_vaddr = nullptr, ElfW(Addr)* max_vaddr = nullptr); ++ ++int phdr_table_protect_segments(const ElfW(Phdr)* phdr_table, ++ size_t phdr_count, ElfW(Addr) load_bias); ++ ++int phdr_table_unprotect_segments(const ElfW(Phdr)* phdr_table, size_t phdr_count, ++ ElfW(Addr) load_bias); ++ ++int phdr_table_protect_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, ++ ElfW(Addr) load_bias); ++ ++int phdr_table_serialize_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, ++ ElfW(Addr) load_bias, int fd); ++ ++int phdr_table_map_gnu_relro(const ElfW(Phdr)* phdr_table, size_t phdr_count, ++ ElfW(Addr) load_bias, int fd); ++ ++#if defined(__arm__) ++int phdr_table_get_arm_exidx(const ElfW(Phdr)* phdr_table, size_t phdr_count, ElfW(Addr) load_bias, ++ ElfW(Addr)** arm_exidx, size_t* arm_exidix_count); +#endif -+#define SC_THREAD_SAFE_FUNCTIONS 0x0055 -+#ifdef _SC_THREAD_SAFE_FUNCTIONS -+MAP_TO_UNISTD(SC_THREAD_SAFE_FUNCTIONS), ++ ++void phdr_table_get_dynamic_section(const ElfW(Phdr)* phdr_table, size_t phdr_count, ++ ElfW(Addr) load_bias, ElfW(Dyn)** dynamic, ++ ElfW(Word)* dynamic_flags); ++ ++#endif /* LINKER_PHDR_H */ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_reloc_iterators.h +@@ -0,0 +1,165 @@ ++/* ++ * Copyright (C) 2015 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 __LINKER_RELOC_ITERATORS_H ++#define __LINKER_RELOC_ITERATORS_H ++ ++#include "linker.h" ++ ++#include ++ ++const size_t RELOCATION_GROUPED_BY_INFO_FLAG = 1; ++const size_t RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG = 2; ++const size_t RELOCATION_GROUPED_BY_ADDEND_FLAG = 4; ++const size_t RELOCATION_GROUP_HAS_ADDEND_FLAG = 8; ++ ++class plain_reloc_iterator { ++#if defined(USE_RELA) ++ typedef ElfW(Rela) rel_t; ++#else ++ typedef ElfW(Rel) rel_t; +#endif ++ public: ++ plain_reloc_iterator(rel_t* rel_array, size_t count) ++ : begin_(rel_array), end_(begin_ + count), current_(begin_) {} ++ ++ bool has_next() { ++ return current_ < end_; ++ } ++ ++ rel_t* next() { ++ return current_++; ++ } ++ private: ++ rel_t* const begin_; ++ rel_t* const end_; ++ rel_t* current_; ++ ++ DISALLOW_COPY_AND_ASSIGN(plain_reloc_iterator); ++}; + -+#define SC_NPROCESSORS_CONF 0x0060 -+#ifdef _SC_NPROCESSORS_CONF -+MAP_TO_UNISTD(SC_NPROCESSORS_CONF), ++template ++class packed_reloc_iterator { ++#if defined(USE_RELA) ++ typedef ElfW(Rela) rel_t; ++#else ++ typedef ElfW(Rel) rel_t; +#endif -+#define SC_NPROCESSORS_ONLN 0x0061 -+#ifdef _SC_NPROCESSORS_ONLN -+MAP_TO_UNISTD(SC_NPROCESSORS_ONLN), ++ public: ++ explicit packed_reloc_iterator(decoder_t&& decoder) ++ : decoder_(decoder) { ++ // initialize fields ++ memset(&reloc_, 0, sizeof(reloc_)); ++ relocation_count_ = decoder_.pop_front(); ++ reloc_.r_offset = decoder_.pop_front(); ++ relocation_index_ = 0; ++ relocation_group_index_ = 0; ++ group_size_ = 0; ++ } ++ ++ bool has_next() const { ++ return relocation_index_ < relocation_count_; ++ } ++ ++ rel_t* next() { ++ if (relocation_group_index_ == group_size_) { ++ if (!read_group_fields()) { ++ // Iterator is inconsistent state; it should not be called again ++ // but in case it is let's make sure has_next() returns false. ++ relocation_index_ = relocation_count_ = 0; ++ return nullptr; ++ } ++ } ++ ++ if (is_relocation_grouped_by_offset_delta()) { ++ reloc_.r_offset += group_r_offset_delta_; ++ } else { ++ reloc_.r_offset += decoder_.pop_front(); ++ } ++ ++ if (!is_relocation_grouped_by_info()) { ++ reloc_.r_info = decoder_.pop_front(); ++ } ++ ++#if defined(USE_RELA) ++ if (is_relocation_group_has_addend() && ++ !is_relocation_grouped_by_addend()) { ++ reloc_.r_addend += decoder_.pop_front(); ++ } +#endif -+#define SC_PHYS_PAGES 0x0062 -+#ifdef _SC_PHYS_PAGES -+MAP_TO_UNISTD(SC_PHYS_PAGES), ++ ++ relocation_index_++; ++ relocation_group_index_++; ++ ++ return &reloc_; ++ } ++ private: ++ bool read_group_fields() { ++ group_size_ = decoder_.pop_front(); ++ group_flags_ = decoder_.pop_front(); ++ ++ if (is_relocation_grouped_by_offset_delta()) { ++ group_r_offset_delta_ = decoder_.pop_front(); ++ } ++ ++ if (is_relocation_grouped_by_info()) { ++ reloc_.r_info = decoder_.pop_front(); ++ } ++ ++ if (is_relocation_group_has_addend() && ++ is_relocation_grouped_by_addend()) { ++#if !defined(USE_RELA) ++ // This platform does not support rela, and yet we have it encoded in android_rel section. ++ DL_ERR("unexpected r_addend in android.rel section"); ++ return false; ++#else ++ reloc_.r_addend += decoder_.pop_front(); ++ } else if (!is_relocation_group_has_addend()) { ++ reloc_.r_addend = 0; +#endif -+#define SC_AVPHYS_PAGES 0x0063 -+#ifdef _SC_AVPHYS_PAGES -+MAP_TO_UNISTD(SC_AVPHYS_PAGES), ++ } ++ ++ relocation_group_index_ = 0; ++ return true; ++ } ++ ++ bool is_relocation_grouped_by_info() { ++ return (group_flags_ & RELOCATION_GROUPED_BY_INFO_FLAG) != 0; ++ } ++ ++ bool is_relocation_grouped_by_offset_delta() { ++ return (group_flags_ & RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG) != 0; ++ } ++ ++ bool is_relocation_grouped_by_addend() { ++ return (group_flags_ & RELOCATION_GROUPED_BY_ADDEND_FLAG) != 0; ++ } ++ ++ bool is_relocation_group_has_addend() { ++ return (group_flags_ & RELOCATION_GROUP_HAS_ADDEND_FLAG) != 0; ++ } ++ ++ decoder_t decoder_; ++ size_t relocation_count_; ++ size_t group_size_; ++ size_t group_flags_; ++ size_t group_r_offset_delta_; ++ size_t relocation_index_; ++ size_t relocation_group_index_; ++ rel_t reloc_; ++}; ++ ++#endif // __LINKER_RELOC_ITERATORS_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_relocs.h +@@ -0,0 +1,54 @@ ++/* ++ * Copyright (C) 2015 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 __LINKER_RELOCS_H ++#define __LINKER_RELOCS_H ++ ++#include ++ ++#define R_GENERIC_NONE 0 // R_*_NONE is always 0 ++ ++#if defined (__aarch64__) ++ ++#define R_GENERIC_JUMP_SLOT R_AARCH64_JUMP_SLOT ++#define R_GENERIC_GLOB_DAT R_AARCH64_GLOB_DAT ++#define R_GENERIC_RELATIVE R_AARCH64_RELATIVE ++#define R_GENERIC_IRELATIVE R_AARCH64_IRELATIVE ++ ++#elif defined (__arm__) ++ ++#define R_GENERIC_JUMP_SLOT R_ARM_JUMP_SLOT ++#define R_GENERIC_GLOB_DAT R_ARM_GLOB_DAT ++#define R_GENERIC_RELATIVE R_ARM_RELATIVE ++#define R_GENERIC_IRELATIVE R_ARM_IRELATIVE ++ ++#elif defined (__i386__) ++ ++#define R_GENERIC_JUMP_SLOT R_386_JMP_SLOT ++#define R_GENERIC_GLOB_DAT R_386_GLOB_DAT ++#define R_GENERIC_RELATIVE R_386_RELATIVE ++#define R_GENERIC_IRELATIVE R_386_IRELATIVE ++ ++#elif defined (__x86_64__) ++ ++#define R_GENERIC_JUMP_SLOT R_X86_64_JUMP_SLOT ++#define R_GENERIC_GLOB_DAT R_X86_64_GLOB_DAT ++#define R_GENERIC_RELATIVE R_X86_64_RELATIVE ++#define R_GENERIC_IRELATIVE R_X86_64_IRELATIVE ++ +#endif ++ ++#endif // __LINKER_RELOCS_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_sdk_versions.cpp +@@ -0,0 +1,34 @@ ++/* ++ * Copyright (C) 2015 The Android Open Source Project ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ */ ++ ++#include "linker.h" ++#include ++#include ++ ++static std::atomic g_target_sdk_version(__ANDROID_API__); ++ ++void set_application_target_sdk_version(uint32_t target) { ++ // translate current sdk_version to platform sdk_version ++ if (target == 0) { ++ target = __ANDROID_API__; ++ } ++ g_target_sdk_version = target; ++} ++ ++uint32_t get_application_target_sdk_version() { ++ return g_target_sdk_version; ++} ++ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/linker_sleb128.h +@@ -0,0 +1,58 @@ ++/* ++ * Copyright (C) 2015 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 _LINKER_SLEB128_H ++#define _LINKER_SLEB128_H ++ ++#include ++ ++// Helper classes for decoding LEB128, used in packed relocation data. ++// http://en.wikipedia.org/wiki/LEB128 ++ ++class sleb128_decoder { ++ public: ++ sleb128_decoder(const uint8_t* buffer, size_t count) ++ : current_(buffer), end_(buffer+count) { } ++ ++ size_t pop_front() { ++ size_t value = 0; ++ static const size_t size = CHAR_BIT * sizeof(value); ++ ++ size_t shift = 0; ++ uint8_t byte; ++ ++ do { ++ if (current_ >= end_) { ++ __libc_fatal("sleb128_decoder ran out of bounds"); ++ } ++ byte = *current_++; ++ value |= (static_cast(byte & 127) << shift); ++ shift += 7; ++ } while (byte & 128); ++ ++ if (shift < size && (byte & 64)) { ++ value |= -(static_cast(1) << shift); ++ } ++ ++ return value; ++ } ++ ++ private: ++ const uint8_t* current_; ++ const uint8_t* const end_; +}; -+#undef MAP_TO_UNISTD + -+long my_sysconf(int name) ++#endif // __LINKER_SLEB128_H +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/mm/rt.cpp +@@ -0,0 +1,35 @@ ++/* ++ * Copyright (C) 2008 The Android Open Source Project ++ * All rights reserved. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * * Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * * Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in ++ * the documentation and/or other materials provided with the ++ * distribution. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ++ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ++ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ++ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, ++ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS ++ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED ++ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ++ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ++ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ */ ++ ++/* ++ * This function is an empty stub where GDB locates a breakpoint to get notified ++ * about linker activity. It canʼt be inlined away, can't be hidden. ++ */ ++extern "C" void __attribute__((noinline)) __attribute__((visibility("default"))) rtld_db_dlactivity() { ++} ++ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/strlcat.c +@@ -0,0 +1,59 @@ ++/* $OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $ */ ++ ++/* ++ * Copyright (c) 1998 Todd C. Miller ++ * ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#if defined(LIBC_SCCS) && !defined(lint) ++static char *rcsid = "$OpenBSD: strlcat.c,v 1.11 2003/06/17 21:56:24 millert Exp $"; ++#endif /* LIBC_SCCS and not lint */ ++ ++#include ++#include ++ ++/* ++ * Appends src to string dst of size siz (unlike strncat, siz is the ++ * full size of dst, not space left). At most siz-1 characters ++ * will be copied. Always NUL terminates (unless siz <= strlen(dst)). ++ * Returns strlen(src) + MIN(siz, strlen(initial dst)). ++ * If retval >= siz, truncation occurred. ++ */ ++size_t ++strlcat(char *dst, const char *src, size_t siz) ++{ ++ register char *d = dst; ++ register const char *s = src; ++ register size_t n = siz; ++ size_t dlen; ++ ++ /* Find the end of dst and adjust bytes left but don't go past end */ ++ while (n-- != 0 && *d != '\0') ++ d++; ++ dlen = d - dst; ++ n = siz - dlen; ++ ++ if (n == 0) ++ return(dlen + strlen(s)); ++ while (*s != '\0') { ++ if (n != 1) { ++ *d++ = *s; ++ n--; ++ } ++ s++; ++ } ++ *d = '\0'; ++ ++ return(dlen + (s - src)); /* count does not include NUL */ ++} +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/stub/Makefile.am +@@ -0,0 +1,4 @@ ++noinst_LTLIBRARIES = \ ++ libstub-linker.la ++libstub_linker_la_SOURCES = \ ++ linker.c +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/stub/linker.c +@@ -0,0 +1,49 @@ ++/* ++ * Copyright (c) 2016 Canonical Ltd ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ * ++ */ ++ ++#include ++#include ++ ++void *android_dlopen(const char *filename, int flag) ++{ ++ fprintf(stderr, "%s called but not implemented!\n", __func__); ++ return NULL; ++} ++ ++void *android_dlsym(void *name, const char *symbol) ++{ ++ fprintf(stderr, "%s called but not implemented!\n", __func__); ++ return NULL; ++} ++ ++int android_dlclose(void *handle) ++{ ++ fprintf(stderr, "%s called but not implemented!\n", __func__); ++ return -1; ++} ++ ++const char *android_dlerror(void) ++{ ++ fprintf(stderr, "%s called but not implemented!\n", __func__); ++ return NULL; ++} ++ ++int android_dladdr(const void *addr, void *info) +{ -+ return sysconf(sysconf_map[name]); ++ fprintf(stderr, "%s called but not implemented!\n", __func__); ++ return -1; +} ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/configure.ac -+++ libhybris-0.1.0+git20131207+e452e83/hybris/configure.ac -@@ -184,6 +184,10 @@ AC_CONFIG_FILES([ - input/libis.pc - camera/Makefile +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/common/sysconf.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/sysconf.c +@@ -1,8 +1,27 @@ ++/* ++ * Copyright (c) 2013 Adrian Negreanu ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ * ++ */ ++ + #include + + /* +- * bionic/libc/include/sys/sysconf.h processed with s/define _\(\w*\)\(.*\)/define \1\2\r#ifdef _\1\rMAP_TO_UNISTD(\1),\r#endif/g ++ * bionic/libc/include/sys/sysconf.h processed with: ++ * s/define _\(\w*\)\(.*\)/define \1\2\r#ifdef _\1\rMAP_TO_UNISTD(\1),\r#endif/g + */ ++ + #define MAP_TO_UNISTD(a) [a]=_##a + static int sysconf_map[]= { + #define SC_ARG_MAX 0x0000 +@@ -321,7 +340,6 @@ MAP_TO_UNISTD(SC_THREAD_THREADS_MAX), + #ifdef _SC_TTY_NAME_MAX + MAP_TO_UNISTD(SC_TTY_NAME_MAX), + #endif +- + #define SC_THREADS 0x004f + #ifdef _SC_THREADS + MAP_TO_UNISTD(SC_THREADS), +@@ -350,7 +368,6 @@ MAP_TO_UNISTD(SC_THREAD_PRIO_PROTECT), + #ifdef _SC_THREAD_SAFE_FUNCTIONS + MAP_TO_UNISTD(SC_THREAD_SAFE_FUNCTIONS), + #endif +- + #define SC_NPROCESSORS_CONF 0x0060 + #ifdef _SC_NPROCESSORS_CONF + MAP_TO_UNISTD(SC_NPROCESSORS_CONF), +@@ -367,10 +384,242 @@ MAP_TO_UNISTD(SC_PHYS_PAGES), + #ifdef _SC_AVPHYS_PAGES + MAP_TO_UNISTD(SC_AVPHYS_PAGES), + #endif ++#define SC_MONOTONIC_CLOCK 0x0064 ++#ifdef _SC_MONOTONIC_CLOCK ++MAP_TO_UNISTD(SC_MONOTONIC_CLOCK), ++#endif ++#define SC_2_PBS 0x0065 ++#ifdef _SC_2_PBS ++MAP_TO_UNISTD(SC_2_PBS), ++#endif ++#define SC_2_PBS_ACCOUNTING 0x0066 ++#ifdef _SC_2_PBS_ACCOUNTING ++MAP_TO_UNISTD(SC_2_PBS_ACCOUNTING), ++#endif ++#define SC_2_PBS_CHECKPOINT 0x0067 ++#ifdef _SC_2_PBS_CHECKPOINT ++MAP_TO_UNISTD(SC_2_PBS_CHECKPOINT), ++#endif ++#define SC_2_PBS_LOCATE 0x0068 ++#ifdef _SC_2_PBS_LOCATE ++MAP_TO_UNISTD(SC_2_PBS_LOCATE), ++#endif ++#define SC_2_PBS_MESSAGE 0x0069 ++#ifdef _SC_2_PBS_MESSAGE ++MAP_TO_UNISTD(SC_2_PBS_MESSAGE), ++#endif ++#define SC_2_PBS_TRACK 0x006a ++#ifdef _SC_2_PBS_TRACK ++MAP_TO_UNISTD(SC_2_PBS_TRACK), ++#endif ++#define SC_ADVISORY_INFO 0x006b ++#ifdef _SC_ADVISORY_INFO ++MAP_TO_UNISTD(SC_ADVISORY_INFO), ++#endif ++#define SC_BARRIERS 0x006c ++#ifdef _SC_BARRIERS ++MAP_TO_UNISTD(SC_BARRIERS), ++#endif ++#define SC_CLOCK_SELECTION 0x006d ++#ifdef _SC_CLOCK_SELECTION ++MAP_TO_UNISTD(SC_CLOCK_SELECTION), ++#endif ++#define SC_CPUTIME 0x006e ++#ifdef _SC_CPUTIME ++MAP_TO_UNISTD(SC_CPUTIME), ++#endif ++#define SC_HOST_NAME_MAX 0x006f ++#ifdef _SC_HOST_NAME_MAX ++MAP_TO_UNISTD(SC_HOST_NAME_MAX), ++#endif ++#define SC_IPV6 0x0070 ++#ifdef _SC_IPV6 ++MAP_TO_UNISTD(SC_IPV6), ++#endif ++#define SC_RAW_SOCKETS 0x0071 ++#ifdef _SC_RAW_SOCKETS ++MAP_TO_UNISTD(SC_RAW_SOCKETS), ++#endif ++#define SC_READER_WRITER_LOCKS 0x0072 ++#ifdef _SC_READER_WRITER_LOCKS ++MAP_TO_UNISTD(SC_READER_WRITER_LOCKS), ++#endif ++#define SC_REGEXP 0x0073 ++#ifdef _SC_REGEXP ++MAP_TO_UNISTD(SC_REGEXP), ++#endif ++#define SC_SHELL 0x0074 ++#ifdef _SC_SHELL ++MAP_TO_UNISTD(SC_SHELL), ++#endif ++#define SC_SPAWN 0x0075 ++#ifdef _SC_SPAWN ++MAP_TO_UNISTD(SC_SPAWN), ++#endif ++#define SC_SPIN_LOCKS 0x0076 ++#ifdef _SC_SPIN_LOCKS ++MAP_TO_UNISTD(SC_SPIN_LOCKS), ++#endif ++#define SC_SPORADIC_SERVER 0x0077 ++#ifdef _SC_SPORADIC_SERVER ++MAP_TO_UNISTD(SC_SPORADIC_SERVER), ++#endif ++#define SC_SS_REPL_MAX 0x0078 ++#ifdef _SC_SS_REPL_MAX ++MAP_TO_UNISTD(SC_SS_REPL_MAX), ++#endif ++#define SC_SYMLOOP_MAX 0x0079 ++#ifdef _SC_SYMLOOP_MAX ++MAP_TO_UNISTD(SC_SYMLOOP_MAX), ++#endif ++#define SC_THREAD_CPUTIME 0x007a ++#ifdef _SC_THREAD_CPUTIME ++MAP_TO_UNISTD(SC_THREAD_CPUTIME), ++#endif ++#define SC_THREAD_PROCESS_SHARED 0x007b ++#ifdef _SC_THREAD_PROCESS_SHARED ++MAP_TO_UNISTD(SC_THREAD_PROCESS_SHARED), ++#endif ++#define SC_THREAD_ROBUST_PRIO_INHERIT 0x007c ++#ifdef _SC_THREAD_ROBUST_PRIO_INHERIT ++MAP_TO_UNISTD(SC_THREAD_ROBUST_PRIO_INHERIT), ++#endif ++#define SC_THREAD_ROBUST_PRIO_PROTECT 0x007d ++#ifdef _SC_THREAD_ROBUST_PRIO_PROTECT ++MAP_TO_UNISTD(SC_THREAD_ROBUST_PRIO_PROTECT), ++#endif ++#define SC_THREAD_SPORADIC_SERVER 0x007e ++#ifdef _SC_THREAD_SPORADIC_SERVER ++MAP_TO_UNISTD(SC_THREAD_SPORADIC_SERVER), ++#endif ++#define SC_TIMEOUTS 0x007f ++#ifdef _SC_TIMEOUTS ++MAP_TO_UNISTD(SC_TIMEOUTS), ++#endif ++#define SC_TRACE 0x0080 ++#ifdef _SC_TRACE ++MAP_TO_UNISTD(SC_TRACE), ++#endif ++#define SC_TRACE_EVENT_FILTER 0x0081 ++#ifdef _SC_TRACE_EVENT_FILTER ++MAP_TO_UNISTD(SC_TRACE_EVENT_FILTER), ++#endif ++#define SC_TRACE_EVENT_NAME_MAX 0x0082 ++#ifdef _SC_TRACE_EVENT_NAME_MAX ++MAP_TO_UNISTD(SC_TRACE_EVENT_NAME_MAX), ++#endif ++#define SC_TRACE_INHERIT 0x0083 ++#ifdef _SC_TRACE_INHERIT ++MAP_TO_UNISTD(SC_TRACE_INHERIT), ++#endif ++#define SC_TRACE_LOG 0x0084 ++#ifdef _SC_TRACE_LOG ++MAP_TO_UNISTD(SC_TRACE_LOG), ++#endif ++#define SC_TRACE_NAME_MAX 0x0085 ++#ifdef _SC_TRACE_NAME_MAX ++MAP_TO_UNISTD(SC_TRACE_NAME_MAX), ++#endif ++#define SC_TRACE_SYS_MAX 0x0086 ++#ifdef _SC_TRACE_SYS_MAX ++MAP_TO_UNISTD(SC_TRACE_SYS_MAX), ++#endif ++#define SC_TRACE_USER_EVENT_MAX 0x0087 ++#ifdef _SC_TRACE_USER_EVENT_MAX ++MAP_TO_UNISTD(SC_TRACE_USER_EVENT_MAX), ++#endif ++#define SC_TYPED_MEMORY_OBJECTS 0x0088 ++#ifdef _SC_TYPED_MEMORY_OBJECTS ++MAP_TO_UNISTD(SC_TYPED_MEMORY_OBJECTS), ++#endif ++#define SC_V7_ILP32_OFF32 0x0089 ++#ifdef _SC_V7_ILP32_OFF32 ++MAP_TO_UNISTD(SC_V7_ILP32_OFF32), ++#endif ++#define SC_V7_ILP32_OFFBIG 0x008a ++#ifdef _SC_V7_ILP32_OFFBIG ++MAP_TO_UNISTD(SC_V7_ILP32_OFFBIG), ++#endif ++#define SC_V7_LP64_OFF64 0x008b ++#ifdef _SC_V7_LP64_OFF64 ++MAP_TO_UNISTD(SC_V7_LP64_OFF64), ++#endif ++#define SC_V7_LPBIG_OFFBIG 0x008c ++#ifdef _SC_V7_LPBIG_OFFBIG ++MAP_TO_UNISTD(SC_V7_LPBIG_OFFBIG), ++#endif ++#define SC_XOPEN_STREAMS 0x008d ++#ifdef _SC_XOPEN_STREAMS ++MAP_TO_UNISTD(SC_XOPEN_STREAMS), ++#endif ++#define SC_XOPEN_UUCP 0x008e ++#ifdef _SC_XOPEN_UUCP ++MAP_TO_UNISTD(SC_XOPEN_UUCP), ++#endif ++#define SC_LEVEL1_ICACHE_SIZE 0x008f ++#ifdef _SC_LEVEL1_ICACHE_SIZE ++MAP_TO_UNISTD(SC_LEVEL1_ICACHE_SIZE), ++#endif ++#define SC_LEVEL1_ICACHE_ASSOC 0x0090 ++#ifdef _SC_LEVEL1_ICACHE_ASSOC ++MAP_TO_UNISTD(SC_LEVEL1_ICACHE_ASSOC), ++#endif ++#define SC_LEVEL1_ICACHE_LINESIZE 0x0091 ++#ifdef _SC_LEVEL1_ICACHE_LINESIZE ++MAP_TO_UNISTD(SC_LEVEL1_ICACHE_LINESIZE), ++#endif ++#define SC_LEVEL1_DCACHE_SIZE 0x0092 ++#ifdef _SC_LEVEL1_DCACHE_SIZE ++MAP_TO_UNISTD(SC_LEVEL1_DCACHE_SIZE), ++#endif ++#define SC_LEVEL1_DCACHE_ASSOC 0x0093 ++#ifdef _SC_LEVEL1_DCACHE_ASSOC ++MAP_TO_UNISTD(SC_LEVEL1_DCACHE_ASSOC), ++#endif ++#define SC_LEVEL1_DCACHE_LINESIZE 0x0094 ++#ifdef _SC_LEVEL1_DCACHE_LINESIZE ++MAP_TO_UNISTD(SC_LEVEL1_DCACHE_LINESIZE), ++#endif ++#define SC_LEVEL2_CACHE_SIZE 0x0095 ++#ifdef _SC_LEVEL2_CACHE_SIZE ++MAP_TO_UNISTD(SC_LEVEL2_CACHE_SIZE), ++#endif ++#define SC_LEVEL2_CACHE_ASSOC 0x0096 ++#ifdef _SC_LEVEL2_CACHE_ASSOC ++MAP_TO_UNISTD(SC_LEVEL2_CACHE_ASSOC), ++#endif ++#define SC_LEVEL2_CACHE_LINESIZE 0x0097 ++#ifdef _SC_LEVEL2_CACHE_LINESIZE ++MAP_TO_UNISTD(SC_LEVEL2_CACHE_LINESIZE), ++#endif ++#define SC_LEVEL3_CACHE_SIZE 0x0098 ++#ifdef _SC_LEVEL3_CACHE_SIZE ++MAP_TO_UNISTD(SC_LEVEL3_CACHE_SIZE), ++#endif ++#define SC_LEVEL3_CACHE_ASSOC 0x0099 ++#ifdef _SC_LEVEL3_CACHE_ASSOC ++MAP_TO_UNISTD(SC_LEVEL3_CACHE_ASSOC), ++#endif ++#define SC_LEVEL3_CACHE_LINESIZE 0x009a ++#ifdef _SC_LEVEL3_CACHE_LINESIZE ++MAP_TO_UNISTD(SC_LEVEL3_CACHE_LINESIZE), ++#endif ++#define SC_LEVEL4_CACHE_SIZE 0x009b ++#ifdef _SC_LEVEL4_CACHE_SIZE ++MAP_TO_UNISTD(SC_LEVEL4_CACHE_SIZE), ++#endif ++#define SC_LEVEL4_CACHE_ASSOC 0x009c ++#ifdef _SC_LEVEL4_CACHE_ASSOC ++MAP_TO_UNISTD(SC_LEVEL4_CACHE_ASSOC), ++#endif ++#define SC_LEVEL4_CACHE_LINESIZE 0x009d ++#ifdef _SC_LEVEL4_CACHE_LINESIZE ++MAP_TO_UNISTD(SC_LEVEL4_CACHE_LINESIZE), ++#endif + }; + #undef MAP_TO_UNISTD + +-long my_sysconf(int name) ++long _hybris_map_sysconf(int name) + { + return sysconf(sysconf_map[name]); + } +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/configure.ac ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/configure.ac +@@ -42,6 +42,12 @@ AC_ARG_ENABLE(debug, + [debug="no"]) + AM_CONDITIONAL( [WANT_DEBUG], [test x"$debug" = x"yes"]) + ++AC_ARG_ENABLE(experimental, ++ [ --enable-experimental Enable experimental features (default=disabled)], ++ [experimental=$enableval], ++ [experimental="no"]) ++AM_CONDITIONAL( [WANT_EXPERIMENTAL], [test x"$experimental" = x"yes"]) ++ + AC_ARG_ENABLE(trace, + [ --enable-trace Enable TRACE statements (default=disabled)], + [trace=$enableval], +@@ -73,14 +79,30 @@ AC_ARG_ENABLE(wayland_serverside_buffers + [wayland_serverside_buffers=yes]) + AM_CONDITIONAL( [WANT_WL_SERVERSIDE_BUFFERS], [test x"$wayland_serverside_buffers" = x"yes"]) + ++AC_ARG_ENABLE(property_cache, ++ [ --enable-property-cache Enable runtime android property cache (default=disabled)], ++ [property_cache=$enableval], ++ [property_cache=no]) ++AM_CONDITIONAL( [WANT_RUNTIME_PROPERTY_CACHE], [test x"$property_cache" = x"yes"]) ++ ++AC_ARG_ENABLE(ubuntu-linker-overrides, ++ [ --enable-ubuntu-linker-overrides Enable Ubuntu linker overrides (default=disabled)], ++ [ubuntu_linker_overrides=$enableval], ++ [ubuntu_linker_overrides=no]) ++AM_CONDITIONAL([WANT_UBUNTU_LINKER_OVERRIDES], [test x"$ubuntu_linker_overrides" = x"yes"]) ++ + AC_ARG_ENABLE(arch, + [ --enable-arch[=arch] Compile specific CPU target(default=arm) + arm: compile for ARM + x86: Compile for x86], + [ if test "x$enableval" = "xarm" ; then + arch="arm" ++ elif test "x$enableval" = "xarm64" ; then ++ arch="arm64" + elif test "x$enableval" = "xx86" ; then + arch="x86" ++ elif test "x$enableval" = "xx86-64" ; then ++ arch="x86-64" + else + echo + echo "Error!" +@@ -91,7 +113,9 @@ AC_ARG_ENABLE(arch, + [arch="arm"] + ) + AM_CONDITIONAL([WANT_ARCH_ARM], [test x$arch = xarm]) ++AM_CONDITIONAL([WANT_ARCH_ARM64], [test x$arch = xarm64]) + AM_CONDITIONAL([WANT_ARCH_X86], [test x$arch = xx86]) ++AM_CONDITIONAL([WANT_ARCH_X86_64], [test x$arch = xx86-64]) + + DEFAULT_EGL_PLATFORM="null" + AC_ARG_WITH(default-egl-platform, +@@ -100,7 +124,11 @@ AC_ARG_WITH(default-egl-platform, + [ ]) + AC_SUBST(DEFAULT_EGL_PLATFORM) + +-DEFAULT_HYBRIS_LD_LIBRARY_PATH="/vendor/lib:/system/lib" ++if test "x$arch" = "xarm" -o "x$arch" = "xx86"; then ++ DEFAULT_HYBRIS_LD_LIBRARY_PATH="/vendor/lib:/system/lib" ++else ++ DEFAULT_HYBRIS_LD_LIBRARY_PATH="/vendor/lib64:/system/lib64" ++fi + AC_ARG_WITH(default-hybris-ld-library-path, + [ --with-default-hybris-ld-library-path=PATH1:PATH2:... Use PATH1:PATH2 for default HYBRIS_LD_LIBRARY_PATH if not specified by environment ], + [ DEFAULT_HYBRIS_LD_LIBRARY_PATH="$withval" ], +@@ -114,7 +142,10 @@ AC_ARG_WITH(android-headers, + AS_IF([test -f $withval/libnfc-nxp/phLibNfc.h], [ANDROID_HEADERS_CFLAGS="-I$withval -I$withval/libnfc-nxp"],[ANDROID_HEADERS_CFLAGS="-I$withval"]) + AC_SUBST([ANDROID_HEADERS_CFLAGS]) + ], +- [ PKG_CHECK_MODULES(ANDROID_HEADERS, android-headers,, exit) ] ++ [ ++ PKG_CHECK_MODULES(ANDROID_HEADERS, android-headers,, exit) ++ AM_CONDITIONAL([HAS_LIBNFC_NXP_HEADERS], [false]) ++ ] + ) + CPPFLAGS="$CPPFLAGS $ANDROID_HEADERS_CFLAGS" + +@@ -177,15 +208,26 @@ AM_CONDITIONAL([HAS_ANDROID_4_1_0], [tes + AM_CONDITIONAL([HAS_ANDROID_4_0_0], [test $android_headers_major -ge 4 -a $android_headers_minor -ge 0 ]) + AM_CONDITIONAL([HAS_ANDROID_2_3_0], [test $android_headers_major -ge 2 -a $android_headers_minor -ge 3 ]) + ++AC_ARG_ENABLE(mali-quirks, ++ [ --enable-mali-quirks Enable Mali GPU driver quirks (default=disabled)], ++ [mali_quirks=$enableval], ++ [mali_quirks="no"]) ++AM_CONDITIONAL([WANT_MALI_QUIRKS], [test x"$mali_quirks" = x"yes"]) ++ ++AC_ARG_ENABLE(stub-linker, ++ [ --enable-stub-linker Enable a stub linker which does nothing (default=disabled)], ++ [stub_linker=$enableval], ++ [stub_linker="no"]) ++AM_CONDITIONAL([WANT_STUB_LINKER], [test x"$stub_linker" = x"yes"]) + + AC_CONFIG_FILES([ + Makefile + properties/Makefile + properties/libandroid-properties.pc + common/Makefile +- common/gingerbread/Makefile +- common/ics/Makefile + common/jb/Makefile ++ common/stub/Makefile ++ common/mm/Makefile + egl/egl.pc + egl/Makefile + egl/platforms/Makefile +@@ -217,6 +259,10 @@ AC_CONFIG_FILES([ camera/libcamera.pc + vibrator/Makefile + vibrator/libvibrator.pc + media/Makefile + media/libmedia.pc + wifi/Makefile @@ -10275,1242 +23964,1290 @@ include/Makefile utils/Makefile tests/Makefile ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/egl/egl.c -+++ libhybris-0.1.0+git20131207+e452e83/hybris/egl/egl.c -@@ -17,6 +17,8 @@ - - /* EGL function pointers */ - #define EGL_EGLEXT_PROTOTYPES -+/* For RTLD_DEFAULT */ -+#define _GNU_SOURCE - #include - #include - #include -@@ -449,9 +451,16 @@ __eglMustCastToProperFunctionPointerType - return _my_glEGLImageTargetTexture2DOES; - } - __eglMustCastToProperFunctionPointerType ret = ws_eglGetProcAddress(procname); -- if (ret == NULL) -- return (*_eglGetProcAddress)(procname); -- else return ret; -+ -+ if (ret == NULL) { -+#ifdef RTLD_DEFAULT -+ ret = dlsym(RTLD_DEFAULT, procname); -+ if (ret == NULL) -+#endif -+ ret = (*_eglGetProcAddress)(procname); -+ } -+ -+ return ret; +@@ -236,16 +282,26 @@ echo " debug build.............: $debug + echo + echo " trace...................: $trace" + echo ++echo " experimental features...: $experimental" ++echo + echo " prefix..................: $prefix" + echo + echo " arch ..................: $arch" + echo + echo " headers path ...........: $android_headers_path" + echo ++echo " Android version.........: $android_headers_major.$android_headers_minor.$android_headers_patch" ++echo + echo " default egl platform ...: $DEFAULT_EGL_PLATFORM" + echo + echo " default ld_library_path.: $DEFAULT_HYBRIS_LD_LIBRARY_PATH" + echo ++echo "Features:" ++echo ++echo " stub linker.............: $stub_linker" ++echo ++echo " Ubuntu linker overrides.: $ubuntu_linker_overrides" ++echo + echo "------------------------------------------------------------------------" + echo + echo "Now type 'make' to compile and 'make install' to install this package." +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/egl/egl.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/egl.c +@@ -266,8 +266,11 @@ EGLSurface eglCreateWindowSurface(EGLDis + + HYBRIS_TRACE_BEGIN("native-egl", "eglCreateWindowSurface", ""); + EGLSurface result = (*_eglCreateWindowSurface)(dpy, config, win, attrib_list); ++ + HYBRIS_TRACE_END("native-egl", "eglCreateWindowSurface", ""); +- egl_helper_push_mapping(result, win); ++ ++ if (result != EGL_NO_SURFACE) ++ egl_helper_push_mapping(result, win); + + HYBRIS_TRACE_END("hybris-egl", "eglCreateWindowSurface", ""); + return result; +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/egl/platforms/null/eglplatform_null.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/null/eglplatform_null.c +@@ -16,7 +16,7 @@ static alloc_device_t *alloc = 0; + + static void _init_androidui() + { +- _libui = (void *) android_dlopen("/system/lib/libui.so", RTLD_LAZY); ++ _libui = (void *) android_dlopen("libui.so", RTLD_LAZY); } - EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image) ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/glesv2/glesv2.c -+++ libhybris-0.1.0+git20131207+e452e83/hybris/glesv2/glesv2.c -@@ -27,1016 +27,393 @@ + #define UI_DLSYM(fptr, sym) do { if (_libui == NULL) { _init_androidui(); }; if (*(fptr) == NULL) { *(fptr) = (void *) android_dlsym(_libui, sym); } } while (0) +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/glesv1/glesv1_cm.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/glesv1/glesv1_cm.c +@@ -26,7 +26,7 @@ + + #include + +-#define GLESV1_CM_LIBRARY_PATH "/system/lib/libGLESv1_CM.so" ++#define GLESV1_CM_LIBRARY_PATH "libGLESv1_CM.so" + + HYBRIS_LIBRARY_INITIALIZE(glesv1_cm, GLESV1_CM_LIBRARY_PATH); + +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/glesv2/glesv2.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/glesv2/glesv2.c +@@ -22,404 +22,1028 @@ + #include + #include + +-#include + #include +-#include static void *_libglesv2 = NULL; --static void (*_glActiveTexture)(GLenum texture) = NULL; --static void (*_glAttachShader)(GLuint program, GLuint shader) = NULL; --static void (*_glBindAttribLocation)(GLuint program, GLuint index, const GLchar* name) = NULL; --static void (*_glBindBuffer)(GLenum target, GLuint buffer) = NULL; --static void (*_glBindFramebuffer)(GLenum target, GLuint framebuffer) = NULL; --static void (*_glBindRenderbuffer)(GLenum target, GLuint renderbuffer) = NULL; --static void (*_glBindTexture)(GLenum target, GLuint texture) = NULL; -+/* Only functions with floating point argument need a wrapper to change the call convention correctly */ -+ +-/* Only functions with floating point argument need a wrapper to change the call convention correctly */ +- ++static void (*_glActiveTexture)(GLenum texture) = NULL; ++static void (*_glAttachShader)(GLuint program, GLuint shader) = NULL; ++static void (*_glBindAttribLocation)(GLuint program, GLuint index, const GLchar* name) = NULL; ++static void (*_glBindBuffer)(GLenum target, GLuint buffer) = NULL; ++static void (*_glBindFramebuffer)(GLenum target, GLuint framebuffer) = NULL; ++static void (*_glBindRenderbuffer)(GLenum target, GLuint renderbuffer) = NULL; ++static void (*_glBindTexture)(GLenum target, GLuint texture) = NULL; static void (*_glBlendColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) FP_ATTRIB = NULL; --static void (*_glBlendEquation)(GLenum mode ) = NULL; --static void (*_glBlendEquationSeparate)(GLenum modeRGB, GLenum modeAlpha) = NULL; --static void (*_glBlendFunc)(GLenum sfactor, GLenum dfactor) = NULL; --static void (*_glBlendFuncSeparate)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) = NULL; --static void (*_glBufferData)(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) = NULL; --static void (*_glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) = NULL; --static GLenum (*_glCheckFramebufferStatus)(GLenum target) = NULL; --static void (*_glClear)(GLbitfield mask) = NULL; ++static void (*_glBlendEquation)(GLenum mode ) = NULL; ++static void (*_glBlendEquationSeparate)(GLenum modeRGB, GLenum modeAlpha) = NULL; ++static void (*_glBlendFunc)(GLenum sfactor, GLenum dfactor) = NULL; ++static void (*_glBlendFuncSeparate)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) = NULL; ++static void (*_glBufferData)(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) = NULL; ++static void (*_glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) = NULL; ++static GLenum (*_glCheckFramebufferStatus)(GLenum target) = NULL; ++static void (*_glClear)(GLbitfield mask) = NULL; static void (*_glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) FP_ATTRIB = NULL; static void (*_glClearDepthf)(GLclampf depth) FP_ATTRIB = NULL; --static void (*_glClearStencil)(GLint s) = NULL; --static void (*_glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) = NULL; --static void (*_glCompileShader)(GLuint shader) = NULL; --static void (*_glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) = NULL; --static void (*_glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) = NULL; --static void (*_glCopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) = NULL; --static void (*_glCopyTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) = NULL; --static GLuint (*_glCreateProgram)(void) = NULL; --static GLuint (*_glCreateShader)(GLenum type) = NULL; --static void (*_glCullFace)(GLenum mode) = NULL; --static void (*_glDeleteBuffers)(GLsizei n, const GLuint* buffers) = NULL; --static void (*_glDeleteFramebuffers)(GLsizei n, const GLuint* framebuffers) = NULL; --static void (*_glDeleteProgram)(GLuint program) = NULL; --static void (*_glDeleteRenderbuffers)(GLsizei n, const GLuint* renderbuffers) = NULL; --static void (*_glDeleteShader)(GLuint shader) = NULL; --static void (*_glDeleteTextures)(GLsizei n, const GLuint* textures) = NULL; --static void (*_glDepthFunc)(GLenum func) = NULL; --static void (*_glDepthMask)(GLboolean flag) = NULL; ++static void (*_glClearStencil)(GLint s) = NULL; ++static void (*_glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) = NULL; ++static void (*_glCompileShader)(GLuint shader) = NULL; ++static void (*_glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) = NULL; ++static void (*_glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) = NULL; ++static void (*_glCopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) = NULL; ++static void (*_glCopyTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) = NULL; ++static GLuint (*_glCreateProgram)(void) = NULL; ++static GLuint (*_glCreateShader)(GLenum type) = NULL; ++static void (*_glCullFace)(GLenum mode) = NULL; ++static void (*_glDeleteBuffers)(GLsizei n, const GLuint* buffers) = NULL; ++static void (*_glDeleteFramebuffers)(GLsizei n, const GLuint* framebuffers) = NULL; ++static void (*_glDeleteProgram)(GLuint program) = NULL; ++static void (*_glDeleteRenderbuffers)(GLsizei n, const GLuint* renderbuffers) = NULL; ++static void (*_glDeleteShader)(GLuint shader) = NULL; ++static void (*_glDeleteTextures)(GLsizei n, const GLuint* textures) = NULL; ++static void (*_glDepthFunc)(GLenum func) = NULL; ++static void (*_glDepthMask)(GLboolean flag) = NULL; static void (*_glDepthRangef)(GLclampf zNear, GLclampf zFar) FP_ATTRIB = NULL; --static void (*_glDetachShader)(GLuint program, GLuint shader) = NULL; --static void (*_glDisable)(GLenum cap) = NULL; --static void (*_glDisableVertexAttribArray)(GLuint index) = NULL; --static void (*_glDrawArrays)(GLenum mode, GLint first, GLsizei count) = NULL; --static void (*_glDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) = NULL; --static void (*_glEnable)(GLenum cap) = NULL; --static void (*_glEnableVertexAttribArray)(GLuint index) = NULL; --static void (*_glFinish)(void) = NULL; --static void (*_glFlush)(void) = NULL; --static void (*_glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) = NULL; --static void (*_glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) = NULL; --static void (*_glFrontFace)(GLenum mode) = NULL; --static void (*_glGenBuffers)(GLsizei n, GLuint* buffers) = NULL; --static void (*_glGenerateMipmap)(GLenum target) = NULL; --static void (*_glGenFramebuffers)(GLsizei n, GLuint* framebuffers) = NULL; --static void (*_glGenRenderbuffers)(GLsizei n, GLuint* renderbuffers) = NULL; --static void (*_glGenTextures)(GLsizei n, GLuint* textures) = NULL; --static void (*_glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) = NULL; --static void (*_glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) = NULL; --static void (*_glGetAttachedShaders)(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) = NULL; --static int (*_glGetAttribLocation)(GLuint program, const GLchar* name) = NULL; --static void (*_glGetBooleanv)(GLenum pname, GLboolean* params) = NULL; --static void (*_glGetBufferParameteriv)(GLenum target, GLenum pname, GLint* params) = NULL; --static GLenum (*_glGetError)(void) = NULL; --static void (*_glGetFloatv)(GLenum pname, GLfloat* params) = NULL; --static void (*_glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint* params) = NULL; --static void (*_glGetIntegerv)(GLenum pname, GLint* params) = NULL; --static void (*_glGetProgramiv)(GLuint program, GLenum pname, GLint* params) = NULL; --static void (*_glGetProgramInfoLog)(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog) = NULL; --static void (*_glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint* params) = NULL; --static void (*_glGetShaderiv)(GLuint shader, GLenum pname, GLint* params) = NULL; --static void (*_glGetShaderInfoLog)(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog) = NULL; --static void (*_glGetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) = NULL; --static void (*_glGetShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) = NULL; --static const GLubyte* (*_glGetString)(GLenum name) = NULL; --static void (*_glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat* params) = NULL; --static void (*_glGetTexParameteriv)(GLenum target, GLenum pname, GLint* params) = NULL; --static void (*_glGetUniformfv)(GLuint program, GLint location, GLfloat* params) = NULL; --static void (*_glGetUniformiv)(GLuint program, GLint location, GLint* params) = NULL; --static int (*_glGetUniformLocation)(GLuint program, const GLchar* name) = NULL; --static void (*_glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat* params) = NULL; --static void (*_glGetVertexAttribiv)(GLuint index, GLenum pname, GLint* params) = NULL; --static void (*_glGetVertexAttribPointerv)(GLuint index, GLenum pname, GLvoid** pointer) = NULL; --static void (*_glHint)(GLenum target, GLenum mode) = NULL; --static GLboolean (*_glIsBuffer)(GLuint buffer) = NULL; --static GLboolean (*_glIsEnabled)(GLenum cap) = NULL; --static GLboolean (*_glIsFramebuffer)(GLuint framebuffer) = NULL; --static GLboolean (*_glIsProgram)(GLuint program) = NULL; --static GLboolean (*_glIsRenderbuffer)(GLuint renderbuffer) = NULL; --static GLboolean (*_glIsShader)(GLuint shader) = NULL; --static GLboolean (*_glIsTexture)(GLuint texture) = NULL; ++static void (*_glDetachShader)(GLuint program, GLuint shader) = NULL; ++static void (*_glDisable)(GLenum cap) = NULL; ++static void (*_glDisableVertexAttribArray)(GLuint index) = NULL; ++static void (*_glDrawArrays)(GLenum mode, GLint first, GLsizei count) = NULL; ++static void (*_glDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) = NULL; ++static void (*_glEnable)(GLenum cap) = NULL; ++static void (*_glEnableVertexAttribArray)(GLuint index) = NULL; ++static void (*_glFinish)(void) = NULL; ++static void (*_glFlush)(void) = NULL; ++static void (*_glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) = NULL; ++static void (*_glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) = NULL; ++static void (*_glFrontFace)(GLenum mode) = NULL; ++static void (*_glGenBuffers)(GLsizei n, GLuint* buffers) = NULL; ++static void (*_glGenerateMipmap)(GLenum target) = NULL; ++static void (*_glGenFramebuffers)(GLsizei n, GLuint* framebuffers) = NULL; ++static void (*_glGenRenderbuffers)(GLsizei n, GLuint* renderbuffers) = NULL; ++static void (*_glGenTextures)(GLsizei n, GLuint* textures) = NULL; ++static void (*_glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) = NULL; ++static void (*_glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) = NULL; ++static void (*_glGetAttachedShaders)(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) = NULL; ++static int (*_glGetAttribLocation)(GLuint program, const GLchar* name) = NULL; ++static void (*_glGetBooleanv)(GLenum pname, GLboolean* params) = NULL; ++static void (*_glGetBufferParameteriv)(GLenum target, GLenum pname, GLint* params) = NULL; ++static GLenum (*_glGetError)(void) = NULL; ++static void (*_glGetFloatv)(GLenum pname, GLfloat* params) = NULL; ++static void (*_glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint* params) = NULL; ++static void (*_glGetIntegerv)(GLenum pname, GLint* params) = NULL; ++static void (*_glGetProgramiv)(GLuint program, GLenum pname, GLint* params) = NULL; ++static void (*_glGetProgramInfoLog)(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog) = NULL; ++static void (*_glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint* params) = NULL; ++static void (*_glGetShaderiv)(GLuint shader, GLenum pname, GLint* params) = NULL; ++static void (*_glGetShaderInfoLog)(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog) = NULL; ++static void (*_glGetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) = NULL; ++static void (*_glGetShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) = NULL; ++static const GLubyte* (*_glGetString)(GLenum name) = NULL; ++static void (*_glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat* params) = NULL; ++static void (*_glGetTexParameteriv)(GLenum target, GLenum pname, GLint* params) = NULL; ++static void (*_glGetUniformfv)(GLuint program, GLint location, GLfloat* params) = NULL; ++static void (*_glGetUniformiv)(GLuint program, GLint location, GLint* params) = NULL; ++static int (*_glGetUniformLocation)(GLuint program, const GLchar* name) = NULL; ++static void (*_glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat* params) = NULL; ++static void (*_glGetVertexAttribiv)(GLuint index, GLenum pname, GLint* params) = NULL; ++static void (*_glGetVertexAttribPointerv)(GLuint index, GLenum pname, GLvoid** pointer) = NULL; ++static void (*_glHint)(GLenum target, GLenum mode) = NULL; ++static GLboolean (*_glIsBuffer)(GLuint buffer) = NULL; ++static GLboolean (*_glIsEnabled)(GLenum cap) = NULL; ++static GLboolean (*_glIsFramebuffer)(GLuint framebuffer) = NULL; ++static GLboolean (*_glIsProgram)(GLuint program) = NULL; ++static GLboolean (*_glIsRenderbuffer)(GLuint renderbuffer) = NULL; ++static GLboolean (*_glIsShader)(GLuint shader) = NULL; ++static GLboolean (*_glIsTexture)(GLuint texture) = NULL; static void (*_glLineWidth)(GLfloat width) FP_ATTRIB = NULL; --static void (*_glLinkProgram)(GLuint program) = NULL; --static void (*_glPixelStorei)(GLenum pname, GLint param) = NULL; ++static void (*_glLinkProgram)(GLuint program) = NULL; ++static void (*_glPixelStorei)(GLenum pname, GLint param) = NULL; static void (*_glPolygonOffset)(GLfloat factor, GLfloat units) FP_ATTRIB = NULL; --static void (*_glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) = NULL; --static void (*_glReleaseShaderCompiler)(void) = NULL; --static void (*_glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) = NULL; ++static void (*_glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) = NULL; ++static void (*_glReleaseShaderCompiler)(void) = NULL; ++static void (*_glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) = NULL; static void (*_glSampleCoverage)(GLclampf value, GLboolean invert) FP_ATTRIB = NULL; --static void (*_glScissor)(GLint x, GLint y, GLsizei width, GLsizei height) = NULL; --static void (*_glShaderBinary)(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length) = NULL; --static void (*_glShaderSource)(GLuint shader, GLsizei count, const GLchar** string, const GLint* length) = NULL; --static void (*_glStencilFunc)(GLenum func, GLint ref, GLuint mask) = NULL; --static void (*_glStencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask) = NULL; --static void (*_glStencilMask)(GLuint mask) = NULL; --static void (*_glStencilMaskSeparate)(GLenum face, GLuint mask) = NULL; --static void (*_glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass) = NULL; --static void (*_glStencilOpSeparate)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) = NULL; --static void (*_glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels) = NULL; ++static void (*_glScissor)(GLint x, GLint y, GLsizei width, GLsizei height) = NULL; ++static void (*_glShaderBinary)(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length) = NULL; ++static void (*_glShaderSource)(GLuint shader, GLsizei count, const GLchar** string, const GLint* length) = NULL; ++static void (*_glStencilFunc)(GLenum func, GLint ref, GLuint mask) = NULL; ++static void (*_glStencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask) = NULL; ++static void (*_glStencilMask)(GLuint mask) = NULL; ++static void (*_glStencilMaskSeparate)(GLenum face, GLuint mask) = NULL; ++static void (*_glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass) = NULL; ++static void (*_glStencilOpSeparate)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) = NULL; ++static void (*_glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels) = NULL; static void (*_glTexParameterf)(GLenum target, GLenum pname, GLfloat param) FP_ATTRIB = NULL; --static void (*_glTexParameterfv)(GLenum target, GLenum pname, const GLfloat* params) = NULL; --static void (*_glTexParameteri)(GLenum target, GLenum pname, GLint param) = NULL; --static void (*_glTexParameteriv)(GLenum target, GLenum pname, const GLint* params) = NULL; --static void (*_glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) = NULL; ++static void (*_glTexParameterfv)(GLenum target, GLenum pname, const GLfloat* params) = NULL; ++static void (*_glTexParameteri)(GLenum target, GLenum pname, GLint param) = NULL; ++static void (*_glTexParameteriv)(GLenum target, GLenum pname, const GLint* params) = NULL; ++static void (*_glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) = NULL; static void (*_glUniform1f)(GLint location, GLfloat x) FP_ATTRIB = NULL; --static void (*_glUniform1fv)(GLint location, GLsizei count, const GLfloat* v) = NULL; --static void (*_glUniform1i)(GLint location, GLint x) = NULL; --static void (*_glUniform1iv)(GLint location, GLsizei count, const GLint* v) = NULL; ++static void (*_glUniform1fv)(GLint location, GLsizei count, const GLfloat* v) = NULL; ++static void (*_glUniform1i)(GLint location, GLint x) = NULL; ++static void (*_glUniform1iv)(GLint location, GLsizei count, const GLint* v) = NULL; static void (*_glUniform2f)(GLint location, GLfloat x, GLfloat y) FP_ATTRIB = NULL; --static void (*_glUniform2fv)(GLint location, GLsizei count, const GLfloat* v) = NULL; --static void (*_glUniform2i)(GLint location, GLint x, GLint y) = NULL; --static void (*_glUniform2iv)(GLint location, GLsizei count, const GLint* v) = NULL; ++static void (*_glUniform2fv)(GLint location, GLsizei count, const GLfloat* v) = NULL; ++static void (*_glUniform2i)(GLint location, GLint x, GLint y) = NULL; ++static void (*_glUniform2iv)(GLint location, GLsizei count, const GLint* v) = NULL; static void (*_glUniform3f)(GLint location, GLfloat x, GLfloat y, GLfloat z) FP_ATTRIB = NULL; --static void (*_glUniform3fv)(GLint location, GLsizei count, const GLfloat* v) = NULL; --static void (*_glUniform3i)(GLint location, GLint x, GLint y, GLint z) = NULL; --static void (*_glUniform3iv)(GLint location, GLsizei count, const GLint* v) = NULL; ++static void (*_glUniform3fv)(GLint location, GLsizei count, const GLfloat* v) = NULL; ++static void (*_glUniform3i)(GLint location, GLint x, GLint y, GLint z) = NULL; ++static void (*_glUniform3iv)(GLint location, GLsizei count, const GLint* v) = NULL; static void (*_glUniform4f)(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) FP_ATTRIB = NULL; --static void (*_glUniform4fv)(GLint location, GLsizei count, const GLfloat* v) = NULL; --static void (*_glUniform4i)(GLint location, GLint x, GLint y, GLint z, GLint w) = NULL; --static void (*_glUniform4iv)(GLint location, GLsizei count, const GLint* v) = NULL; --static void (*_glUniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = NULL; --static void (*_glUniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = NULL; --static void (*_glUniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = NULL; --static void (*_glUseProgram)(GLuint program) = NULL; --static void (*_glValidateProgram)(GLuint program) = NULL; ++static void (*_glUniform4fv)(GLint location, GLsizei count, const GLfloat* v) = NULL; ++static void (*_glUniform4i)(GLint location, GLint x, GLint y, GLint z, GLint w) = NULL; ++static void (*_glUniform4iv)(GLint location, GLsizei count, const GLint* v) = NULL; ++static void (*_glUniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = NULL; ++static void (*_glUniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = NULL; ++static void (*_glUniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = NULL; ++static void (*_glUseProgram)(GLuint program) = NULL; ++static void (*_glValidateProgram)(GLuint program) = NULL; static void (*_glVertexAttrib1f)(GLuint indx, GLfloat x) FP_ATTRIB = NULL; --static void (*_glVertexAttrib1fv)(GLuint indx, const GLfloat* values) = NULL; ++static void (*_glVertexAttrib1fv)(GLuint indx, const GLfloat* values) = NULL; static void (*_glVertexAttrib2f)(GLuint indx, GLfloat x, GLfloat y) FP_ATTRIB = NULL; --static void (*_glVertexAttrib2fv)(GLuint indx, const GLfloat* values) = NULL; ++static void (*_glVertexAttrib2fv)(GLuint indx, const GLfloat* values) = NULL; static void (*_glVertexAttrib3f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z) FP_ATTRIB = NULL; --static void (*_glVertexAttrib3fv)(GLuint indx, const GLfloat* values) = NULL; ++static void (*_glVertexAttrib3fv)(GLuint indx, const GLfloat* values) = NULL; static void (*_glVertexAttrib4f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) FP_ATTRIB = NULL; --static void (*_glVertexAttrib4fv)(GLuint indx, const GLfloat* values) = NULL; --static void (*_glVertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) = NULL; --static void (*_glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) = NULL; --static void (*_glEGLImageTargetTexture2DOES) (GLenum target, GLeglImageOES image) = NULL; +-static void (*_glEGLImageTargetTexture2DOES)(GLenum target, GLeglImageOES image) = NULL; ++static void (*_glVertexAttrib4fv)(GLuint indx, const GLfloat* values) = NULL; ++static void (*_glVertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) = NULL; ++static void (*_glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) = NULL; ++static void (*_glEGLImageTargetTexture2DOES) (GLenum target, GLeglImageOES image) = NULL; #define GLES2_LOAD(sym) { *(&_ ## sym) = (void *) android_dlsym(_libglesv2, #sym); } -+/* -+This generates a function that when first called overwrites it's plt entry with new address. Subsequent calls jump directly at the target function in the android library. This means effectively 0 call overhead after the first call. -+*/ -+ -+#define GLES2_IDLOAD(sym) \ -+ __asm__ (".type " #sym ", %gnu_indirect_function"); \ -+typeof(sym) * sym ## _dispatch (void) __asm__ (#sym);\ -+typeof(sym) * sym ## _dispatch (void) \ -+{ \ -+ return (void *) android_dlsym(_libglesv2, #sym); \ -+} -+ +-/* +-This generates a function that when first called overwrites it's plt entry with new address. Subsequent calls jump directly at the target function in the android library. This means effectively 0 call overhead after the first call. +-*/ +- +-#define GLES2_IDLOAD(sym) \ +- __asm__ (".type " #sym ", %gnu_indirect_function"); \ +-typeof(sym) * sym ## _dispatch (void) __asm__ (#sym);\ +-typeof(sym) * sym ## _dispatch (void) \ +-{ \ +- return (void *) android_dlsym(_libglesv2, #sym); \ +-} +- static void __attribute__((constructor)) _init_androidglesv2() { _libglesv2 = (void *) android_dlopen(getenv("LIBGLESV2") ? getenv("LIBGLESV2") : "libGLESv2.so", RTLD_NOW); -- GLES2_LOAD(glActiveTexture); -- GLES2_LOAD(glAttachShader); -- GLES2_LOAD(glBindAttribLocation); -- GLES2_LOAD(glBindBuffer); -- GLES2_LOAD(glBindFramebuffer); -- GLES2_LOAD(glBindRenderbuffer); -- GLES2_LOAD(glBindTexture); ++ GLES2_LOAD(glActiveTexture); ++ GLES2_LOAD(glAttachShader); ++ GLES2_LOAD(glBindAttribLocation); ++ GLES2_LOAD(glBindBuffer); ++ GLES2_LOAD(glBindFramebuffer); ++ GLES2_LOAD(glBindRenderbuffer); ++ GLES2_LOAD(glBindTexture); GLES2_LOAD(glBlendColor); -- GLES2_LOAD(glBlendEquation); -- GLES2_LOAD(glBlendEquationSeparate); -- GLES2_LOAD(glBlendFunc); -- GLES2_LOAD(glBlendFuncSeparate); -- GLES2_LOAD(glBufferData); -- GLES2_LOAD(glBufferSubData); -- GLES2_LOAD(glCheckFramebufferStatus); -- GLES2_LOAD(glClear); ++ GLES2_LOAD(glBlendEquation); ++ GLES2_LOAD(glBlendEquationSeparate); ++ GLES2_LOAD(glBlendFunc); ++ GLES2_LOAD(glBlendFuncSeparate); ++ GLES2_LOAD(glBufferData); ++ GLES2_LOAD(glBufferSubData); ++ GLES2_LOAD(glCheckFramebufferStatus); ++ GLES2_LOAD(glClear); GLES2_LOAD(glClearColor); GLES2_LOAD(glClearDepthf); -- GLES2_LOAD(glClearStencil); -- GLES2_LOAD(glColorMask); -- GLES2_LOAD(glCompileShader); -- GLES2_LOAD(glCompressedTexImage2D); -- GLES2_LOAD(glCompressedTexSubImage2D); -- GLES2_LOAD(glCopyTexImage2D); -- GLES2_LOAD(glCopyTexSubImage2D); -- GLES2_LOAD(glCreateProgram); -- GLES2_LOAD(glCreateShader); -- GLES2_LOAD(glCullFace); -- GLES2_LOAD(glDeleteBuffers); -- GLES2_LOAD(glDeleteFramebuffers); -- GLES2_LOAD(glDeleteProgram); -- GLES2_LOAD(glDeleteRenderbuffers); -- GLES2_LOAD(glDeleteShader); -- GLES2_LOAD(glDeleteTextures); -- GLES2_LOAD(glDepthFunc); -- GLES2_LOAD(glDepthMask); ++ GLES2_LOAD(glClearStencil); ++ GLES2_LOAD(glColorMask); ++ GLES2_LOAD(glCompileShader); ++ GLES2_LOAD(glCompressedTexImage2D); ++ GLES2_LOAD(glCompressedTexSubImage2D); ++ GLES2_LOAD(glCopyTexImage2D); ++ GLES2_LOAD(glCopyTexSubImage2D); ++ GLES2_LOAD(glCreateProgram); ++ GLES2_LOAD(glCreateShader); ++ GLES2_LOAD(glCullFace); ++ GLES2_LOAD(glDeleteBuffers); ++ GLES2_LOAD(glDeleteFramebuffers); ++ GLES2_LOAD(glDeleteProgram); ++ GLES2_LOAD(glDeleteRenderbuffers); ++ GLES2_LOAD(glDeleteShader); ++ GLES2_LOAD(glDeleteTextures); ++ GLES2_LOAD(glDepthFunc); ++ GLES2_LOAD(glDepthMask); GLES2_LOAD(glDepthRangef); -- GLES2_LOAD(glDetachShader); -- GLES2_LOAD(glDisable); -- GLES2_LOAD(glDisableVertexAttribArray); -- GLES2_LOAD(glDrawArrays); -- GLES2_LOAD(glDrawElements); -- GLES2_LOAD(glEnable); -- GLES2_LOAD(glEnableVertexAttribArray); -- GLES2_LOAD(glFinish); -- GLES2_LOAD(glFlush); -- GLES2_LOAD(glFramebufferRenderbuffer); -- GLES2_LOAD(glFramebufferTexture2D); -- GLES2_LOAD(glFrontFace); -- GLES2_LOAD(glGenBuffers); -- GLES2_LOAD(glGenerateMipmap); -- GLES2_LOAD(glGenFramebuffers); -- GLES2_LOAD(glGenRenderbuffers); -- GLES2_LOAD(glGenTextures); -- GLES2_LOAD(glGetActiveAttrib); -- GLES2_LOAD(glGetActiveUniform); -- GLES2_LOAD(glGetAttachedShaders); -- GLES2_LOAD(glGetAttribLocation); -- GLES2_LOAD(glGetBooleanv); -- GLES2_LOAD(glGetBufferParameteriv); -- GLES2_LOAD(glGetError); -- GLES2_LOAD(glGetFloatv); -- GLES2_LOAD(glGetFramebufferAttachmentParameteriv); -- GLES2_LOAD(glGetIntegerv); -- GLES2_LOAD(glGetProgramiv); -- GLES2_LOAD(glGetProgramInfoLog); -- GLES2_LOAD(glGetRenderbufferParameteriv); -- GLES2_LOAD(glGetShaderiv); -- GLES2_LOAD(glGetShaderInfoLog); -- GLES2_LOAD(glGetShaderPrecisionFormat); -- GLES2_LOAD(glGetShaderSource); -- GLES2_LOAD(glGetString); -- GLES2_LOAD(glGetTexParameterfv); -- GLES2_LOAD(glGetTexParameteriv); -- GLES2_LOAD(glGetUniformfv); -- GLES2_LOAD(glGetUniformiv); -- GLES2_LOAD(glGetUniformLocation); -- GLES2_LOAD(glGetVertexAttribfv); -- GLES2_LOAD(glGetVertexAttribiv); -- GLES2_LOAD(glGetVertexAttribPointerv); -- GLES2_LOAD(glHint); -- GLES2_LOAD(glIsBuffer); -- GLES2_LOAD(glIsEnabled); -- GLES2_LOAD(glIsFramebuffer); -- GLES2_LOAD(glIsProgram); -- GLES2_LOAD(glIsRenderbuffer); -- GLES2_LOAD(glIsShader); -- GLES2_LOAD(glIsTexture); ++ GLES2_LOAD(glDetachShader); ++ GLES2_LOAD(glDisable); ++ GLES2_LOAD(glDisableVertexAttribArray); ++ GLES2_LOAD(glDrawArrays); ++ GLES2_LOAD(glDrawElements); ++ GLES2_LOAD(glEnable); ++ GLES2_LOAD(glEnableVertexAttribArray); ++ GLES2_LOAD(glFinish); ++ GLES2_LOAD(glFlush); ++ GLES2_LOAD(glFramebufferRenderbuffer); ++ GLES2_LOAD(glFramebufferTexture2D); ++ GLES2_LOAD(glFrontFace); ++ GLES2_LOAD(glGenBuffers); ++ GLES2_LOAD(glGenerateMipmap); ++ GLES2_LOAD(glGenFramebuffers); ++ GLES2_LOAD(glGenRenderbuffers); ++ GLES2_LOAD(glGenTextures); ++ GLES2_LOAD(glGetActiveAttrib); ++ GLES2_LOAD(glGetActiveUniform); ++ GLES2_LOAD(glGetAttachedShaders); ++ GLES2_LOAD(glGetAttribLocation); ++ GLES2_LOAD(glGetBooleanv); ++ GLES2_LOAD(glGetBufferParameteriv); ++ GLES2_LOAD(glGetError); ++ GLES2_LOAD(glGetFloatv); ++ GLES2_LOAD(glGetFramebufferAttachmentParameteriv); ++ GLES2_LOAD(glGetIntegerv); ++ GLES2_LOAD(glGetProgramiv); ++ GLES2_LOAD(glGetProgramInfoLog); ++ GLES2_LOAD(glGetRenderbufferParameteriv); ++ GLES2_LOAD(glGetShaderiv); ++ GLES2_LOAD(glGetShaderInfoLog); ++ GLES2_LOAD(glGetShaderPrecisionFormat); ++ GLES2_LOAD(glGetShaderSource); ++ GLES2_LOAD(glGetString); ++ GLES2_LOAD(glGetTexParameterfv); ++ GLES2_LOAD(glGetTexParameteriv); ++ GLES2_LOAD(glGetUniformfv); ++ GLES2_LOAD(glGetUniformiv); ++ GLES2_LOAD(glGetUniformLocation); ++ GLES2_LOAD(glGetVertexAttribfv); ++ GLES2_LOAD(glGetVertexAttribiv); ++ GLES2_LOAD(glGetVertexAttribPointerv); ++ GLES2_LOAD(glHint); ++ GLES2_LOAD(glIsBuffer); ++ GLES2_LOAD(glIsEnabled); ++ GLES2_LOAD(glIsFramebuffer); ++ GLES2_LOAD(glIsProgram); ++ GLES2_LOAD(glIsRenderbuffer); ++ GLES2_LOAD(glIsShader); ++ GLES2_LOAD(glIsTexture); GLES2_LOAD(glLineWidth); -- GLES2_LOAD(glLinkProgram); -- GLES2_LOAD(glPixelStorei); ++ GLES2_LOAD(glLinkProgram); ++ GLES2_LOAD(glPixelStorei); GLES2_LOAD(glPolygonOffset); -- GLES2_LOAD(glReadPixels); -- GLES2_LOAD(glReleaseShaderCompiler); -- GLES2_LOAD(glRenderbufferStorage); ++ GLES2_LOAD(glReadPixels); ++ GLES2_LOAD(glReleaseShaderCompiler); ++ GLES2_LOAD(glRenderbufferStorage); GLES2_LOAD(glSampleCoverage); -- GLES2_LOAD(glScissor); -- GLES2_LOAD(glShaderBinary); -- GLES2_LOAD(glShaderSource); -- GLES2_LOAD(glStencilFunc); -- GLES2_LOAD(glStencilFuncSeparate); -- GLES2_LOAD(glStencilMask); -- GLES2_LOAD(glStencilMaskSeparate); -- GLES2_LOAD(glStencilOp); -- GLES2_LOAD(glStencilOpSeparate); -- GLES2_LOAD(glTexImage2D); ++ GLES2_LOAD(glScissor); ++ GLES2_LOAD(glShaderBinary); ++ GLES2_LOAD(glShaderSource); ++ GLES2_LOAD(glStencilFunc); ++ GLES2_LOAD(glStencilFuncSeparate); ++ GLES2_LOAD(glStencilMask); ++ GLES2_LOAD(glStencilMaskSeparate); ++ GLES2_LOAD(glStencilOp); ++ GLES2_LOAD(glStencilOpSeparate); ++ GLES2_LOAD(glTexImage2D); GLES2_LOAD(glTexParameterf); -- GLES2_LOAD(glTexParameterfv); -- GLES2_LOAD(glTexParameteri); -- GLES2_LOAD(glTexParameteriv); -- GLES2_LOAD(glTexSubImage2D); ++ GLES2_LOAD(glTexParameterfv); ++ GLES2_LOAD(glTexParameteri); ++ GLES2_LOAD(glTexParameteriv); ++ GLES2_LOAD(glTexSubImage2D); GLES2_LOAD(glUniform1f); -- GLES2_LOAD(glUniform1fv); -- GLES2_LOAD(glUniform1i); -- GLES2_LOAD(glUniform1iv); ++ GLES2_LOAD(glUniform1fv); ++ GLES2_LOAD(glUniform1i); ++ GLES2_LOAD(glUniform1iv); GLES2_LOAD(glUniform2f); -- GLES2_LOAD(glUniform2fv); -- GLES2_LOAD(glUniform2i); -- GLES2_LOAD(glUniform2iv); ++ GLES2_LOAD(glUniform2fv); ++ GLES2_LOAD(glUniform2i); ++ GLES2_LOAD(glUniform2iv); GLES2_LOAD(glUniform3f); -- GLES2_LOAD(glUniform3fv); -- GLES2_LOAD(glUniform3i); -- GLES2_LOAD(glUniform3iv); ++ GLES2_LOAD(glUniform3fv); ++ GLES2_LOAD(glUniform3i); ++ GLES2_LOAD(glUniform3iv); GLES2_LOAD(glUniform4f); -- GLES2_LOAD(glUniform4fv); -- GLES2_LOAD(glUniform4i); -- GLES2_LOAD(glUniform4iv); -- GLES2_LOAD(glUniformMatrix2fv); -- GLES2_LOAD(glUniformMatrix3fv); -- GLES2_LOAD(glUniformMatrix4fv); -- GLES2_LOAD(glUseProgram); -- GLES2_LOAD(glValidateProgram); ++ GLES2_LOAD(glUniform4fv); ++ GLES2_LOAD(glUniform4i); ++ GLES2_LOAD(glUniform4iv); ++ GLES2_LOAD(glUniformMatrix2fv); ++ GLES2_LOAD(glUniformMatrix3fv); ++ GLES2_LOAD(glUniformMatrix4fv); ++ GLES2_LOAD(glUseProgram); ++ GLES2_LOAD(glValidateProgram); GLES2_LOAD(glVertexAttrib1f); -- GLES2_LOAD(glVertexAttrib1fv); ++ GLES2_LOAD(glVertexAttrib1fv); GLES2_LOAD(glVertexAttrib2f); -- GLES2_LOAD(glVertexAttrib2fv); ++ GLES2_LOAD(glVertexAttrib2fv); GLES2_LOAD(glVertexAttrib3f); -- GLES2_LOAD(glVertexAttrib3fv); ++ GLES2_LOAD(glVertexAttrib3fv); GLES2_LOAD(glVertexAttrib4f); -- GLES2_LOAD(glVertexAttrib4fv); -- GLES2_LOAD(glVertexAttribPointer); -- GLES2_LOAD(glViewport); -- GLES2_LOAD(glEGLImageTargetTexture2DOES); -- --} - -- --void glActiveTexture (GLenum texture) --{ -- return (*_glActiveTexture)(texture); ++ GLES2_LOAD(glVertexAttrib4fv); ++ GLES2_LOAD(glVertexAttribPointer); ++ GLES2_LOAD(glViewport); + GLES2_LOAD(glEGLImageTargetTexture2DOES); ++ } --void glAttachShader (GLuint program, GLuint shader) --{ -- return (*_glAttachShader)(program, shader); --} - --void glBindAttribLocation (GLuint program, GLuint index, const GLchar* name) --{ -- return (*_glBindAttribLocation)(program, index, name); --} -+GLES2_IDLOAD(glActiveTexture); --void glBindBuffer (GLenum target, GLuint buffer) --{ -- return (*_glBindBuffer)(target, buffer); --} -+GLES2_IDLOAD(glAttachShader); +-GLES2_IDLOAD(glActiveTexture); ++void glActiveTexture (GLenum texture) ++{ ++ (*_glActiveTexture)(texture); ++} --void glBindFramebuffer (GLenum target, GLuint framebuffer) --{ -- return (*_glBindFramebuffer)(target, framebuffer); --} -+GLES2_IDLOAD(glBindAttribLocation); +-GLES2_IDLOAD(glAttachShader); ++void glAttachShader (GLuint program, GLuint shader) ++{ ++ (*_glAttachShader)(program, shader); ++} --void glBindRenderbuffer (GLenum target, GLuint renderbuffer) --{ -- return (*_glBindRenderbuffer)(target, renderbuffer); --} -+GLES2_IDLOAD(glBindBuffer); +-GLES2_IDLOAD(glBindAttribLocation); ++void glBindAttribLocation (GLuint program, GLuint index, const GLchar* name) ++{ ++ (*_glBindAttribLocation)(program, index, name); ++} --void glBindTexture (GLenum target, GLuint texture) --{ -- return (*_glBindTexture)(target, texture); --} -+GLES2_IDLOAD(glBindFramebuffer); +-GLES2_IDLOAD(glBindBuffer); ++void glBindBuffer (GLenum target, GLuint buffer) ++{ ++ (*_glBindBuffer)(target, buffer); ++} --void glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) --{ -- return (*_glBlendColor)(red, green, blue, alpha); --} -+GLES2_IDLOAD(glBindRenderbuffer); +-GLES2_IDLOAD(glBindFramebuffer); ++void glBindFramebuffer (GLenum target, GLuint framebuffer) ++{ ++ (*_glBindFramebuffer)(target, framebuffer); ++} --void glBlendEquation ( GLenum mode ) --{ -- return (*_glBlendEquation)(mode); --} -+GLES2_IDLOAD(glBindTexture); +-GLES2_IDLOAD(glBindRenderbuffer); ++void glBindRenderbuffer (GLenum target, GLuint renderbuffer) ++{ ++ (*_glBindRenderbuffer)(target, renderbuffer); ++} --void glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha) --{ -- return (*_glBlendEquationSeparate)(modeRGB, modeAlpha); --} -+GLES2_IDLOAD(glBlendEquation); +-GLES2_IDLOAD(glBindTexture); ++void glBindTexture (GLenum target, GLuint texture) ++{ ++ (*_glBindTexture)(target, texture); ++} --void glBlendFunc (GLenum sfactor, GLenum dfactor) --{ -- return (*_glBlendFunc)(sfactor, dfactor); --} -+GLES2_IDLOAD(glBlendEquationSeparate); +-GLES2_IDLOAD(glBlendEquation); ++void glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) ++{ ++ (*_glBlendColor)(red, green, blue, alpha); ++} --void glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) --{ -- return (*_glBlendFuncSeparate)(srcRGB, dstRGB, srcAlpha, dstAlpha); --} -+GLES2_IDLOAD(glBlendFunc); +-GLES2_IDLOAD(glBlendEquationSeparate); ++void glBlendEquation ( GLenum mode ) ++{ ++ (*_glBlendEquation)(mode); ++} --void glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) --{ -- return (*_glBufferData)(target, size, data, usage); --} -+GLES2_IDLOAD(glBlendFuncSeparate); +-GLES2_IDLOAD(glBlendFunc); ++void glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha) ++{ ++ (*_glBlendEquationSeparate)(modeRGB, modeAlpha); ++} --void glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) --{ -- return (*_glBufferSubData)(target, offset, size, data); --} -+GLES2_IDLOAD(glBufferData); +-GLES2_IDLOAD(glBlendFuncSeparate); ++void glBlendFunc (GLenum sfactor, GLenum dfactor) ++{ ++ (*_glBlendFunc)(sfactor, dfactor); ++} --GLenum glCheckFramebufferStatus (GLenum target) --{ -- return (*_glCheckFramebufferStatus)(target); --} -+GLES2_IDLOAD(glBufferSubData); +-GLES2_IDLOAD(glBufferData); ++void glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) ++{ ++ (*_glBlendFuncSeparate)(srcRGB, dstRGB, srcAlpha, dstAlpha); ++} --void glClear (GLbitfield mask) --{ -- return (*_glClear)(mask); --} -+GLES2_IDLOAD(glCheckFramebufferStatus); +-GLES2_IDLOAD(glBufferSubData); ++void glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) ++{ ++ (*_glBufferData)(target, size, data, usage); ++} --void glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) --{ -- return (*_glClearColor)(red, green, blue, alpha); --} -+GLES2_IDLOAD(glClear); +-GLES2_IDLOAD(glCheckFramebufferStatus); ++void glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) ++{ ++ (*_glBufferSubData)(target, offset, size, data); ++} --void glClearDepthf (GLclampf depth) --{ -- return (*_glClearDepthf)(depth); --} -+GLES2_IDLOAD(glClearStencil); +-GLES2_IDLOAD(glClear); ++GLenum glCheckFramebufferStatus (GLenum target) ++{ ++ return (*_glCheckFramebufferStatus)(target); ++} --void glClearStencil (GLint s) --{ -- return (*_glClearStencil)(s); --} -+GLES2_IDLOAD(glColorMask); +-GLES2_IDLOAD(glClearStencil); ++void glClear (GLbitfield mask) ++{ ++ (*_glClear)(mask); ++} --void glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) --{ -- return (*_glColorMask)(red, green, blue, alpha); --} -+GLES2_IDLOAD(glCompileShader); +-GLES2_IDLOAD(glColorMask); ++void glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) ++{ ++ (*_glClearColor)(red, green, blue, alpha); ++} --void glCompileShader (GLuint shader) --{ -- return (*_glCompileShader)(shader); --} -+GLES2_IDLOAD(glCompressedTexImage2D); +-GLES2_IDLOAD(glCompileShader); ++void glClearDepthf (GLclampf depth) ++{ ++ (*_glClearDepthf)(depth); ++} --void glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) --{ -- return (*_glCompressedTexImage2D)(target, level, internalformat, width, height, border, imageSize, data); --} -+GLES2_IDLOAD(glCompressedTexSubImage2D); +-GLES2_IDLOAD(glCompressedTexImage2D); ++void glClearStencil (GLint s) ++{ ++ (*_glClearStencil)(s); ++} --void glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) --{ -- return (*_glCompressedTexSubImage2D)(target, level, xoffset, yoffset, width, height, format, imageSize, data); --} -+GLES2_IDLOAD(glCopyTexImage2D); +-GLES2_IDLOAD(glCompressedTexSubImage2D); ++void glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) ++{ ++ (*_glColorMask)(red, green, blue, alpha); ++} --void glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) --{ -- return (*_glCopyTexImage2D)(target, level, internalformat, x, y, width, height, border); --} -+GLES2_IDLOAD(glCopyTexSubImage2D); +-GLES2_IDLOAD(glCopyTexImage2D); ++void glCompileShader (GLuint shader) ++{ ++ (*_glCompileShader)(shader); ++} --void glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) --{ -- return (*_glCopyTexSubImage2D)(target, level, xoffset, yoffset, x, y, width, height); --} -+GLES2_IDLOAD(glCreateProgram); +-GLES2_IDLOAD(glCopyTexSubImage2D); ++void glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) ++{ ++ (*_glCompressedTexImage2D)(target, level, internalformat, width, height, border, imageSize, data); ++} --GLuint glCreateProgram (void) --{ -- return (*_glCreateProgram)(); --} -+GLES2_IDLOAD(glCreateShader); +-GLES2_IDLOAD(glCreateProgram); ++void glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) ++{ ++ (*_glCompressedTexSubImage2D)(target, level, xoffset, yoffset, width, height, format, imageSize, data); ++} --GLuint glCreateShader (GLenum type) --{ -- return (*_glCreateShader)(type); --} -+GLES2_IDLOAD(glCullFace); +-GLES2_IDLOAD(glCreateShader); ++void glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) ++{ ++ (*_glCopyTexImage2D)(target, level, internalformat, x, y, width, height, border); ++} --void glCullFace (GLenum mode) --{ -- return (*_glCullFace)(mode); --} -+GLES2_IDLOAD(glDeleteBuffers); +-GLES2_IDLOAD(glCullFace); ++void glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) ++{ ++ (*_glCopyTexSubImage2D)(target, level, xoffset, yoffset, x, y, width, height); ++} --void glDeleteBuffers (GLsizei n, const GLuint* buffers) --{ -- return (*_glDeleteBuffers)(n, buffers); --} -+GLES2_IDLOAD(glDeleteFramebuffers); +-GLES2_IDLOAD(glDeleteBuffers); ++GLuint glCreateProgram (void) ++{ ++ return (*_glCreateProgram)(); ++} --void glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers) --{ -- return (*_glDeleteFramebuffers)(n, framebuffers); --} -+GLES2_IDLOAD(glDeleteProgram); +-GLES2_IDLOAD(glDeleteFramebuffers); ++GLuint glCreateShader (GLenum type) ++{ ++ return (*_glCreateShader)(type); ++} --void glDeleteProgram (GLuint program) --{ -- return (*_glDeleteProgram)(program); --} -+GLES2_IDLOAD(glDeleteRenderbuffers); +-GLES2_IDLOAD(glDeleteProgram); ++void glCullFace (GLenum mode) ++{ ++ (*_glCullFace)(mode); ++} --void glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers) --{ -- return (*_glDeleteRenderbuffers)(n, renderbuffers); --} -+GLES2_IDLOAD(glDeleteShader); +-GLES2_IDLOAD(glDeleteRenderbuffers); ++void glDeleteBuffers (GLsizei n, const GLuint* buffers) ++{ ++ (*_glDeleteBuffers)(n, buffers); ++} --void glDeleteShader (GLuint shader) --{ -- return (*_glDeleteShader)(shader); --} -+GLES2_IDLOAD(glDeleteTextures); +-GLES2_IDLOAD(glDeleteShader); ++void glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers) ++{ ++ (*_glDeleteFramebuffers)(n, framebuffers); ++} --void glDeleteTextures (GLsizei n, const GLuint* textures) --{ -- return (*_glDeleteTextures)(n, textures); --} -+GLES2_IDLOAD(glDepthFunc); +-GLES2_IDLOAD(glDeleteTextures); ++void glDeleteProgram (GLuint program) ++{ ++ (*_glDeleteProgram)(program); ++} --void glDepthFunc (GLenum func) --{ -- return (*_glDepthFunc)(func); --} -+GLES2_IDLOAD(glDepthMask); +-GLES2_IDLOAD(glDepthFunc); ++void glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers) ++{ ++ (*_glDeleteRenderbuffers)(n, renderbuffers); ++} --void glDepthMask (GLboolean flag) --{ -- return (*_glDepthMask)(flag); --} -+GLES2_IDLOAD(glDetachShader); +-GLES2_IDLOAD(glDepthMask); ++void glDeleteShader (GLuint shader) ++{ ++ (*_glDeleteShader)(shader); ++} --void glDepthRangef (GLclampf zNear, GLclampf zFar) --{ -- return (*_glDepthRangef)(zNear, zFar); --} -+GLES2_IDLOAD(glDisable); +-GLES2_IDLOAD(glDetachShader); ++void glDeleteTextures (GLsizei n, const GLuint* textures) ++{ ++ (*_glDeleteTextures)(n, textures); ++} --void glDetachShader (GLuint program, GLuint shader) --{ -- return (*_glDetachShader)(program, shader); --} -+GLES2_IDLOAD(glDisableVertexAttribArray); +-GLES2_IDLOAD(glDisable); ++void glDepthFunc (GLenum func) ++{ ++ (*_glDepthFunc)(func); ++} --void glDisable (GLenum cap) --{ -- return (*_glDisable)(cap); --} -+GLES2_IDLOAD(glDrawArrays); +-GLES2_IDLOAD(glDisableVertexAttribArray); ++void glDepthMask (GLboolean flag) ++{ ++ (*_glDepthMask)(flag); ++} --void glDisableVertexAttribArray (GLuint index) --{ -- return (*_glDisableVertexAttribArray)(index); --} -+GLES2_IDLOAD(glDrawElements); +-GLES2_IDLOAD(glDrawArrays); ++void glDepthRangef (GLclampf zNear, GLclampf zFar) ++{ ++ (*_glDepthRangef)(zNear, zFar); ++} --void glDrawArrays (GLenum mode, GLint first, GLsizei count) --{ -- return (*_glDrawArrays)(mode, first, count); --} -+GLES2_IDLOAD(glEnable); +-GLES2_IDLOAD(glDrawElements); ++void glDetachShader (GLuint program, GLuint shader) ++{ ++ (*_glDetachShader)(program, shader); ++} --void glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) --{ -- return (*_glDrawElements)(mode, count, type, indices); --} -+GLES2_IDLOAD(glEnableVertexAttribArray); +-GLES2_IDLOAD(glEnable); ++void glDisable (GLenum cap) ++{ ++ (*_glDisable)(cap); ++} --void glEnable (GLenum cap) --{ -- return (*_glEnable)(cap); --} -+GLES2_IDLOAD(glFinish); +-GLES2_IDLOAD(glEnableVertexAttribArray); ++void glDisableVertexAttribArray (GLuint index) ++{ ++ (*_glDisableVertexAttribArray)(index); ++} --void glEnableVertexAttribArray (GLuint index) --{ -- return (*_glEnableVertexAttribArray)(index); --} -+GLES2_IDLOAD(glFlush); +-GLES2_IDLOAD(glFinish); ++void glDrawArrays (GLenum mode, GLint first, GLsizei count) ++{ ++ (*_glDrawArrays)(mode, first, count); ++} --void glFinish (void) --{ -- return (*_glFinish)(); --} -+GLES2_IDLOAD(glFramebufferRenderbuffer); +-GLES2_IDLOAD(glFlush); ++void glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) ++{ ++ (*_glDrawElements)(mode, count, type, indices); ++} --void glFlush (void) --{ -- return (*_glFlush)(); --} -+GLES2_IDLOAD(glFramebufferTexture2D); +-GLES2_IDLOAD(glFramebufferRenderbuffer); ++void glEnable (GLenum cap) ++{ ++ (*_glEnable)(cap); ++} --void glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) --{ -- return (*_glFramebufferRenderbuffer)(target, attachment, renderbuffertarget, renderbuffer); --} -+GLES2_IDLOAD(glFrontFace); +-GLES2_IDLOAD(glFramebufferTexture2D); ++void glEnableVertexAttribArray (GLuint index) ++{ ++ (*_glEnableVertexAttribArray)(index); ++} --void glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) --{ -- return (*_glFramebufferTexture2D)(target, attachment, textarget, texture, level); --} -+GLES2_IDLOAD(glGenBuffers); +-GLES2_IDLOAD(glFrontFace); ++void glFinish (void) ++{ ++ (*_glFinish)(); ++} --void glFrontFace (GLenum mode) --{ -- return (*_glFrontFace)(mode); --} -+GLES2_IDLOAD(glGenerateMipmap); +-GLES2_IDLOAD(glGenBuffers); ++void glFlush (void) ++{ ++ (*_glFlush)(); ++} --void glGenBuffers (GLsizei n, GLuint* buffers) --{ -- return (*_glGenBuffers)(n, buffers); --} -+GLES2_IDLOAD(glGenFramebuffers); +-GLES2_IDLOAD(glGenerateMipmap); ++void glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) ++{ ++ (*_glFramebufferRenderbuffer)(target, attachment, renderbuffertarget, renderbuffer); ++} --void glGenerateMipmap (GLenum target) --{ -- return (*_glGenerateMipmap)(target); --} -+GLES2_IDLOAD(glGenRenderbuffers); +-GLES2_IDLOAD(glGenFramebuffers); ++void glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) ++{ ++ (*_glFramebufferTexture2D)(target, attachment, textarget, texture, level); ++} --void glGenFramebuffers (GLsizei n, GLuint* framebuffers) --{ -- return (*_glGenFramebuffers)(n, framebuffers); --} -+GLES2_IDLOAD(glGenTextures); +-GLES2_IDLOAD(glGenRenderbuffers); ++void glFrontFace (GLenum mode) ++{ ++ (*_glFrontFace)(mode); ++} --void glGenRenderbuffers (GLsizei n, GLuint* renderbuffers) --{ -- return (*_glGenRenderbuffers)(n, renderbuffers); --} -+GLES2_IDLOAD(glGetActiveAttrib); +-GLES2_IDLOAD(glGenTextures); ++void glGenBuffers (GLsizei n, GLuint* buffers) ++{ ++ (*_glGenBuffers)(n, buffers); ++} --void glGenTextures (GLsizei n, GLuint* textures) --{ -- return (*_glGenTextures)(n, textures); --} -+GLES2_IDLOAD(glGetActiveUniform); +-GLES2_IDLOAD(glGetActiveAttrib); ++void glGenerateMipmap (GLenum target) ++{ ++ (*_glGenerateMipmap)(target); ++} --void glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) --{ -- return (*_glGetActiveAttrib)(program, index, bufsize, length, size, type, name); --} -+GLES2_IDLOAD(glGetAttachedShaders); +-GLES2_IDLOAD(glGetActiveUniform); ++void glGenFramebuffers (GLsizei n, GLuint* framebuffers) ++{ ++ (*_glGenFramebuffers)(n, framebuffers); ++} --void glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) --{ -- return (*_glGetActiveUniform)(program, index, bufsize, length, size, type, name); --} -+GLES2_IDLOAD(glGetAttribLocation); +-GLES2_IDLOAD(glGetAttachedShaders); ++void glGenRenderbuffers (GLsizei n, GLuint* renderbuffers) ++{ ++ (*_glGenRenderbuffers)(n, renderbuffers); ++} --void glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) --{ -- return (*_glGetAttachedShaders)(program, maxcount, count, shaders); --} -+GLES2_IDLOAD(glGetBooleanv); +-GLES2_IDLOAD(glGetAttribLocation); ++void glGenTextures (GLsizei n, GLuint* textures) ++{ ++ (*_glGenTextures)(n, textures); ++} --int glGetAttribLocation (GLuint program, const GLchar* name) --{ -- return (*_glGetAttribLocation)(program, name); --} -+GLES2_IDLOAD(glGetBufferParameteriv); +-GLES2_IDLOAD(glGetBooleanv); ++void glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) ++{ ++ (*_glGetActiveAttrib)(program, index, bufsize, length, size, type, name); ++} --void glGetBooleanv (GLenum pname, GLboolean* params) --{ -- return (*_glGetBooleanv)(pname, params); --} -+GLES2_IDLOAD(glGetError); +-GLES2_IDLOAD(glGetBufferParameteriv); ++void glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) ++{ ++ (*_glGetActiveUniform)(program, index, bufsize, length, size, type, name); ++} --void glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params) --{ -- return (*_glGetBufferParameteriv)(target, pname, params); --} -+GLES2_IDLOAD(glGetFloatv); +-GLES2_IDLOAD(glGetError); ++void glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) ++{ ++ (*_glGetAttachedShaders)(program, maxcount, count, shaders); ++} --GLenum glGetError (void) --{ -- return (*_glGetError)(); --} -+GLES2_IDLOAD(glGetFramebufferAttachmentParameteriv); +-GLES2_IDLOAD(glGetFloatv); ++int glGetAttribLocation (GLuint program, const GLchar* name) ++{ ++ (*_glGetAttribLocation)(program, name); ++} --void glGetFloatv (GLenum pname, GLfloat* params) --{ -- return (*_glGetFloatv)(pname, params); --} -+GLES2_IDLOAD(glGetIntegerv); +-GLES2_IDLOAD(glGetFramebufferAttachmentParameteriv); ++void glGetBooleanv (GLenum pname, GLboolean* params) ++{ ++ (*_glGetBooleanv)(pname, params); ++} --void glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params) --{ -- return (*_glGetFramebufferAttachmentParameteriv)(target, attachment, pname, params); --} -+GLES2_IDLOAD(glGetProgramiv); +-GLES2_IDLOAD(glGetIntegerv); ++void glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params) ++{ ++ (*_glGetBufferParameteriv)(target, pname, params); ++} --void glGetIntegerv (GLenum pname, GLint* params) --{ -- return (*_glGetIntegerv)(pname, params); --} -+GLES2_IDLOAD(glGetProgramInfoLog); +-GLES2_IDLOAD(glGetProgramiv); ++GLenum glGetError (void) ++{ ++ return (*_glGetError)(); ++} --void glGetProgramiv (GLuint program, GLenum pname, GLint* params) --{ -- return (*_glGetProgramiv)(program, pname, params); --} -+GLES2_IDLOAD(glGetRenderbufferParameteriv); +-GLES2_IDLOAD(glGetProgramInfoLog); ++void glGetFloatv (GLenum pname, GLfloat* params) ++{ ++ (*_glGetFloatv)(pname, params); ++} --void glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog) --{ -- return (*_glGetProgramInfoLog)(program, bufsize, length, infolog); --} -+GLES2_IDLOAD(glGetShaderiv); +-GLES2_IDLOAD(glGetRenderbufferParameteriv); ++void glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params) ++{ ++ (*_glGetFramebufferAttachmentParameteriv)(target, attachment, pname, params); ++} --void glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params) --{ -- return (*_glGetRenderbufferParameteriv)(target, pname, params); --} -+GLES2_IDLOAD(glGetShaderInfoLog); +-GLES2_IDLOAD(glGetShaderiv); ++void glGetIntegerv (GLenum pname, GLint* params) ++{ ++ (*_glGetIntegerv)(pname, params); ++} --void glGetShaderiv (GLuint shader, GLenum pname, GLint* params) --{ -- return (*_glGetShaderiv)(shader, pname, params); --} -+GLES2_IDLOAD(glGetShaderPrecisionFormat); +-GLES2_IDLOAD(glGetShaderInfoLog); ++void glGetProgramiv (GLuint program, GLenum pname, GLint* params) ++{ ++ (*_glGetProgramiv)(program, pname, params); ++} --void glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog) --{ -- return (*_glGetShaderInfoLog)(shader, bufsize, length, infolog); --} -+GLES2_IDLOAD(glGetShaderSource); +-GLES2_IDLOAD(glGetShaderPrecisionFormat); ++void glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog) ++{ ++ (*_glGetProgramInfoLog)(program, bufsize, length, infolog); ++} --void glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) --{ -- return (*_glGetShaderPrecisionFormat)(shadertype, precisiontype, range, precision); --} -+GLES2_IDLOAD(glGetString); +-GLES2_IDLOAD(glGetShaderSource); ++void glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params) ++{ ++ (*_glGetRenderbufferParameteriv)(target, pname, params); ++} --void glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) --{ -- return (*_glGetShaderSource)(shader, bufsize, length, source); --} -+GLES2_IDLOAD(glGetTexParameterfv); +-GLES2_IDLOAD(glGetString); ++void glGetShaderiv (GLuint shader, GLenum pname, GLint* params) ++{ ++ (*_glGetShaderiv)(shader, pname, params); ++} --const GLubyte* glGetString (GLenum name) --{ -- return (*_glGetString)(name); --} -+GLES2_IDLOAD(glGetTexParameteriv); +-GLES2_IDLOAD(glGetTexParameterfv); ++void glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog) ++{ ++ (*_glGetShaderInfoLog)(shader, bufsize, length, infolog); ++} --void glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params) --{ -- return (*_glGetTexParameterfv)(target, pname, params); --} -+GLES2_IDLOAD(glGetUniformfv); +-GLES2_IDLOAD(glGetTexParameteriv); ++void glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) ++{ ++ (*_glGetShaderPrecisionFormat)(shadertype, precisiontype, range, precision); ++} --void glGetTexParameteriv (GLenum target, GLenum pname, GLint* params) --{ -- return (*_glGetTexParameteriv)(target, pname, params); --} -+GLES2_IDLOAD(glGetUniformiv); +-GLES2_IDLOAD(glGetUniformfv); ++void glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) ++{ ++ (*_glGetShaderSource)(shader, bufsize, length, source); ++} --void glGetUniformfv (GLuint program, GLint location, GLfloat* params) --{ -- return (*_glGetUniformfv)(program, location, params); --} -+GLES2_IDLOAD(glGetUniformLocation); +-GLES2_IDLOAD(glGetUniformiv); ++const GLubyte* glGetString (GLenum name) ++{ ++ // Return 2.0 even though drivers might actually support 3.0 or higher, ++ // because libhybris does not provide any 3.0+ symbols. ++ if (name == GL_VERSION) { ++ static GLubyte glGetString_versionString[64]; ++ snprintf(glGetString_versionString, sizeof(glGetString_versionString), "OpenGL ES 2.0 (%s)", (*_glGetString)(name)); ++ return glGetString_versionString; ++ } --void glGetUniformiv (GLuint program, GLint location, GLint* params) --{ -- return (*_glGetUniformiv)(program, location, params); --} -+GLES2_IDLOAD(glGetVertexAttribfv); +-GLES2_IDLOAD(glGetUniformLocation); ++ (*_glGetString)(name); ++} --int glGetUniformLocation (GLuint program, const GLchar* name) --{ -- return (*_glGetUniformLocation)(program, name); --} -+GLES2_IDLOAD(glGetVertexAttribiv); +-GLES2_IDLOAD(glGetVertexAttribfv); ++void glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params) ++{ ++ (*_glGetTexParameterfv)(target, pname, params); ++} --void glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params) --{ -- return (*_glGetVertexAttribfv)(index, pname, params); --} -+GLES2_IDLOAD(glGetVertexAttribPointerv); +-GLES2_IDLOAD(glGetVertexAttribiv); ++void glGetTexParameteriv (GLenum target, GLenum pname, GLint* params) ++{ ++ (*_glGetTexParameteriv)(target, pname, params); ++} --void glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params) --{ -- return (*_glGetVertexAttribiv)(index, pname, params); --} -+GLES2_IDLOAD(glHint); +-GLES2_IDLOAD(glGetVertexAttribPointerv); ++void glGetUniformfv (GLuint program, GLint location, GLfloat* params) ++{ ++ (*_glGetUniformfv)(program, location, params); ++} --void glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer) --{ -- return (*_glGetVertexAttribPointerv)(index, pname, pointer); --} -+GLES2_IDLOAD(glIsBuffer); +-GLES2_IDLOAD(glHint); ++void glGetUniformiv (GLuint program, GLint location, GLint* params) ++{ ++ (*_glGetUniformiv)(program, location, params); ++} --void glHint (GLenum target, GLenum mode) --{ -- return (*_glHint)(target, mode); --} -+GLES2_IDLOAD(glIsEnabled); +-GLES2_IDLOAD(glIsBuffer); ++int glGetUniformLocation (GLuint program, const GLchar* name) ++{ ++ (*_glGetUniformLocation)(program, name); ++} --GLboolean glIsBuffer (GLuint buffer) --{ -- return (*_glIsBuffer)(buffer); --} -+GLES2_IDLOAD(glIsFramebuffer); +-GLES2_IDLOAD(glIsEnabled); ++void glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params) ++{ ++ (*_glGetVertexAttribfv)(index, pname, params); ++} --GLboolean glIsEnabled (GLenum cap) --{ -- return (*_glIsEnabled)(cap); --} -+GLES2_IDLOAD(glIsProgram); +-GLES2_IDLOAD(glIsFramebuffer); ++void glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params) ++{ ++ (*_glGetVertexAttribiv)(index, pname, params); ++} --GLboolean glIsFramebuffer (GLuint framebuffer) --{ -- return (*_glIsFramebuffer)(framebuffer); --} -+GLES2_IDLOAD(glIsRenderbuffer); +-GLES2_IDLOAD(glIsProgram); ++void glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer) ++{ ++ (*_glGetVertexAttribPointerv)(index, pname, pointer); ++} --GLboolean glIsProgram (GLuint program) --{ -- return (*_glIsProgram)(program); --} -+GLES2_IDLOAD(glIsShader); +-GLES2_IDLOAD(glIsRenderbuffer); ++void glHint (GLenum target, GLenum mode) ++{ ++ (*_glHint)(target, mode); ++} --GLboolean glIsRenderbuffer (GLuint renderbuffer) --{ -- return (*_glIsRenderbuffer)(renderbuffer); --} -+GLES2_IDLOAD(glIsTexture); +-GLES2_IDLOAD(glIsShader); ++GLboolean glIsBuffer (GLuint buffer) ++{ ++ return (*_glIsBuffer)(buffer); ++} --GLboolean glIsShader (GLuint shader) --{ -- return (*_glIsShader)(shader); --} -+GLES2_IDLOAD(glLinkProgram); +-GLES2_IDLOAD(glIsTexture); ++GLboolean glIsEnabled (GLenum cap) ++{ ++ return (*_glIsEnabled)(cap); ++} --GLboolean glIsTexture (GLuint texture) --{ -- return (*_glIsTexture)(texture); --} -+GLES2_IDLOAD(glPixelStorei); +-GLES2_IDLOAD(glLinkProgram); ++GLboolean glIsFramebuffer (GLuint framebuffer) ++{ ++ return (*_glIsFramebuffer)(framebuffer); ++} --void glLineWidth (GLfloat width) --{ -- return (*_glLineWidth)(width); --} -+GLES2_IDLOAD(glReadPixels); +-GLES2_IDLOAD(glPixelStorei); ++GLboolean glIsProgram (GLuint program) ++{ ++ return (*_glIsProgram)(program); ++} --void glLinkProgram (GLuint program) --{ -- return (*_glLinkProgram)(program); --} -+GLES2_IDLOAD(glReleaseShaderCompiler); +-GLES2_IDLOAD(glReadPixels); ++GLboolean glIsRenderbuffer (GLuint renderbuffer) ++{ ++ return (*_glIsRenderbuffer)(renderbuffer); ++} --void glPixelStorei (GLenum pname, GLint param) --{ -- return (*_glPixelStorei)(pname, param); --} -+GLES2_IDLOAD(glRenderbufferStorage); +-GLES2_IDLOAD(glReleaseShaderCompiler); ++GLboolean glIsShader (GLuint shader) ++{ ++ return (*_glIsShader)(shader); ++} --void glPolygonOffset (GLfloat factor, GLfloat units) --{ -- return (*_glPolygonOffset)(factor, units); --} -+GLES2_IDLOAD(glScissor); +-GLES2_IDLOAD(glRenderbufferStorage); ++GLboolean glIsTexture (GLuint texture) ++{ ++ return (*_glIsTexture)(texture); ++} --void glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) --{ -- return (*_glReadPixels)(x, y, width, height, format, type, pixels); -+GLES2_IDLOAD(glShaderBinary); +-GLES2_IDLOAD(glScissor); ++void glLineWidth (GLfloat width) ++{ ++ (*_glLineWidth)(width); ++} --} -+GLES2_IDLOAD(glShaderSource); +-GLES2_IDLOAD(glShaderBinary); ++void glLinkProgram (GLuint program) ++{ ++ (*_glLinkProgram)(program); ++} --void glReleaseShaderCompiler (void) --{ -- return (*_glReleaseShaderCompiler)(); --} -+GLES2_IDLOAD(glStencilFunc); +-GLES2_IDLOAD(glShaderSource); ++void glPixelStorei (GLenum pname, GLint param) ++{ ++ (*_glPixelStorei)(pname, param); ++} --void glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height) --{ -- return (*_glRenderbufferStorage)(target, internalformat, width, height); --} -+GLES2_IDLOAD(glStencilFuncSeparate); +-GLES2_IDLOAD(glStencilFunc); ++void glPolygonOffset (GLfloat factor, GLfloat units) ++{ ++ (*_glPolygonOffset)(factor, units); ++} --void glSampleCoverage (GLclampf value, GLboolean invert) --{ -- return (*_glSampleCoverage)(value, invert); --} -+GLES2_IDLOAD(glStencilMask); +-GLES2_IDLOAD(glStencilFuncSeparate); ++void glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) ++{ ++ (*_glReadPixels)(x, y, width, height, format, type, pixels); --void glScissor (GLint x, GLint y, GLsizei width, GLsizei height) --{ -- return (*_glScissor)(x, y, width, height); --} -+GLES2_IDLOAD(glStencilMaskSeparate); +-GLES2_IDLOAD(glStencilMask); ++} --void glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length) --{ -- return (*_glShaderBinary)(n, shaders, binaryformat, binary, length); --} -+GLES2_IDLOAD(glStencilOp); +-GLES2_IDLOAD(glStencilMaskSeparate); ++void glReleaseShaderCompiler (void) ++{ ++ (*_glReleaseShaderCompiler)(); ++} --void glShaderSource (GLuint shader, GLsizei count, const GLchar** string, const GLint* length) --{ -- return (*_glShaderSource)(shader, count, string, length); --} -+GLES2_IDLOAD(glStencilOpSeparate); +-GLES2_IDLOAD(glStencilOp); ++void glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height) ++{ ++ (*_glRenderbufferStorage)(target, internalformat, width, height); ++} --void glStencilFunc (GLenum func, GLint ref, GLuint mask) --{ -- return (*_glStencilFunc)(func, ref, mask); --} -+GLES2_IDLOAD(glTexImage2D); +-GLES2_IDLOAD(glStencilOpSeparate); ++void glSampleCoverage (GLclampf value, GLboolean invert) ++{ ++ (*_glSampleCoverage)(value, invert); ++} --void glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask) --{ -- return (*_glStencilFuncSeparate)(face, func, ref, mask); --} -+GLES2_IDLOAD(glTexParameterfv); +-GLES2_IDLOAD(glTexImage2D); ++void glScissor (GLint x, GLint y, GLsizei width, GLsizei height) ++{ ++ (*_glScissor)(x, y, width, height); ++} --void glStencilMask (GLuint mask) --{ -- return (*_glStencilMask)(mask); --} -+GLES2_IDLOAD(glTexParameteri); +-GLES2_IDLOAD(glTexParameterfv); ++void glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length) ++{ ++ (*_glShaderBinary)(n, shaders, binaryformat, binary, length); ++} --void glStencilMaskSeparate (GLenum face, GLuint mask) --{ -- return (*_glStencilMaskSeparate)(face, mask); --} -+GLES2_IDLOAD(glTexParameteriv); +-GLES2_IDLOAD(glTexParameteri); ++void glShaderSource (GLuint shader, GLsizei count, const GLchar** string, const GLint* length) ++{ ++ (*_glShaderSource)(shader, count, string, length); ++} --void glStencilOp (GLenum fail, GLenum zfail, GLenum zpass) --{ -- return (*_glStencilOp)(fail, zfail, zpass); --} -+GLES2_IDLOAD(glTexSubImage2D); +-GLES2_IDLOAD(glTexParameteriv); ++void glStencilFunc (GLenum func, GLint ref, GLuint mask) ++{ ++ (*_glStencilFunc)(func, ref, mask); ++} --void glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass) --{ -- return (*_glStencilOpSeparate)(face, fail, zfail, zpass); --} -+GLES2_IDLOAD(glUniform1fv); +-GLES2_IDLOAD(glTexSubImage2D); ++void glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask) ++{ ++ (*_glStencilFuncSeparate)(face, func, ref, mask); ++} --void glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels) --{ -- return (*_glTexImage2D)(target, level, internalformat, width, height, border, format, type, pixels); --} -+GLES2_IDLOAD(glUniform1i); +-GLES2_IDLOAD(glUniform1fv); ++void glStencilMask (GLuint mask) ++{ ++ (*_glStencilMask)(mask); ++} --void glTexParameterf (GLenum target, GLenum pname, GLfloat param) --{ -- return (*_glTexParameterf)(target, pname, param); --} -+GLES2_IDLOAD(glUniform1iv); +-GLES2_IDLOAD(glUniform1i); ++void glStencilMaskSeparate (GLenum face, GLuint mask) ++{ ++ (*_glStencilMaskSeparate)(face, mask); ++} --void glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params) --{ -- return (*_glTexParameterfv)(target, pname, params); --} -+GLES2_IDLOAD(glUniform2fv); +-GLES2_IDLOAD(glUniform1iv); ++void glStencilOp (GLenum fail, GLenum zfail, GLenum zpass) ++{ ++ (*_glStencilOp)(fail, zfail, zpass); ++} --void glTexParameteri (GLenum target, GLenum pname, GLint param) --{ -- return (*_glTexParameteri)(target, pname, param); --} -+GLES2_IDLOAD(glUniform2i); +-GLES2_IDLOAD(glUniform2fv); ++void glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass) ++{ ++ (*_glStencilOpSeparate)(face, fail, zfail, zpass); ++} --void glTexParameteriv (GLenum target, GLenum pname, const GLint* params) --{ -- return (*_glTexParameteriv)(target, pname, params); --} -+GLES2_IDLOAD(glUniform2iv); +-GLES2_IDLOAD(glUniform2i); ++void glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels) ++{ ++ (*_glTexImage2D)(target, level, internalformat, width, height, border, format, type, pixels); ++} --void glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) --{ -- return (*_glTexSubImage2D)(target, level, xoffset, yoffset, width, height, format, type, pixels); --} -+GLES2_IDLOAD(glUniform3fv); +-GLES2_IDLOAD(glUniform2iv); ++void glTexParameterf (GLenum target, GLenum pname, GLfloat param) ++{ ++ (*_glTexParameterf)(target, pname, param); ++} --void glUniform1f (GLint location, GLfloat x) --{ -- return (*_glUniform1f)(location, x); --} -+GLES2_IDLOAD(glUniform3i); +-GLES2_IDLOAD(glUniform3fv); ++void glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params) ++{ ++ (*_glTexParameterfv)(target, pname, params); ++} --void glUniform1fv (GLint location, GLsizei count, const GLfloat* v) --{ -- return (*_glUniform1fv)(location, count, v); --} -+GLES2_IDLOAD(glUniform3iv); +-GLES2_IDLOAD(glUniform3i); ++void glTexParameteri (GLenum target, GLenum pname, GLint param) ++{ ++ (*_glTexParameteri)(target, pname, param); ++} --void glUniform1i (GLint location, GLint x) --{ -- return (*_glUniform1i)(location, x); --} -+GLES2_IDLOAD(glUniform4fv); +-GLES2_IDLOAD(glUniform3iv); ++void glTexParameteriv (GLenum target, GLenum pname, const GLint* params) ++{ ++ (*_glTexParameteriv)(target, pname, params); ++} --void glUniform1iv (GLint location, GLsizei count, const GLint* v) --{ -- return (*_glUniform1iv)(location, count, v); --} -+GLES2_IDLOAD(glUniform4i); +-GLES2_IDLOAD(glUniform4fv); ++void glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) ++{ ++ (*_glTexSubImage2D)(target, level, xoffset, yoffset, width, height, format, type, pixels); ++} --void glUniform2f (GLint location, GLfloat x, GLfloat y) --{ -- return (*_glUniform2f)(location, x, y); --} -+GLES2_IDLOAD(glUniform4iv); +-GLES2_IDLOAD(glUniform4i); ++void glUniform1f (GLint location, GLfloat x) ++{ ++ (*_glUniform1f)(location, x); ++} --void glUniform2fv (GLint location, GLsizei count, const GLfloat* v) --{ -- return (*_glUniform2fv)(location, count, v); --} -+GLES2_IDLOAD(glUniformMatrix2fv); +-GLES2_IDLOAD(glUniform4iv); ++void glUniform1fv (GLint location, GLsizei count, const GLfloat* v) ++{ ++ (*_glUniform1fv)(location, count, v); ++} --void glUniform2i (GLint location, GLint x, GLint y) --{ -- return (*_glUniform2i)(location, x, y); --} -+GLES2_IDLOAD(glUniformMatrix3fv); +-GLES2_IDLOAD(glUniformMatrix2fv); ++void glUniform1i (GLint location, GLint x) ++{ ++ (*_glUniform1i)(location, x); ++} --void glUniform2iv (GLint location, GLsizei count, const GLint* v) --{ -- return (*_glUniform2iv)(location, count, v); --} -+GLES2_IDLOAD(glUniformMatrix4fv); +-GLES2_IDLOAD(glUniformMatrix3fv); ++void glUniform1iv (GLint location, GLsizei count, const GLint* v) ++{ ++ (*_glUniform1iv)(location, count, v); ++} --void glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z) --{ -- return (*_glUniform3f)(location, x, y, z); --} -+GLES2_IDLOAD(glUseProgram); +-GLES2_IDLOAD(glUniformMatrix4fv); ++void glUniform2f (GLint location, GLfloat x, GLfloat y) ++{ ++ (*_glUniform2f)(location, x, y); ++} --void glUniform3fv (GLint location, GLsizei count, const GLfloat* v) --{ -- return (*_glUniform3fv)(location, count, v); --} -+GLES2_IDLOAD(glValidateProgram); +-GLES2_IDLOAD(glUseProgram); ++void glUniform2fv (GLint location, GLsizei count, const GLfloat* v) ++{ ++ (*_glUniform2fv)(location, count, v); ++} --void glUniform3i (GLint location, GLint x, GLint y, GLint z) --{ -- return (*_glUniform3i)(location, x, y, z); --} -+GLES2_IDLOAD(glVertexAttrib1fv); +-GLES2_IDLOAD(glValidateProgram); ++void glUniform2i (GLint location, GLint x, GLint y) ++{ ++ (*_glUniform2i)(location, x, y); ++} --void glUniform3iv (GLint location, GLsizei count, const GLint* v) --{ -- return (*_glUniform3iv)(location, count, v); --} -+GLES2_IDLOAD(glVertexAttrib2fv); +-GLES2_IDLOAD(glVertexAttrib1fv); ++void glUniform2iv (GLint location, GLsizei count, const GLint* v) ++{ ++ (*_glUniform2iv)(location, count, v); ++} --void glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) --{ -- return (*_glUniform4f)(location, x, y, z, w); --} -+GLES2_IDLOAD(glVertexAttrib3fv); +-GLES2_IDLOAD(glVertexAttrib2fv); ++void glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z) ++{ ++ (*_glUniform3f)(location, x, y, z); ++} --void glUniform4fv (GLint location, GLsizei count, const GLfloat* v) --{ -- return (*_glUniform4fv)(location, count, v); --} -+GLES2_IDLOAD(glVertexAttrib4fv); +-GLES2_IDLOAD(glVertexAttrib3fv); ++void glUniform3fv (GLint location, GLsizei count, const GLfloat* v) ++{ ++ (*_glUniform3fv)(location, count, v); ++} --void glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w) --{ -- return (*_glUniform4i)(location, x, y, z, w); --} -+GLES2_IDLOAD(glVertexAttribPointer); +-GLES2_IDLOAD(glVertexAttrib4fv); ++void glUniform3i (GLint location, GLint x, GLint y, GLint z) ++{ ++ (*_glUniform3i)(location, x, y, z); ++} --void glUniform4iv (GLint location, GLsizei count, const GLint* v) --{ -- return (*_glUniform4iv)(location, count, v); --} -+GLES2_IDLOAD(glViewport); +-GLES2_IDLOAD(glVertexAttribPointer); ++void glUniform3iv (GLint location, GLsizei count, const GLint* v) ++{ ++ (*_glUniform3iv)(location, count, v); ++} --void glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) --{ -- return (*_glUniformMatrix2fv)(location, count, transpose, value); --} -+GLES2_IDLOAD(glEGLImageTargetTexture2DOES); +-GLES2_IDLOAD(glViewport); ++void glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) ++{ ++ (*_glUniform4f)(location, x, y, z, w); ++} --void glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) -+void glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) +-void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) ++void glUniform4fv (GLint location, GLsizei count, const GLfloat* v) { -- return (*_glUniformMatrix3fv)(location, count, transpose, value); -+ return (*_glBlendColor)(red, green, blue, alpha); +- struct egl_image *img = image; +- return (*_glEGLImageTargetTexture2DOES)(target, img ? img->egl_image : NULL); ++ (*_glUniform4fv)(location, count, v); } --void glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) -+void glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +-void glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) ++void glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w) { -- return (*_glUniformMatrix4fv)(location, count, transpose, value); -+ return (*_glVertexAttrib4f)(indx, x, y, z, w); +- return (*_glBlendColor)(red, green, blue, alpha); ++ (*_glUniform4i)(location, x, y, z, w); } --void glUseProgram (GLuint program) -+void glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y) +-void glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) ++void glUniform4iv (GLint location, GLsizei count, const GLint* v) { -- return (*_glUseProgram)(program); -+ return (*_glVertexAttrib2f)(indx, x, y); +- return (*_glVertexAttrib4f)(indx, x, y, z, w); ++ (*_glUniform4iv)(location, count, v); } --void glValidateProgram (GLuint program) -+void glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z) +-void glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y) ++void glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { -- return (*_glValidateProgram)(program); -+ return (*_glVertexAttrib3f)(indx, x, y, z); +- return (*_glVertexAttrib2f)(indx, x, y); ++ (*_glUniformMatrix2fv)(location, count, transpose, value); } -+ - void glVertexAttrib1f (GLuint indx, GLfloat x) +-void glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z) ++void glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) { - return (*_glVertexAttrib1f)(indx, x); +- return (*_glVertexAttrib3f)(indx, x, y, z); ++ (*_glUniformMatrix3fv)(location, count, transpose, value); } --void glVertexAttrib1fv (GLuint indx, const GLfloat* values) -+void glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) ++void glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) ++{ ++ (*_glUniformMatrix4fv)(location, count, transpose, value); ++} + +-void glVertexAttrib1f (GLuint indx, GLfloat x) ++void glUseProgram (GLuint program) { -- return (*_glVertexAttrib1fv)(indx, values); -+ return (*_glUniform4f)(location, x, y, z, w); +- return (*_glVertexAttrib1f)(indx, x); ++ (*_glUseProgram)(program); } --void glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y) -+void glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z) +-void glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) ++void glValidateProgram (GLuint program) { -- return (*_glVertexAttrib2f)(indx, x, y); -+ return (*_glUniform3f)(location, x, y, z); +- return (*_glUniform4f)(location, x, y, z, w); ++ (*_glValidateProgram)(program); } --void glVertexAttrib2fv (GLuint indx, const GLfloat* values) -+void glUniform2f (GLint location, GLfloat x, GLfloat y) +-void glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z) ++void glVertexAttrib1f (GLuint indx, GLfloat x) { -- return (*_glVertexAttrib2fv)(indx, values); -+ return (*_glUniform2f)(location, x, y); +- return (*_glUniform3f)(location, x, y, z); ++ (*_glVertexAttrib1f)(indx, x); } --void glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z) -+void glUniform1f (GLint location, GLfloat x) +-void glUniform2f (GLint location, GLfloat x, GLfloat y) ++void glVertexAttrib1fv (GLuint indx, const GLfloat* values) { -- return (*_glVertexAttrib3f)(indx, x, y, z); -+ return (*_glUniform1f)(location, x); +- return (*_glUniform2f)(location, x, y); ++ (*_glVertexAttrib1fv)(indx, values); } --void glVertexAttrib3fv (GLuint indx, const GLfloat* values) -+void glTexParameterf (GLenum target, GLenum pname, GLfloat param) +-void glUniform1f (GLint location, GLfloat x) ++void glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y) { -- return (*_glVertexAttrib3fv)(indx, values); -+ return (*_glTexParameterf)(target, pname, param); +- return (*_glUniform1f)(location, x); ++ (*_glVertexAttrib2f)(indx, x, y); } --void glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) -+void glSampleCoverage (GLclampf value, GLboolean invert) +-void glTexParameterf (GLenum target, GLenum pname, GLfloat param) ++void glVertexAttrib2fv (GLuint indx, const GLfloat* values) { -- return (*_glVertexAttrib4f)(indx, x, y, z, w); -+ return (*_glSampleCoverage)(value, invert); +- return (*_glTexParameterf)(target, pname, param); ++ (*_glVertexAttrib2fv)(indx, values); } -- --void glVertexAttrib4fv (GLuint indx, const GLfloat* values) -+void glPolygonOffset (GLfloat factor, GLfloat units) + +-void glSampleCoverage (GLclampf value, GLboolean invert) ++void glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z) { -- return (*_glVertexAttrib4fv)(indx, values); -+ return (*_glPolygonOffset)(factor, units); +- return (*_glSampleCoverage)(value, invert); ++ (*_glVertexAttrib3f)(indx, x, y, z); } -- --void glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) -+void glDepthRangef (GLclampf zNear, GLclampf zFar) +-void glPolygonOffset (GLfloat factor, GLfloat units) ++ ++void glVertexAttrib3fv (GLuint indx, const GLfloat* values) { -- return (*_glVertexAttribPointer)(indx, size, type, normalized, stride, ptr); -+ return (*_glDepthRangef)(zNear, zFar); +- return (*_glPolygonOffset)(factor, units); ++ (*_glVertexAttrib3fv)(indx, values); } - --void glViewport (GLint x, GLint y, GLsizei width, GLsizei height) +-void glDepthRangef (GLclampf zNear, GLclampf zFar) + -+void glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) ++void glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { -- return (*_glViewport)(x, y, width, height); -+ return (*_glClearColor)(red, green, blue, alpha); +- return (*_glDepthRangef)(zNear, zFar); ++ (*_glVertexAttrib4f)(indx, x, y, z, w); } --void glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image) -+void glClearDepthf (GLclampf depth) - { -- (*_glEGLImageTargetTexture2DOES)(target, image); -+ return (*_glClearDepthf)(depth); -+} -+void glLineWidth (GLfloat width) ++void glVertexAttrib4fv (GLuint indx, const GLfloat* values) +{ -+ return (*_glLineWidth)(width); ++ (*_glVertexAttrib4fv)(indx, values); ++} + +-void glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) ++void glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) + { +- return (*_glClearColor)(red, green, blue, alpha); ++ (*_glVertexAttribPointer)(indx, size, type, normalized, stride, ptr); } +-void glClearDepthf (GLclampf depth) ++void glViewport (GLint x, GLint y, GLsizei width, GLsizei height) + { +- return (*_glClearDepthf)(depth); ++ (*_glViewport)(x, y, width, height); + } +-void glLineWidth (GLfloat width) ++ ++void glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image) + { +- return (*_glLineWidth)(width); ++ (*_glEGLImageTargetTexture2DOES)(target, image); + } ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/hardware/hardware.c -+++ libhybris-0.1.0+git20131207+e452e83/hybris/hardware/hardware.c -@@ -17,6 +17,7 @@ +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/hardware/hardware.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/hardware/hardware.c +@@ -18,6 +18,7 @@ + #include #include #include +#include - #include - #include + #include + #include -@@ -26,15 +27,20 @@ static int (*_hw_get_module)(const char +@@ -27,15 +28,20 @@ static int (*_hw_get_module)(const char static int (*_hw_get_module_by_class)(const char *class_id, const char *inst, const struct hw_module_t **module) = NULL; @@ -11520,9 +25257,9 @@ -static void _init_lib_hardware() +static void *_init_lib_hardware() { -- _libhardware = (void *) android_dlopen("/system/lib/libhardware.so", RTLD_LAZY); +- _libhardware = (void *) android_dlopen("libhardware.so", RTLD_LAZY); + if (!_libhardware) -+ _libhardware = (void *) android_dlopen("/system/lib/libhardware.so", RTLD_LAZY); ++ _libhardware = (void *) android_dlopen("libhardware.so", RTLD_LAZY); + return _libhardware; } @@ -11534,7 +25271,7 @@ HARDWARE_DLSYM(&_hw_get_module, "hw_get_module"); return (*_hw_get_module)(id, module); } -@@ -42,6 +48,9 @@ int hw_get_module(const char *id, const +@@ -43,6 +49,9 @@ int hw_get_module(const char *id, const int hw_get_module_by_class(const char *class_id, const char *inst, const struct hw_module_t **module) { @@ -11544,9 +25281,9 @@ HARDWARE_DLSYM(&_hw_get_module_by_class, "hw_get_module_by_class"); return (*_hw_get_module_by_class)(class_id, inst, module); } ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/include/Makefile.am -+++ libhybris-0.1.0+git20131207+e452e83/hybris/include/Makefile.am -@@ -65,6 +65,16 @@ propertiesincludedir = $(includedir)/hyb +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/include/Makefile.am ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/Makefile.am +@@ -65,6 +65,20 @@ propertiesincludedir = $(includedir)/hyb propertiesinclude_HEADERS = \ hybris/properties/properties.h @@ -11558,13 +25295,72 @@ + hybris/media/media_format_layer.h \ + hybris/media/media_recorder_layer.h \ + hybris/media/surface_texture_client_hybris.h \ -+ hybris/media/recorder_compatibility_layer.h ++ hybris/media/recorder_compatibility_layer.h \ ++ hybris/media/media_codec_source_layer.h \ ++ hybris/media/media_message_layer.h \ ++ hybris/media/media_buffer_layer.h \ ++ hybris/media/media_meta_data_layer.h + dlfcnincludedir = $(includedir)/hybris/dlfcn dlfcninclude_HEADERS = \ hybris/dlfcn/dlfcn.h ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/include/hybris/camera/camera_compatibility_layer_capabilities.h -+++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/camera/camera_compatibility_layer_capabilities.h +@@ -73,4 +87,5 @@ commonincludedir = $(includedir)/hybris/ + commoninclude_HEADERS = \ + hybris/common/binding.h \ + hybris/common/floating_point_abi.h \ +- hybris/common/dlfcn.h ++ hybris/common/dlfcn.h \ ++ hybris/common/hooks.h +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/include/hybris/camera/camera_compatibility_layer.h ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/camera/camera_compatibility_layer.h +@@ -37,6 +37,12 @@ extern "C" { + FRONT_FACING_CAMERA_TYPE + } CameraType; + ++ typedef enum ++ { ++ PREVIEW_CALLBACK_DISABLED, ++ PREVIEW_CALLBACK_ENABLED ++ } PreviewCallbackMode; ++ + struct CameraControl; + + typedef void (*on_msg_error)(void* context); +@@ -47,6 +53,7 @@ extern "C" { + typedef void (*on_data_raw_image)(void* data, uint32_t data_size, void* context); + typedef void (*on_data_compressed_image)(void* data, uint32_t data_size, void* context); + typedef void (*on_preview_texture_needs_update)(void* context); ++ typedef void (*on_preview_frame)(void* data, uint32_t data_size, void* context); + + struct CameraControlListener + { +@@ -73,10 +80,14 @@ extern "C" { + on_preview_texture_needs_update on_preview_texture_needs_update_cb; + + void* context; ++ ++ // Called when there is a new preview frame ++ on_preview_frame on_preview_frame_cb; + }; + + // Initializes a connection to the camera, returns NULL on error. + struct CameraControl* android_camera_connect_to(CameraType camera_type, struct CameraControlListener* listener); ++ struct CameraControl* android_camera_connect_by_id(int32_t camera_id, struct CameraControlListener* listener); + + // Disconnects the camera and deletes the pointer + void android_camera_disconnect(struct CameraControl* control); +@@ -135,6 +146,9 @@ extern "C" { + // completed. Ideally, this is done from the raw data callback. + void android_camera_take_snapshot(struct CameraControl* control); + ++ // Enable or disable the preview callback for clients that want software frames ++ int android_camera_set_preview_callback_mode(struct CameraControl* control, PreviewCallbackMode mode); ++ + #ifdef __cplusplus + } + #endif +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/include/hybris/camera/camera_compatibility_layer_capabilities.h ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/camera/camera_compatibility_layer_capabilities.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Canonical Ltd @@ -11592,8 +25388,12 @@ } SceneMode; typedef enum -@@ -95,6 +97,8 @@ extern "C" { - } FocusRegion; +@@ -92,28 +94,36 @@ extern "C" { + int bottom; + int right; + int weight; +- } FocusRegion; ++ } FocusRegion, MeteringRegion; typedef void (*size_callback)(void* ctx, int width, int height); + typedef void (*scene_mode_callback)(void* ctx, SceneMode mode); @@ -11601,7 +25401,11 @@ // Dumps the camera parameters to stdout. void android_camera_dump_parameters(struct CameraControl* control); -@@ -105,15 +109,20 @@ extern "C" { + + // Query camera parameters + int android_camera_get_number_of_devices(); ++ int android_camera_get_device_info(int32_t camera_id, int* facing, int* orientation); + void android_camera_enumerate_supported_preview_sizes(struct CameraControl* control, size_callback cb, void* ctx); void android_camera_get_preview_fps_range(struct CameraControl* control, int* min, int* max); void android_camera_get_preview_fps(struct CameraControl* control, int* fps); void android_camera_enumerate_supported_picture_sizes(struct CameraControl* control, size_callback cb, void* ctx); @@ -11622,7 +25426,7 @@ void android_camera_get_scene_mode(struct CameraControl* control, SceneMode* mode); void android_camera_get_auto_focus_mode(struct CameraControl* control, AutoFocusMode* mode); void android_camera_get_preview_format(struct CameraControl* control, CameraPixelFormat* format); -@@ -122,18 +131,21 @@ extern "C" { +@@ -122,18 +132,24 @@ extern "C" { void android_camera_set_preview_size(struct CameraControl* control, int width, int height); void android_camera_set_preview_fps(struct CameraControl* control, int fps); void android_camera_set_picture_size(struct CameraControl* control, int width, int height); @@ -11638,14 +25442,17 @@ void android_camera_set_focus_region(struct CameraControl* control, FocusRegion* region); void android_camera_reset_focus_region(struct CameraControl* control); ++ void android_camera_set_metering_region(struct CameraControl* control, MeteringRegion* region); ++ void android_camera_reset_metering_region(struct CameraControl* control); ++ // Set photo metadata void android_camera_set_rotation(struct CameraControl* control, int rotation); + void android_camera_set_location(struct CameraControl* control, const float* latitude, const float* longitude, const float* altitude, int timestamp, const char* method); // Video support void android_camera_enumerate_supported_video_sizes(struct CameraControl* control, size_callback cb, void* ctx); ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/include/hybris/camera/camera_compatibility_layer_configuration_translator.h -+++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/camera/camera_compatibility_layer_configuration_translator.h +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/include/hybris/camera/camera_compatibility_layer_configuration_translator.h ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/camera/camera_compatibility_layer_configuration_translator.h @@ -96,6 +96,7 @@ extern "C" { m.add(android::String8(android::CameraParameters::FLASH_MODE_AUTO), FLASH_MODE_AUTO); m.add(android::String8(android::CameraParameters::FLASH_MODE_ON), FLASH_MODE_ON); @@ -11683,8 +25490,96 @@ static const char* auto_focus_modes[] = { ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/include/hybris/input/input_stack_compatibility_layer.h -+++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/input/input_stack_compatibility_layer.h +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/include/hybris/common/binding.h ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/common/binding.h +@@ -32,7 +32,6 @@ const char *android_dlerror(void); + int android_dladdr(const void *addr, void *info); + + +- + /** + * XXX AUTO-GENERATED FILE XXX + * +@@ -41,7 +40,7 @@ int android_dladdr(const void *addr, voi + * an updated version of this header file: + * + * python utils/generate_wrapper_macros.py > \ +- * hybris/include/hybris/common/binding.h ++ * hybris/include/hybris/internal/binding.h + * + * If you need macros with more arguments, just customize the + * MAX_ARGS variable in generate_wrapper_macros.py. +@@ -65,6 +64,12 @@ int android_dladdr(const void *addr, voi + name##_handle = android_dlopen(path, RTLD_LAZY); \ + } + ++#define HYBRIS_LIRBARY_CHECK_SYMBOL(name) \ ++ bool hybris_##name##_check_for_symbol(const char *sym) \ ++ { \ ++ return android_dlsym(name##_handle, sym) != NULL; \ ++ } ++ + + + #define HYBRIS_IMPLEMENT_FUNCTION0(name, return_type, symbol) \ +@@ -435,7 +440,7 @@ int android_dladdr(const void *addr, voi + * an updated version of this header file: + * + * python utils/generate_wrapper_macros.py > \ +- * hybris/include/hybris/common/binding.h ++ * hybris/include/hybris/internal/binding.h + * + * If you need macros with more arguments, just customize the + * MAX_ARGS variable in generate_wrapper_macros.py. +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/include/hybris/common/dlfcn.h ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/common/dlfcn.h +@@ -25,7 +25,7 @@ extern "C" { + void *hybris_dlopen(const char *filename, int flag); + void *hybris_dlsym(void *handle, const char *symbol); + int hybris_dlclose(void *handle); +-char *hybris_dlerror(void); ++const char *hybris_dlerror(void); + + #ifdef __cplusplus + } +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/common/hooks.h +@@ -0,0 +1,33 @@ ++/* ++ * Copyright (c) 2016 Canonical Ltd ++ * ++ * 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 _HYBRIS_HOOKS_H_ ++#define _HYBRIS_HOOKS_H_ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++typedef void* (*hybris_hook_cb)(const char *symbol_name, const char *requester); ++ ++void hybris_set_hook_callback(hybris_hook_cb callback); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/include/hybris/input/input_stack_compatibility_layer.h ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/input/input_stack_compatibility_layer.h @@ -109,6 +109,7 @@ extern "C" { int input_area_height; }; @@ -11693,8 +25588,8 @@ void android_input_stack_initialize( struct AndroidEventListener* listener, struct InputStackConfiguration* input_stack_configuration); ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/include/hybris/internal/camera_control.h -+++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/internal/camera_control.h +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/include/hybris/internal/camera_control.h ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/internal/camera_control.h @@ -19,7 +19,11 @@ #include @@ -11707,7 +25602,7 @@ #include #include -@@ -31,15 +35,22 @@ extern "C" { +@@ -31,16 +35,27 @@ extern "C" { struct CameraControlListener; struct CameraControl : public android::CameraListener, @@ -11729,11 +25624,16 @@ + android::sp preview_texture; +#endif + // From android::SurfaceTexture/GLConsumer::FrameAvailableListener ++#if ANDROID_VERSION_MAJOR==5 && ANDROID_VERSION_MINOR>=1 || ANDROID_VERSION_MAJOR>=6 ++ void onFrameAvailable(const android::BufferItem& item); ++#else void onFrameAvailable(); ++#endif // From android::CameraListener ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/include/hybris/internal/surface_flinger_compatibility_layer_internal.h -+++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/internal/surface_flinger_compatibility_layer_internal.h + void notify(int32_t msg_type, int32_t ext1, int32_t ext2); +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/include/hybris/internal/surface_flinger_compatibility_layer_internal.h ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/internal/surface_flinger_compatibility_layer_internal.h @@ -25,6 +25,7 @@ #include @@ -11743,7 +25643,7 @@ #include #include --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/media/decoding_service.h ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/media/decoding_service.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2014 Canonical Ltd @@ -11785,8 +25685,81 @@ + +#endif --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/media/media_codec_layer.h -@@ -0,0 +1,102 @@ ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/media/media_buffer_layer.h +@@ -0,0 +1,70 @@ ++/* ++ * Copyright (C) 2016 Canonical Ltd ++ * ++ * 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. ++ * ++ * Authored by: Simon Fels ++ */ ++ ++#ifndef MEDIA_BUFFER_LAYER_H_ ++#define MEDIA_BUFFER_LAYER_H_ ++ ++#include ++#include ++ ++#include ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++typedef void MediaBufferWrapper; ++typedef void (*MediaBufferReturnCallback)(MediaBufferWrapper *buffer, void *user_data); ++ ++MediaBufferWrapper* media_buffer_create(size_t size); ++void media_buffer_destroy(MediaBufferWrapper *buffer); ++void media_buffer_release(MediaBufferWrapper *buffer); ++void media_buffer_ref(MediaBufferWrapper *buffer); ++ ++int media_buffer_get_refcount(MediaBufferWrapper *buffer); ++ ++void* media_buffer_get_data(MediaBufferWrapper *buffer); ++size_t media_buffer_get_size(MediaBufferWrapper *buffer); ++size_t media_buffer_get_range_offset(MediaBufferWrapper *buffer); ++size_t media_buffer_get_range_length(MediaBufferWrapper *buffer); ++MediaMetaDataWrapper* media_buffer_get_meta_data(MediaBufferWrapper *buffer); ++ ++void media_buffer_set_return_callback(MediaBufferWrapper *buffer, ++ MediaBufferReturnCallback callback, void *user_data); ++ ++typedef void MediaABufferWrapper; ++ ++MediaABufferWrapper* media_abuffer_create(size_t capacity); ++MediaABufferWrapper* media_abuffer_create_with_data(uint8_t *data, size_t size); ++ ++void media_abuffer_set_range(MediaABufferWrapper *buffer, size_t offset, size_t size); ++void media_abuffer_set_media_buffer_base(MediaABufferWrapper *buffer, MediaBufferWrapper *mbuf); ++MediaBufferWrapper* media_abuffer_get_media_buffer_base(MediaABufferWrapper *buffer); ++ ++void* media_abuffer_get_data(MediaABufferWrapper *buffer); ++size_t media_abuffer_get_size(MediaABufferWrapper *buffer); ++size_t media_abuffer_get_range_offset(MediaABufferWrapper *buffer); ++size_t media_abuffer_get_capacity(MediaABufferWrapper *buffer); ++MediaMessageWrapper* media_abuffer_get_meta(MediaABufferWrapper *buffer); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/media/media_codec_layer.h +@@ -0,0 +1,107 @@ +/* + * Copyright (C) 2013 Canonical Ltd + * @@ -11815,6 +25788,8 @@ +#include +#endif + ++#include ++#include +#include +#include + @@ -11859,8 +25834,11 @@ + int media_codec_stop(MediaCodecDelegate delegate); + int media_codec_release(MediaCodecDelegate delegate); + int media_codec_flush(MediaCodecDelegate delegate); ++ + size_t media_codec_get_input_buffers_size(MediaCodecDelegate delegate); + uint8_t *media_codec_get_nth_input_buffer(MediaCodecDelegate delegate, size_t n); ++ MediaABufferWrapper* media_codec_get_nth_input_buffer_as_abuffer(MediaCodecDelegate delegate, size_t n); ++ + size_t media_codec_get_nth_input_buffer_capacity(MediaCodecDelegate delegate, size_t n); + size_t media_codec_get_output_buffers_size(MediaCodecDelegate delegate); + uint8_t *media_codec_get_nth_output_buffer(MediaCodecDelegate delegate, size_t n); @@ -11890,7 +25868,7 @@ + +#endif // MEDIA_CODEC_LAYER_H_ --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/media/media_codec_list.h ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/media/media_codec_list.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2013 Canonical Ltd @@ -11913,44 +25891,124 @@ +#ifndef MEDIA_CODEC_LIST_PRIV_H_ +#define MEDIA_CODEC_LIST_PRIV_H_ + -+#include -+#include -+#include ++#include ++#include ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++ ssize_t media_codec_list_find_codec_by_type(const char *type, bool encoder, size_t startIndex); ++ ssize_t media_codec_list_find_codec_by_name(const char *name); ++ size_t media_codec_list_count_codecs(); ++ void media_codec_list_get_codec_info_at_id(size_t index); ++ const char *media_codec_list_get_codec_name(size_t index); ++ bool media_codec_list_is_encoder(size_t index); ++ size_t media_codec_list_get_num_supported_types(size_t index); ++ size_t media_codec_list_get_nth_supported_type_len(size_t index, size_t n); ++ int media_codec_list_get_nth_supported_type(size_t index, char *type, size_t n); ++ ++ struct _profile_level ++ { ++ uint32_t profile; ++ uint32_t level; ++ }; ++ typedef struct _profile_level profile_level; ++ ++ size_t media_codec_list_get_num_profile_levels(size_t index, const char*); ++ size_t media_codec_list_get_num_color_formats(size_t index, const char*); ++ int media_codec_list_get_nth_codec_profile_level(size_t index, const char *type, profile_level *pro_level, size_t n); ++ int media_codec_list_get_codec_color_formats(size_t index, const char *type, uint32_t *color_formats); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif // MEDIA_CODEC_LIST_PRIV_H_ +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/media/media_codec_source_layer.h +@@ -0,0 +1,77 @@ ++/* ++ * Copyright (C) 2016 Canonical Ltd ++ * ++ * 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. ++ * ++ * Authored by: Simon Fels ++ */ ++ ++#ifndef MEDIA_CODEC_SOURCE_LAYER_H_ ++#define MEDIA_CODEC_SOURCE_LAYER_H_ ++ ++#include ++ ++#include ++#include ++#include ++#include + +#ifdef __cplusplus +extern "C" { +#endif + -+ ssize_t media_codec_list_find_codec_by_type(const char *type, bool encoder, size_t startIndex); -+ ssize_t media_codec_list_find_codec_by_name(const char *name); -+ size_t media_codec_list_count_codecs(); -+ void media_codec_list_get_codec_info_at_id(size_t index); -+ const char *media_codec_list_get_codec_name(size_t index); -+ bool media_codec_list_is_encoder(size_t index); -+ size_t media_codec_list_get_num_supported_types(size_t index); -+ size_t media_codec_list_get_nth_supported_type_len(size_t index, size_t n); -+ int media_codec_list_get_nth_supported_type(size_t index, char *type, size_t n); ++typedef void MediaSourceWrapper; + -+ struct _profile_level -+ { -+ uint32_t profile; -+ uint32_t level; -+ }; -+ typedef struct _profile_level profile_level; ++typedef int (*MediaSourceStartCallback)(MediaMetaDataWrapper *meta, void *user_data); ++typedef int (*MediaSourceStopCallback)(void *user_data); ++typedef int (*MediaSourceReadCallback)(MediaBufferWrapper **buffer, void *user_data); ++typedef int (*MediaSourcePauseCallback)(void *user_data); ++ ++MediaSourceWrapper* media_source_create(void); ++void media_source_release(MediaSourceWrapper *source); ++void media_source_set_format(MediaSourceWrapper *source, MediaMetaDataWrapper *meta); ++void media_source_set_start_callback(MediaSourceWrapper *source, MediaSourceStartCallback callback, void *user_data); ++void media_source_set_stop_callback(MediaSourceWrapper *source, MediaSourceStopCallback callback, void *user_data); ++void media_source_set_read_callback(MediaSourceWrapper *source, MediaSourceReadCallback callback, void *user_data); ++void media_source_set_pause_callback(MediaSourceWrapper *source, MediaSourcePauseCallback callback, void *user_data); + -+ size_t media_codec_list_get_num_profile_levels(size_t index, const char*); -+ size_t media_codec_list_get_num_color_formats(size_t index, const char*); -+ int media_codec_list_get_nth_codec_profile_level(size_t index, const char *type, profile_level *pro_level, size_t n); -+ int media_codec_list_get_codec_color_formats(size_t index, const char *type, uint32_t *color_formats); ++enum MediaCodecSourceFlags ++{ ++ MEDIA_CODEC_SOURCE_FLAG_USE_SURFACE_INPUT = 1, ++ MEDIA_CODEC_SOURCE_FLAG_USE_METADATA_INPUT = 2, ++}; ++ ++typedef void MediaCodecSourceWrapper; ++typedef void MediaNativeWindowHandle; ++ ++MediaCodecSourceWrapper* media_codec_source_create(MediaMessageWrapper *format, MediaSourceWrapper *source, int flags); ++void media_codec_source_release(MediaCodecSourceWrapper *source); ++ ++MediaNativeWindowHandle* media_codec_source_get_native_window_handle(MediaCodecSourceWrapper *source); ++ ++// Returned instance is owned by the caller and must be freed ++MediaMetaDataWrapper* media_codec_source_get_format(MediaCodecSourceWrapper *source); ++ ++bool media_codec_source_start(MediaCodecSourceWrapper *source); ++bool media_codec_source_stop(MediaCodecSourceWrapper *source); ++bool media_codec_source_pause(MediaCodecSourceWrapper *source); ++ ++bool media_codec_source_read(MediaCodecSourceWrapper *source, MediaBufferWrapper **buffer); ++ ++bool media_codec_source_request_idr_frame(MediaBufferWrapper *source); + +#ifdef __cplusplus +} +#endif + -+#endif // MEDIA_CODEC_LIST_PRIV_H_ ++#endif --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/media/media_compatibility_layer.h -@@ -0,0 +1,75 @@ ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/media/media_compatibility_layer.h +@@ -0,0 +1,77 @@ +/* + * Copyright (C) 2013 Canonical Ltd + * @@ -11985,6 +26043,8 @@ + // Common compat calls + int media_compat_check_availability(); + ++ unsigned int hybris_media_get_version(); ++ + // Callback types + typedef void (*on_msg_set_video_size)(int height, int width, void *context); + typedef void (*on_video_texture_needs_update)(void *context); @@ -12027,7 +26087,7 @@ + +#endif // MEDIA_COMPATIBILITY_LAYER_H_ --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/media/media_format_layer.h ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/media/media_format_layer.h @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2013 Canonical Ltd @@ -12088,7 +26148,139 @@ + +#endif // MEDIA_FORMAT_LAYER_H_ --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/media/media_recorder_layer.h ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/media/media_message_layer.h +@@ -0,0 +1,57 @@ ++/* ++ * Copyright (C) 2016 Canonical Ltd ++ * ++ * 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. ++ * ++ * Authored by: Simon Fels ++ */ ++ ++#ifndef MEDIA_MESSAGE_LAYER_H_ ++#define MEDIA_MESSAGE_LAYER_H_ ++ ++#include ++ ++#include ++#include ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++typedef void MediaMessageWrapper; ++ ++MediaMessageWrapper* media_message_create(); ++void media_message_release(MediaMessageWrapper *msg); ++ ++void media_message_clear(MediaMessageWrapper *msg); ++const char* media_message_dump(MediaMessageWrapper *msg); ++ ++void media_message_set_int32(MediaMessageWrapper *msg, const char *name, int32_t value); ++void media_message_set_int64(MediaMessageWrapper *msg, const char *name, int64_t value); ++void media_message_set_size(MediaMessageWrapper *msg, const char *name, size_t value); ++void media_message_set_float(MediaMessageWrapper *msg, const char *name, float value); ++void media_message_set_double(MediaMessageWrapper *msg, const char *name, double value); ++void media_message_set_string(MediaMessageWrapper *msg, const char *name, const char *value, ssize_t len); ++ ++bool media_message_find_int32(MediaMessageWrapper *msg, const char *name, int32_t *value); ++bool media_message_find_int64(MediaMessageWrapper *msg, const char *name, int64_t *value); ++bool media_message_find_size(MediaMessageWrapper *msg, const char *name, size_t *value); ++bool media_message_find_float(MediaMessageWrapper *msg, const char *name, float *value); ++bool media_message_find_double(MediaMessageWrapper *msg, const char *name, double *value); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/media/media_meta_data_layer.h +@@ -0,0 +1,69 @@ ++/* ++ * Copyright (C) 2016 Canonical Ltd ++ * ++ * 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. ++ * ++ * Authored by: Simon Fels ++ */ ++ ++#ifndef MEDIA_META_DATA_LAYER_H_ ++#define MEDIA_META_DATA_LAYER_H_ ++ ++#include ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++typedef void MediaMetaDataWrapper; ++ ++enum { ++ MEDIA_META_DATA_KEY_TIME = 1, ++ MEDIA_META_DATA_KEY_IS_CODEC_CONFIG = 2, ++ MEDIA_META_DATA_KEY_MIME = 3, ++ MEDIA_META_DATA_KEY_NUM_BUFFERS = 4, ++ MEDIA_META_DATA_KEY_WIDTH = 5, ++ MEDIA_META_DATA_KEY_HEIGHT = 6, ++ MEDIA_META_DATA_KEY_STRIDE = 7, ++ MEDIA_META_DATA_KEY_COLOR_FORMAT = 8, ++ MEDIA_META_DATA_KEY_SLICE_HEIGHT = 9, ++ MEDIA_META_DATA_KEY_FRAMERATE = 10, ++ MEDIA_META_DATA_KEY_MEDIA_BUFFER = 11 ++}; ++ ++uint32_t media_meta_data_get_key_id(int key); ++ ++MediaMetaDataWrapper* media_meta_data_create(); ++void media_meta_data_release(MediaMetaDataWrapper *meta_data); ++ ++void media_meta_data_clear(MediaMetaDataWrapper *meta_data); ++bool media_meta_data_remove(MediaMetaDataWrapper *meta_data, uint32_t key); ++ ++bool media_meta_data_set_cstring(MediaMetaDataWrapper *meta_data, uint32_t key, const char *value); ++bool media_meta_data_set_int32(MediaMetaDataWrapper *meta_data, uint32_t key, int32_t value); ++bool media_meta_data_set_int64(MediaMetaDataWrapper *meta_data, uint32_t key, int64_t value); ++bool media_meta_data_set_float(MediaMetaDataWrapper *meta_data, uint32_t key, float value); ++bool media_meta_data_set_pointer(MediaMetaDataWrapper *meta_data, uint32_t key, void *value); ++ ++bool media_meta_data_find_cstring(MediaMetaDataWrapper *meta_data, uint32_t key, const char **value); ++bool media_meta_data_find_int32(MediaMetaDataWrapper *meta_data, uint32_t key, int32_t *value); ++bool media_meta_data_find_int64(MediaMetaDataWrapper *meta_data, uint32_t key, int64_t *value); ++bool media_meta_data_find_float(MediaMetaDataWrapper *meta_data, uint32_t key, float *value); ++bool media_meta_data_find_double(MediaMetaDataWrapper *meta_data, uint32_t key, double *value); ++bool media_meta_data_find_pointer(MediaMetaDataWrapper *meta_data, uint32_t key, void **value); ++ ++#ifdef __cplusplus ++} ++#endif ++ ++#endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/media/media_recorder_layer.h @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2013-2014 Canonical Ltd @@ -12232,7 +26424,7 @@ + +#endif --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/media/recorder_compatibility_layer.h ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/media/recorder_compatibility_layer.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2013 Canonical Ltd @@ -12361,7 +26553,7 @@ + +#endif --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/media/surface_texture_client_hybris.h ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/media/surface_texture_client_hybris.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2013 Canonical Ltd @@ -12441,8 +26633,8 @@ +#endif + +#endif // SURFACE_TEXTURE_CLIENT_HYBRIS_H_ ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/include/hybris/ui/ui_compatibility_layer.h -+++ libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/ui/ui_compatibility_layer.h +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/include/hybris/ui/ui_compatibility_layer.h ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/ui/ui_compatibility_layer.h @@ -50,8 +50,10 @@ extern "C" { void* graphic_buffer_get_native_buffer(struct graphic_buffer *buffer); @@ -12454,9 +26646,14 @@ int graphic_buffer_init_check(struct graphic_buffer *buffer); ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/input/is.c -+++ libhybris-0.1.0+git20131207+e452e83/hybris/input/is.c -@@ -28,6 +28,14 @@ +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/input/is.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/input/is.c +@@ -24,10 +24,18 @@ + #include + #include + +-#define COMPAT_LIBRARY_PATH "/system/lib/libis_compat_layer.so" ++#define COMPAT_LIBRARY_PATH "libis_compat_layer.so" HYBRIS_LIBRARY_INITIALIZE(is, COMPAT_LIBRARY_PATH); @@ -12471,8 +26668,30 @@ HYBRIS_IMPLEMENT_VOID_FUNCTION2(is, android_input_stack_initialize, struct AndroidEventListener*, struct InputStackConfiguration*); HYBRIS_IMPLEMENT_VOID_FUNCTION0(is, android_input_stack_start); +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/libnfc_ndef_nxp/libnfc_ndef_nxp.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/libnfc_ndef_nxp/libnfc_ndef_nxp.c +@@ -34,7 +34,7 @@ + + #include + +-HYBRIS_LIBRARY_INITIALIZE(libnfc_ndef_so, "/system/lib/libnfc_ndef.so"); ++HYBRIS_LIBRARY_INITIALIZE(libnfc_ndef_so, "libnfc_ndef.so"); + + HYBRIS_IMPLEMENT_FUNCTION5(libnfc_ndef_so, NFCSTATUS, phFriNfc_NdefRecord_GetRecords, uint8_t *, uint32_t, uint8_t **, uint8_t *, uint32_t *); + HYBRIS_IMPLEMENT_FUNCTION1(libnfc_ndef_so, uint32_t, phFriNfc_NdefRecord_GetLength, phFriNfc_NdefRecord_t *); +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/libnfc_nxp/libnfc_nxp.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/libnfc_nxp/libnfc_nxp.c +@@ -56,7 +56,7 @@ typedef void (*pphDal4Nfc_DeferFuncPoi + + #include + +-HYBRIS_LIBRARY_INITIALIZE(libnfc_so, "/system/lib/libnfc.so"); ++HYBRIS_LIBRARY_INITIALIZE(libnfc_so, "libnfc.so"); + + HYBRIS_IMPLEMENT_FUNCTION2(libnfc_so, NFCSTATUS, phLibNfc_Mgt_ConfigureDriver, pphLibNfc_sConfig_t, void **); + HYBRIS_IMPLEMENT_FUNCTION2(libnfc_so, NFCSTATUS, phDal4Nfc_Config, pphDal4Nfc_sConfig_t, void **); --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/hybris/media/Makefile.am ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/media/Makefile.am @@ -0,0 +1,17 @@ +lib_LTLIBRARIES = \ + libmedia.la @@ -12492,7 +26711,7 @@ +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libmedia.pc --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/hybris/media/libmedia.pc.in ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/media/libmedia.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=${prefix} @@ -12505,8 +26724,8 @@ +Libs: -L${libdir} -lhybris-common -lmedia +Cflags: -I${includedir} --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/hybris/media/media.c -@@ -0,0 +1,302 @@ ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/media/media.c +@@ -0,0 +1,442 @@ +/* + * Copyright (C) 2013-2014 Canonical Ltd + * @@ -12531,7 +26750,7 @@ +#include +#include + -+#include ++#include +#include +#include +#include @@ -12539,8 +26758,10 @@ +#include +#include +#include ++#include ++#include + -+#define COMPAT_LIBRARY_PATH "/system/lib/libmedia_compat_layer.so" ++#define COMPAT_LIBRARY_PATH "libmedia_compat_layer.so" + +#ifdef __ARM_PCS_VFP +#define FP_ATTRIB __attribute__((pcs("aapcs"))) @@ -12557,6 +26778,20 @@ + return media_handle ? 1 : 0; +} + ++unsigned int hybris_media_get_version() ++{ ++ static unsigned int (*f)() FP_ATTRIB = NULL; ++ HYBRIS_DLSYSM(media, &f, "hybris_media_get_version"); ++ ++ /* When the method is not available we return zero here ++ * rather than crashing to indicate the client the ++ * Android side implementation is not versioned yet. */ ++ if (!f) ++ return 0; ++ ++ return f(); ++} ++ +HYBRIS_IMPLEMENT_FUNCTION0(media, struct MediaPlayerWrapper*, + android_media_new_player); +HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, android_media_update_surface_texture, @@ -12809,20 +27044,431 @@ + struct MediaRecorderWrapper*, on_recorder_msg_error, void*); +HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, android_recorder_set_audio_read_cb, + struct MediaRecorderWrapper*, on_recorder_read_audio, void*); ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/tests/Makefile.am -+++ libhybris-0.1.0+git20131207+e452e83/hybris/tests/Makefile.am ++ ++// Media Message ++HYBRIS_IMPLEMENT_FUNCTION0(media, MediaMessageWrapper*, media_message_create); ++HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_message_release, MediaMessageWrapper*); ++HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_message_clear, MediaMessageWrapper*); ++HYBRIS_IMPLEMENT_FUNCTION1(media, const char*, media_message_dump, MediaMessageWrapper*); ++HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, media_message_set_int32, MediaMessageWrapper*, ++ const char*, int32_t); ++HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, media_message_set_int64, MediaMessageWrapper*, ++ const char*, int64_t); ++HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, media_message_set_size, MediaMessageWrapper*, ++ const char*, size_t); ++HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, media_message_set_float, MediaMessageWrapper*, ++ const char*, float); ++HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, media_message_set_double, MediaMessageWrapper*, ++ const char*, double); ++HYBRIS_IMPLEMENT_VOID_FUNCTION4(media, media_message_set_string, MediaMessageWrapper*, ++ const char*, const char*, ssize_t); ++HYBRIS_IMPLEMENT_FUNCTION2(media, bool, media_message_contains, MediaMessageWrapper*, ++ const char*); ++HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_message_find_int32, MediaMessageWrapper*, ++ const char*, int32_t*); ++HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_message_find_int64, MediaMessageWrapper*, ++ const char*, int64_t*); ++HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_message_find_size, MediaMessageWrapper*, ++ const char*, size_t*); ++HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_message_find_float, MediaMessageWrapper*, ++ const char*, float*); ++HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_message_find_double, MediaMessageWrapper*, ++ const char*, double*); ++ ++// Media Meta Data ++HYBRIS_IMPLEMENT_FUNCTION1(media, uint32_t, media_meta_data_get_key_id, int); ++HYBRIS_IMPLEMENT_FUNCTION0(media, MediaMetaDataWrapper*, media_meta_data_create); ++HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_meta_data_release, MediaMetaDataWrapper*); ++HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_meta_data_clear, MediaMetaDataWrapper*); ++HYBRIS_IMPLEMENT_FUNCTION2(media, bool, media_meta_data_remove, MediaMetaDataWrapper*, ++ uint32_t); ++HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_meta_data_set_cstring, MediaMetaDataWrapper*, ++ uint32_t, const char*); ++HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_meta_data_set_int32, MediaMetaDataWrapper*, ++ uint32_t, int32_t); ++HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_meta_data_set_int64, MediaMetaDataWrapper*, ++ uint32_t, int64_t); ++HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_meta_data_set_float, MediaMetaDataWrapper*, ++ uint32_t, float); ++HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_meta_data_set_pointer, MediaMetaDataWrapper*, ++ uint32_t, void*); ++HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_meta_data_find_cstring, MediaMetaDataWrapper*, ++ uint32_t, const char**); ++HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_meta_data_find_int32, MediaMetaDataWrapper*, ++ uint32_t, int32_t*); ++HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_meta_data_find_int64, MediaMetaDataWrapper*, ++ uint32_t, int64_t*); ++HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_meta_data_find_float, MediaMetaDataWrapper*, ++ uint32_t, float*); ++HYBRIS_IMPLEMENT_FUNCTION3(media, bool, media_meta_data_find_pointer, MediaMetaDataWrapper*, ++ uint32_t, void**); ++ ++// Media Buffer ++HYBRIS_IMPLEMENT_FUNCTION1(media, MediaBufferWrapper*, media_buffer_create, size_t); ++HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_buffer_destroy, MediaBufferWrapper*); ++HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_buffer_release, MediaBufferWrapper*); ++HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_buffer_ref, MediaBufferWrapper*); ++HYBRIS_IMPLEMENT_FUNCTION1(media, int, media_buffer_get_refcount, MediaBufferWrapper*); ++HYBRIS_IMPLEMENT_FUNCTION1(media, void*, media_buffer_get_data, MediaBufferWrapper*); ++HYBRIS_IMPLEMENT_FUNCTION1(media, size_t, media_buffer_get_size, MediaBufferWrapper*); ++HYBRIS_IMPLEMENT_FUNCTION1(media, size_t, media_buffer_get_range_offset, MediaBufferWrapper*); ++HYBRIS_IMPLEMENT_FUNCTION1(media, size_t, media_buffer_get_range_length, MediaBufferWrapper*); ++HYBRIS_IMPLEMENT_FUNCTION1(media, MediaMetaDataWrapper*, media_buffer_get_meta_data, MediaBufferWrapper*); ++HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, media_buffer_set_return_callback, MediaBufferWrapper*, ++ MediaBufferReturnCallback, void*); ++ ++// Media ABuffer ++HYBRIS_IMPLEMENT_FUNCTION1(media, MediaABufferWrapper*, media_abuffer_create, ++ size_t); ++HYBRIS_IMPLEMENT_FUNCTION2(media, MediaABufferWrapper*, media_abuffer_create_with_data, ++ uint8_t*, size_t); ++HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, media_abuffer_set_range, ++ MediaABufferWrapper*, size_t, size_t); ++HYBRIS_IMPLEMENT_VOID_FUNCTION2(media, media_abuffer_set_media_buffer_base, ++ MediaABufferWrapper*, MediaBufferWrapper*); ++HYBRIS_IMPLEMENT_FUNCTION1(media, MediaBufferWrapper*, media_abuffer_get_media_buffer_base, ++ MediaABufferWrapper*); ++HYBRIS_IMPLEMENT_FUNCTION1(media, void*, media_abuffer_get_data, ++ MediaABufferWrapper*); ++HYBRIS_IMPLEMENT_FUNCTION1(media, size_t, media_abuffer_get_size, ++ MediaABufferWrapper*); ++HYBRIS_IMPLEMENT_FUNCTION1(media, size_t, media_abuffer_get_range_offset, ++ MediaABufferWrapper*); ++HYBRIS_IMPLEMENT_FUNCTION1(media, size_t, media_abuffer_get_capacity, ++ MediaABufferWrapper*); ++HYBRIS_IMPLEMENT_FUNCTION1(media, MediaMessageWrapper*, media_abuffer_get_meta, ++ MediaABufferWrapper*); ++ ++// Media Codec Source ++HYBRIS_IMPLEMENT_FUNCTION3(media, MediaCodecSourceWrapper*, media_codec_source_create, ++ MediaMessageWrapper*, MediaSourceWrapper*, int); ++HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_codec_source_release, MediaCodecSourceWrapper*); ++HYBRIS_IMPLEMENT_FUNCTION1(media, void*, media_codec_source_get_native_window_handle, ++ MediaCodecSourceWrapper*); ++HYBRIS_IMPLEMENT_FUNCTION1(media, MediaMetaDataWrapper*, media_codec_source_get_format, ++ MediaCodecSourceWrapper*); ++HYBRIS_IMPLEMENT_FUNCTION1(media, bool, media_codec_source_start, MediaCodecSourceWrapper*); ++HYBRIS_IMPLEMENT_FUNCTION1(media, bool, media_codec_source_stop, MediaCodecSourceWrapper*); ++HYBRIS_IMPLEMENT_FUNCTION1(media, bool, media_codec_source_pause, MediaCodecSourceWrapper*); ++HYBRIS_IMPLEMENT_FUNCTION2(media, bool, media_codec_source_read, MediaCodecSourceWrapper*, ++ MediaBufferWrapper**); ++HYBRIS_IMPLEMENT_FUNCTION1(media, bool, media_codec_source_request_idr_frame, ++ MediaCodecSourceWrapper*); ++ ++// Media Source ++HYBRIS_IMPLEMENT_FUNCTION0(media, MediaSourceWrapper*, media_source_create); ++HYBRIS_IMPLEMENT_VOID_FUNCTION1(media, media_source_release, MediaSourceWrapper*); ++HYBRIS_IMPLEMENT_VOID_FUNCTION2(media, media_source_set_format, MediaSourceWrapper*, ++ MediaMetaDataWrapper*); ++HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, media_source_set_start_callback, ++ MediaSourceWrapper*, MediaSourceStartCallback, void*); ++HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, media_source_set_stop_callback, ++ MediaSourceWrapper*, MediaSourceStopCallback, void*); ++HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, media_source_set_read_callback, ++ MediaSourceWrapper*, MediaSourceReadCallback, void*); ++HYBRIS_IMPLEMENT_VOID_FUNCTION3(media, media_source_set_pause_callback, ++ MediaSourceWrapper*, MediaSourcePauseCallback, void*); +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/properties/Makefile.am ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/properties/Makefile.am +@@ -3,6 +3,12 @@ lib_LTLIBRARIES = \ + + libandroid_properties_la_SOURCES = properties.c cache.c + libandroid_properties_la_CFLAGS = -I$(top_srcdir)/include $(ANDROID_HEADERS_CFLAGS) ++if WANT_RUNTIME_PROPERTY_CACHE ++libandroid_properties_la_SOURCES += runtime_cache.c ++else ++libandroid_properties_la_CFLAGS += -DNO_RUNTIME_PROPERTY_CACHE ++endif ++ + if WANT_DEBUG + libandroid_properties_la_CFLAGS += -ggdb -O0 + endif +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/properties/properties.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/properties/properties.c +@@ -151,7 +151,7 @@ static int property_get_socket(const cha + + /* In case it's null, just use the default */ + if ((strlen(msg.value) == 0) && (default_value)) { +- if (strlen(default_value) >= PROP_VALUE_MAX -1) return -1; ++ if (strlen(default_value) > PROP_VALUE_MAX -1) return -1; + strcpy(msg.value, default_value); + } + +@@ -164,11 +164,26 @@ int property_get(const char *key, char * + { + char *ret = NULL; + +- if ((key) && (strlen(key) >= PROP_NAME_MAX -1)) return -1; ++ if ((key) && (strlen(key) > PROP_NAME_MAX -1)) return -1; + if (value == NULL) return -1; + +- if (property_get_socket(key, value, default_value) == 0) +- return strlen(value); ++ ++ // Runtime cache will serialize property lookups within the process. ++ // This will increase latency if multiple threads are doing many ++ // parallel lookups to new properties, but the overhead should ++ // be offset with the caching eventually. ++ runtime_cache_lock(); ++ if (runtime_cache_get(key, value) == 0) { ++ ret = value; ++ } else if (property_get_socket(key, value, default_value) == 0) { ++ runtime_cache_insert(key, value); ++ ret = value; ++ } ++ runtime_cache_unlock(); ++ ++ if (ret) ++ return strlen(ret); ++ + + /* In case the socket is not available, search the property file cache by hand */ + ret = hybris_propcache_find(key); +@@ -193,8 +208,12 @@ int property_set(const char *key, const + + if (key == 0) return -1; + if (value == 0) value = ""; +- if (strlen(key) >= PROP_NAME_MAX -1) return -1; +- if (strlen(value) >= PROP_VALUE_MAX -1) return -1; ++ if (strlen(key) > PROP_NAME_MAX -1) return -1; ++ if (strlen(value) > PROP_VALUE_MAX -1) return -1; ++ ++ runtime_cache_lock(); ++ runtime_cache_remove(key); ++ runtime_cache_unlock(); + + memset(&msg, 0, sizeof(msg)); + msg.cmd = PROP_MSG_SETPROP; +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/properties/properties_p.h ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/properties/properties_p.h +@@ -23,4 +23,18 @@ typedef void (*hybris_propcache_list_cb) + void hybris_propcache_list(hybris_propcache_list_cb cb, void *cookie); + char *hybris_propcache_find(const char *key); + ++#ifndef NO_RUNTIME_PROPERTY_CACHE ++void runtime_cache_lock(); ++void runtime_cache_unlock(); ++int runtime_cache_get(const char *key, char *value); ++void runtime_cache_insert(const char *key, char *value); ++void runtime_cache_remove(const char *key); ++#else ++#define runtime_cache_lock() ++#define runtime_cache_unlock() ++#define runtime_cache_get(K,V) (-1) ++#define runtime_cache_insert(K,V) ++#define runtime_cache_remove(K) ++#endif ++ + #endif +--- /dev/null ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/properties/runtime_cache.c +@@ -0,0 +1,180 @@ ++/* ++ * Copyright (c) 2012 Carsten Munk ++ * Copyright (c) 2008 The Android Open Source Project ++ * Copyright (c) 2013 Simon Busch ++ * Copyright (c) 2013 Canonical Ltd ++ * Copyright (c) 2013 Jolla Ltd. ++ * Copyright (c) 2015 Jolla Ltd. ++ * ++ * Licensed under the Apache License, Version 2.0 (the "License"); ++ * you may not use this file except in compliance with the License. ++ * You may obtain a copy of the License at ++ * ++ * http://www.apache.org/licenses/LICENSE-2.0 ++ * ++ * Unless required by applicable law or agreed to in writing, software ++ * distributed under the License is distributed on an "AS IS" BASIS, ++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++ * See the License for the specific language governing permissions and ++ * limitations under the License. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#define HYBRIS_PROPERTY_CACHE_DEFAULT_TIMEOUT_SECS 10 ++ ++/** Maximum allowed time to return stale data from the cache. Override ++ with HYBRIS_PROPERTY_CACHE_TIMEOUT_SECS environment variable. ++*/ ++static time_t runtime_cache_timeout_secs = HYBRIS_PROPERTY_CACHE_DEFAULT_TIMEOUT_SECS; ++ ++ ++/** Key, value pair and the time of previous update (in seconds) */ ++struct hybris_prop_value ++{ ++ char *key; ++ char *value; ++ time_t last_update; ++}; ++ ++static struct hybris_prop_value * prop_array = 0; ++static int num_prop = 0; ++static int num_alloc = 0; ++ ++/** Protect access to statics */ ++static pthread_mutex_t array_mutex = PTHREAD_MUTEX_INITIALIZER; ++ ++/* private: ++ * compares two hybris_prop_value by key, so as to maintain a qsorted array of ++ * props, and search the array. ++ */ ++static int prop_qcmp(const void *a, const void *b) ++{ ++ struct hybris_prop_value *aa = (struct hybris_prop_value *)a; ++ struct hybris_prop_value *bb = (struct hybris_prop_value *)b; ++ ++ return strcmp(aa->key, bb->key); ++} ++ ++static struct hybris_prop_value *cache_find_internal(const char *key) ++{ ++ struct hybris_prop_value prop_key; ++ prop_key.key = (char*)key; ++ ++ return bsearch(&prop_key, prop_array, num_prop, sizeof(struct hybris_prop_value), prop_qcmp); ++} ++ ++static void runtime_cache_init() ++{ ++ num_alloc = 8; ++ prop_array = malloc(num_alloc * sizeof(struct hybris_prop_value)); ++ ++ const char *timeout_str = getenv("HYBRIS_PROPERTY_CACHE_TIMEOUT_SECS"); ++ if (timeout_str) { ++ runtime_cache_timeout_secs = atoi(timeout_str); ++ } ++} ++ ++static void runtime_cache_ensure_initialized() ++{ ++ if (!prop_array) { ++ runtime_cache_init(); ++ } ++} ++ ++/** Invalidate an entry in the cache ++ * ++ * Cache will never shrink. Instead, assume that the same key ++ * will be queried soon after invalidation and reuse the entry. ++ */ ++static void runtime_cache_invalidate_entry(struct hybris_prop_value *entry) ++{ ++ free(entry->value); ++ entry->value = NULL; ++} ++ ++static int runtime_cache_get_impl(const char *key, char *value) ++{ ++ int ret = -ENOENT; ++ ++ struct hybris_prop_value *entry = cache_find_internal(key); ++ if (entry != NULL && entry->value != NULL) { ++ struct timespec now; ++ clock_gettime(CLOCK_MONOTONIC_COARSE, &now); ++ time_t delta_secs = now.tv_sec - entry->last_update; ++ if (delta_secs > runtime_cache_timeout_secs) { ++ // assume the data in cache is stale, and force refresh ++ runtime_cache_invalidate_entry(entry); ++ } else { ++ // success, return value from cache ++ strcpy(value, entry->value); ++ ret = 0; ++ } ++ } ++ ++ return ret; ++} ++ ++static void runtime_cache_insert_impl(const char *key, char *value) ++{ ++ struct timespec now; ++ clock_gettime(CLOCK_MONOTONIC_COARSE, &now); ++ ++ struct hybris_prop_value *entry = cache_find_internal(key); ++ if (entry) { ++ assert(entry->value == NULL); ++ // key,value pair was invalidated earlier, ++ // reuse entry in the property array ++ entry->value = strdup(value); ++ entry->last_update = now.tv_sec; ++ } else { ++ if (num_alloc == num_prop) { ++ num_alloc = 3 * num_alloc / 2; ++ prop_array = realloc(prop_array, num_alloc * sizeof(struct hybris_prop_value)); ++ } ++ ++ struct hybris_prop_value new_entry = { strdup(key), strdup(value), now.tv_sec }; ++ prop_array[num_prop++] = new_entry; ++ ++ qsort(prop_array, num_prop, sizeof(struct hybris_prop_value), prop_qcmp); ++ } ++} ++ ++ ++void runtime_cache_lock() ++{ ++ pthread_mutex_lock(&array_mutex); ++} ++ ++void runtime_cache_unlock() ++{ ++ pthread_mutex_unlock(&array_mutex); ++} ++ ++void runtime_cache_remove(const char *key) ++{ ++ runtime_cache_ensure_initialized(); ++ struct hybris_prop_value *entry = cache_find_internal(key); ++ if (entry) { ++ runtime_cache_invalidate_entry(entry); ++ } ++} ++ ++int runtime_cache_get(const char *key, char *value) ++{ ++ runtime_cache_ensure_initialized(); ++ return runtime_cache_get_impl(key, value); ++} ++ ++void runtime_cache_insert(const char *key, char *value) ++{ ++ runtime_cache_ensure_initialized(); ++ runtime_cache_insert_impl(key, value); ++} +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/sf/sf.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/sf/sf.c +@@ -24,7 +24,7 @@ + #include + #include + +-#define COMPAT_LIBRARY_PATH "/system/lib/libsf_compat_layer.so" ++#define COMPAT_LIBRARY_PATH "libsf_compat_layer.so" + + HYBRIS_LIBRARY_INITIALIZE(sf, COMPAT_LIBRARY_PATH); + +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/tests/Makefile.am ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/tests/Makefile.am @@ -1,4 +1,5 @@ bin_PROGRAMS = \ + test_audio \ test_egl \ test_egl_configs \ test_glesv2 \ -@@ -6,8 +7,12 @@ bin_PROGRAMS = \ +@@ -6,9 +7,13 @@ bin_PROGRAMS = \ test_sf \ test_sensors \ test_input \ + test_lights \ test_camera \ + test_vibrator \ - test_gps + test_media \ + test_recorder \ @@ -12831,8 +27477,15 @@ if HAS_ANDROID_4_2_0 bin_PROGRAMS += test_hwcomposer -@@ -24,7 +29,8 @@ endif +@@ -23,14 +28,10 @@ if HAS_LIBNFC_NXP_HEADERS + bin_PROGRAMS += test_nfc + endif +-# Please re-enable your test programs according to android +-# if HAS_ANDROID_X_Y_Z +-# bin_PROGRAMS += test_audio +-# endif +- test_audio_SOURCES = test_audio.c test_audio_CFLAGS = \ - -I$(top_srcdir)/include @@ -12841,7 +27494,7 @@ test_audio_LDADD = \ $(top_builddir)/common/libhybris-common.la \ $(top_builddir)/hardware/libhardware.la -@@ -140,6 +146,28 @@ test_camera_LDADD = \ +@@ -146,8 +147,30 @@ test_camera_LDADD = \ $(top_builddir)/camera/libcamera.la \ $(top_builddir)/input/libis.la @@ -12868,25 +27521,39 @@ + $(top_builddir)/sf/libsf.la + test_gps_SOURCES = test_gps.c - test_gps_CFLAGS = -pthread \ +-test_gps_CFLAGS = -pthread \ ++test_gps_CFLAGS = \ + -I$(top_srcdir)/include \ + $(ANDROID_HEADERS_CFLAGS) + +@@ -166,9 +189,9 @@ test_nfc_SOURCES = test_nfc.c + test_nfc_CFLAGS = \ -I$(top_srcdir)/include \ -@@ -164,3 +192,11 @@ test_nfc_LDFLAGS = + $(ANDROID_HEADERS_CFLAGS) +- +-test_nfc_LDFLAGS = ++test_nfc_LDFLAGS = -pthread test_nfc_LDADD = \ ++ $(top_builddir)/common/libhybris-common.la \ $(top_builddir)/libnfc_nxp/libnfc_nxp.la \ $(top_builddir)/hardware/libhardware.la -+ + +@@ -180,3 +203,10 @@ test_vibrator_LDADD = \ + $(top_builddir)/common/libhybris-common.la \ + $(top_builddir)/vibrator/libvibrator.la + +test_wifi_SOURCES = test_wifi.c +test_wifi_CFLAGS = \ -+ -I$(top_srcdir)/include \ -+ -I$(top_srcdir)/include/android ++ -I$(top_srcdir)/include \ ++ $(ANDROID_HEADERS_CFLAGS) +test_wifi_LDADD = \ + $(top_builddir)/wifi/libwifi.la + ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/tests/test_audio.c -+++ libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_audio.c -@@ -24,32 +24,84 @@ - #include - #include +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/tests/test_audio.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_audio.c +@@ -25,32 +25,115 @@ + #include + #include +/* Workaround for MTK */ +#define AUDIO_HARDWARE_MODULE_ID2 "libaudio" @@ -12911,6 +27578,25 @@ assert(hwmod != NULL); assert(audio_hw_device_open(hwmod, &audiohw) == 0); ++ do { ++#if defined(AUDIO_DEVICE_API_VERSION_MIN) ++ if (audiohw->common.version < AUDIO_DEVICE_API_VERSION_MIN) { ++ fprintf(stderr, "Audio device API version %04x failed to meet minimum requirement %0x4.", ++ audiohw->common.version, AUDIO_DEVICE_API_VERSION_MIN); ++ } else ++#endif ++ if (audiohw->common.version != AUDIO_DEVICE_API_VERSION_CURRENT) { ++ fprintf(stderr, "Audio device API version %04x doesn't match platform current %0x4.", ++ audiohw->common.version, AUDIO_DEVICE_API_VERSION_CURRENT); ++ } else ++ break; ++ ++#if defined(AUDIO_DEVICE_API_VERSION_MIN) ++ assert(audiohw->common.version >= AUDIO_DEVICE_API_VERSION_MIN); ++#endif ++ assert(audiohw->common.version == AUDIO_DEVICE_API_VERSION_CURRENT); ++ } while(0); ++ assert(audiohw->init_check(audiohw) == 0); - printf("Audio Hardware Interface initialized.\n"); + fprintf(stdout, "Audio Hardware Interface initialized.\n"); @@ -12939,12 +27625,20 @@ + struct audio_stream_out *stream_out = NULL; + + audiohw->open_output_stream(audiohw, 0, AUDIO_DEVICE_OUT_DEFAULT, -+ AUDIO_OUTPUT_FLAG_PRIMARY, &config_out, &stream_out); ++ AUDIO_OUTPUT_FLAG_PRIMARY, &config_out, &stream_out ++#if ANDROID_VERSION_MAJOR >= 5 ++ , NULL ++#endif ++ ); + + /* Try it again */ + if (!stream_out) + audiohw->open_output_stream(audiohw, 0, AUDIO_DEVICE_OUT_DEFAULT, -+ AUDIO_OUTPUT_FLAG_PRIMARY, &config_out, &stream_out); ++ AUDIO_OUTPUT_FLAG_PRIMARY, &config_out, &stream_out ++#if ANDROID_VERSION_MAJOR >= 5 ++ , NULL ++#endif ++ ); + + assert(stream_out != NULL); + @@ -12959,7 +27653,11 @@ + struct audio_stream_in *stream_in = NULL; + + audiohw->open_input_stream(audiohw, 0, AUDIO_DEVICE_IN_DEFAULT, -+ &config_in, &stream_in); ++ &config_in, &stream_in ++#if ANDROID_VERSION_MAJOR >= 5 ++ , AUDIO_INPUT_FLAG_NONE, NULL, AUDIO_SOURCE_DEFAULT ++#endif ++ ); + assert(stream_in != NULL); + + fprintf(stdout, "Successfully created audio input stream: sample rate: %u, channel_mask: %u, format: %u\n", @@ -12972,9 +27670,9 @@ audio_hw_device_close(audiohw); return 0; ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/tests/test_lights.c -+++ libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_lights.c -@@ -29,19 +29,18 @@ int main(int argc, char **argv) +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/tests/test_lights.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_lights.c +@@ -30,19 +30,18 @@ int main(int argc, char **argv) hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (const hw_module_t**) &hwmod); assert(hwmod != NULL); @@ -12999,7 +27697,7 @@ } --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_media.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_media.c @@ -0,0 +1,373 @@ +/* + * Copyright (C) 2013 Canonical Ltd @@ -13375,7 +28073,7 @@ + return EXIT_SUCCESS; +} --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_recorder.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_recorder.c @@ -0,0 +1,490 @@ +/* + * Copyright (C) 2013 Canonical Ltd @@ -13867,9 +28565,9 @@ + eglSwapBuffers(disp, surface); + } +} ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/tests/test_ui.c -+++ libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_ui.c -@@ -52,8 +52,10 @@ int main(int argc, char **argv) +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/tests/test_ui.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_ui.c +@@ -53,8 +53,10 @@ int main(int argc, char **argv) graphic_buffer_lock(buffer, GRALLOC_USAGE_HW_RENDER, &vaddr); graphic_buffer_unlock(buffer); @@ -13881,8 +28579,8 @@ graphic_buffer_free(buffer); --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_wifi.c -@@ -0,0 +1,54 @@ ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_wifi.c +@@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014 Canonical Ltd + * @@ -13902,7 +28600,8 @@ + +#include + -+#include ++#include ++#include + +#define COMMAND_LOAD_WIFI "1" +#define COMMAND_UNLOAD_WIFI "0" @@ -13937,8 +28636,17 @@ +} + +// vim:ts=4:sw=4:noexpandtab ---- libhybris-0.1.0+git20131207+e452e83.orig/hybris/ui/ui.c -+++ libhybris-0.1.0+git20131207+e452e83/hybris/ui/ui.c +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/ui/ui.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/ui/ui.c +@@ -20,7 +20,7 @@ + #include + #include + +-#define COMPAT_LIBRARY_PATH "/system/lib/libui_compat_layer.so" ++#define COMPAT_LIBRARY_PATH "libui_compat_layer.so" + + HYBRIS_LIBRARY_INITIALIZE(ui, COMPAT_LIBRARY_PATH); + @@ -48,9 +48,11 @@ HYBRIS_IMPLEMENT_FUNCTION1(ui, uint32_t, struct graphic_buffer*); HYBRIS_IMPLEMENT_FUNCTION1(ui, void*, graphic_buffer_get_native_buffer, @@ -13951,8 +28659,19 @@ +#endif HYBRIS_IMPLEMENT_FUNCTION1(ui, int, graphic_buffer_init_check, struct graphic_buffer*); +--- libhybris-0.1.0+git20151016+6d424c9.orig/hybris/vibrator/vibrator.c ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/vibrator/vibrator.c +@@ -22,7 +22,7 @@ + + #include + +-HYBRIS_LIBRARY_INITIALIZE(vibrator, "/system/lib/libhardware_legacy.so"); ++HYBRIS_LIBRARY_INITIALIZE(vibrator, "libhardware_legacy.so"); + + HYBRIS_IMPLEMENT_FUNCTION0(vibrator, int, vibrator_exists); + HYBRIS_IMPLEMENT_FUNCTION1(vibrator, int, vibrator_on, int); --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/hybris/wifi/Makefile.am ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/wifi/Makefile.am @@ -0,0 +1,17 @@ +lib_LTLIBRARIES = \ + libwifi.la @@ -13972,7 +28691,7 @@ +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libwifi.pc --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/hybris/wifi/libwifi.pc.in ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/wifi/libwifi.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=${prefix} @@ -13985,8 +28704,8 @@ +Libs: -L${libdir} -lhybris-common -lwifi +Cflags: -I${includedir} --- /dev/null -+++ libhybris-0.1.0+git20131207+e452e83/hybris/wifi/wifi.c -@@ -0,0 +1,51 @@ ++++ libhybris-0.1.0+git20151016+6d424c9/hybris/wifi/wifi.c +@@ -0,0 +1,53 @@ +/* + * Copyright (C) 2014 Canonical Ltd + * @@ -14008,18 +28727,18 @@ +#include +#include + -+#include -+#include ++#include ++#include + -+#define COMPAT_LIBRARY_PATH "/system/lib/libhardware_legacy.so" ++#define COMPAT_LIBRARY_PATH "libhardware_legacy.so" + +HYBRIS_LIBRARY_INITIALIZE(wifi, COMPAT_LIBRARY_PATH); + +int wifi_compat_check_availability() +{ -+ /* Both are defined via HYBRIS_LIBRARY_INITIALIZE */ -+ hybris_wifi_initialize(); -+ return wifi_handle ? 1 : 0; ++ /* Both are defined via HYBRIS_LIBRARY_INITIALIZE */ ++ hybris_wifi_initialize(); ++ return wifi_handle ? 1 : 0; +} + +HYBRIS_IMPLEMENT_FUNCTION0(wifi, int, wifi_load_driver); @@ -14038,3 +28757,97 @@ +HYBRIS_IMPLEMENT_FUNCTION1(wifi, const char *, wifi_get_fw_path, int); +HYBRIS_IMPLEMENT_FUNCTION1(wifi, int, wifi_change_fw_path, const char *); +HYBRIS_IMPLEMENT_FUNCTION0(wifi, int, ensure_entropy_file_exists); ++HYBRIS_IMPLEMENT_FUNCTION4(wifi, int, wifi_send_driver_command, ++ char*, char*, char*, size_t); +--- libhybris-0.1.0+git20151016+6d424c9.orig/utils/generate_wrapper_macros.py ++++ libhybris-0.1.0+git20151016+6d424c9/utils/generate_wrapper_macros.py +@@ -104,6 +104,12 @@ print """ + name##_handle = android_dlopen(path, RTLD_LAZY); \\ + } + ++#define HYBRIS_LIRBARY_CHECK_SYMBOL(name) \\ ++ bool hybris_##name##_check_for_symbol(const char *sym) \\ ++ { \\ ++ return android_dlsym(name##_handle, sym) != NULL; \\ ++ } ++ + """ + + for count in range(MAX_ARGS): +--- libhybris-0.1.0+git20151016+6d424c9.orig/utils/load_sym_files.py ++++ libhybris-0.1.0+git20151016+6d424c9/utils/load_sym_files.py +@@ -37,19 +37,22 @@ class LoadSymFiles(gdb.Command): + symdir = "/system/symbols" + libdir = "/system/lib" + +- if len(arg_list) == 1: ++ if len(arg_list) >= 1: + symdir = arg_list[0] ++ + if not os.path.isdir(symdir): +- print "error: invalid symbol directory(%s)"%symdir +- print "usage: load-sym-files [symbols-dir] [lib-dir]" ++ print("error: invalid symbol directory '%s'" % symdir) ++ print("usage: load-sym-files [symbols-dir] [lib-dir]") + return + + if len(arg_list) == 2: + libdir = arg_list[1] ++ + if not os.path.isdir(libdir): +- print "error: invalid library directory(%s)"%libdir +- print "usage: load-sym-files [symbols-dir] [lib-dir]" ++ print("error: invalid library directory '%s'" % libdir) ++ print("usage: load-sym-files [symbols-dir] [lib-dir]") + return ++ + try: + pid = gdb.selected_inferior().pid + except AttributeError: +@@ -59,34 +62,38 @@ class LoadSymFiles(gdb.Command): + if len(gdb.inferiors()) == 1: + pid = gdb.inferiors()[0].pid + else: +- print "error: no gdb support for more than 1 inferior" ++ print("error: no gdb support for more than 1 inferior") + return + + if pid == 0: +- print "error: debugee not started yet" ++ print("error: debugee not started yet") + return + + maps = open("/proc/%d/maps"%pid,"rb") + for line in maps: + # b7fc9000-b7fcf000 r-xp 00000000 08:01 1311443 /system/lib/liblog.so +- m = re.match("([0-9A-Fa-f]+)-[0-9A-Fa-f]+\s+r-xp.*(%s.*)"%libdir,line) ++ # m = re.match("([0-9A-Fa-f]+)-[0-9A-Fa-f]+\s+r-xp.*(%s.*)" % libdir, str(line)) ++ m = re.match("([0-9A-Fa-f]+)-[0-9A-Fa-f]+\sr-xp\s.*\s(.*)\\n", line.decode('ascii')) + if not m: + continue + +- start_addr = int(m.group(1),16) ++ start_addr = int(m.group(1), 16) + lib = m.group(2) + text_addr = 0 + +- p = subprocess.Popen("objdump -h "+lib , shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) +- for header in p.stdout.read().split("\n"): ++ if not lib.startswith(libdir): ++ continue ++ ++ p = subprocess.Popen("objdump -h " + lib , shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) ++ for header in p.stdout.read().decode('ascii').split("\n"): + #6 .text 00044ef7 00017f80 00017f80 00017f80 2**4 +- t = re.match("\s*[0-9]+\s+\.text\s+([0-9A-Fa-f]+\s+){3}([0-9A-Fa-f]+)",header) ++ t = re.match("\s*[0-9]+\s+\.text\s+([0-9A-Fa-f]+\s+){3}([0-9A-Fa-f]+)", header) + if t: + text_addr = int(t.group(2),16) + break ++ + symfile = symdir + lib + if os.path.isfile(symfile): + gdb.execute("add-symbol-file %s 0x%X" % (symfile, start_addr+text_addr)) + +- + LoadSymFiles() diff -Nru libhybris-0.1.0+git20131207+e452e83/debian/rules libhybris-0.1.0+git20151016+6d424c9/debian/rules --- libhybris-0.1.0+git20131207+e452e83/debian/rules 2015-04-06 23:53:56.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/debian/rules 2016-08-05 16:46:15.000000000 +0000 @@ -9,6 +9,7 @@ PKG_driver_dbg := libhybris-dbg PKG_version := $(shell dpkg-parsechangelog | sed -n 's/^Version: //p') PKG_source := $(shell dpkg-parsechangelog | sed -n 's/^Source: //p') +PKG_distro := $(shell dpkg-parsechangelog | sed -n 's/^Distribution: //p') UPS_version := $(shell echo '$(PKG_version)' | sed 's/.*://; s/-[^-]*$$//') GIT_rev := $(shell echo '$(UPS_version)' | sed 's/.*+//') @@ -17,9 +18,13 @@ DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) -# Compiler +ifeq ($(PKG_distro),vivid) +# For vivid we still depend on GCC 4.7 as this seems to be still +# required to workaround ABI issues. export CC=gcc-4.7 export CXX=g++-4.7 +EXTRA_BUILD_DEPENDS = gcc-4.7, g++-4.7, +endif # Strong needs at least gcc 4.9 export DEB_BUILD_MAINT_OPTIONS=hardening=-stackprotectorstrong @@ -47,6 +52,19 @@ ld_so_conf_path := $(ld_so_conf_dir)/$(ld_so_conf_file) alt_ld_so_conf_path := $(ld_so_conf_dir)/$(alt_ld_so_conf_file) +.PHONY: debian/control +debian/control: debian/control.in + if [ "$(EXTRA_BUILD_DEPENDS)" = "" ] ; then \ + sed -e '/@EXTRA_BUILD_DEPENDS@/,+0d' \ + debian/control.in > debian/control ; \ + else \ + sed -e "s/@EXTRA_BUILD_DEPENDS@/$(EXTRA_BUILD_DEPENDS)/" \ + debian/control.in > debian/control ; \ + fi + +override_dh_auto_clean: debian/control + dh_auto_clean + # --remote doesn't work with github so this needs to be run from a local checkout get-packaged-orig-source: rm -rf $(PKG_source)-$(UPS_version) @@ -59,12 +77,44 @@ | gzip >../$(PKG_source)_$(UPS_version).orig.tar.gz rm -rf $(PKG_source)-$(UPS_version) -override_dh_auto_configure: +ANDROID_HEADERS_PATH = /usr/include/android +DEFAULT_CONFIGURATION = \ + --enable-wayland \ + --with-android-headers=$(ANDROID_HEADERS_PATH) \ + --enable-property-cache +ARCH_CONFIGURATION = + ifeq ($(DEB_HOST_ARCH),$(findstring $(DEB_HOST_ARCH), armhf)) - dh_auto_configure --sourcedirectory=hybris -- --enable-wayland --enable-arch=arm --with-android-headers=/usr/include/android -else - dh_auto_configure --sourcedirectory=hybris -- --enable-wayland --enable-arch=x86 --with-android-headers=/usr/include/android +ARCH_CONFIGURATION = \ + --enable-arch=arm \ + --enable-mali-quirks \ + --enable-experimental +# We enable the linker selection overrides here as we want to stay +# with the jb linker on a range of selected production devices to +# not cause any extra risk for regressions on them. They will +# migrate to a newer linker version when ported to arm64. +ARCH_CONFIGURATION += \ + --enable-ubuntu-linker-overrides endif +ifeq ($(DEB_HOST_ARCH),$(findstring $(DEB_HOST_ARCH), arm64)) +ARCH_CONFIGURATION = \ + --enable-arch=arm64 \ + --enable-mali-quirks \ + --enable-experimental +endif +ifeq ($(DEB_HOST_ARCH),$(findstring $(DEB_HOST_ARCH), i386)) +ARCH_CONFIGURATION = \ + --enable-arch=x86 +endif +ifeq ($(DEB_HOST_ARCH),$(findstring $(DEB_HOST_ARCH), amd64)) +ARCH_CONFIGURATION = \ + --enable-arch=x86 +endif + +override_dh_auto_configure: + dh_auto_configure --sourcedirectory=hybris -- \ + $(DEFAULT_CONFIGURATION) \ + $(ARCH_CONFIGURATION) override_dh_install: # Fill in important variables diff -Nru libhybris-0.1.0+git20131207+e452e83/.gitignore libhybris-0.1.0+git20151016+6d424c9/.gitignore --- libhybris-0.1.0+git20131207+e452e83/.gitignore 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/.gitignore 2015-07-30 07:51:13.000000000 +0000 @@ -28,9 +28,42 @@ aclocal-copy arm-*-linux-gnueabi-libtool +# Generated .pc, .h and .c files +hybris/camera/libcamera.pc +hybris/documentation.list +hybris/egl/egl.pc +hybris/egl/platforms/common/hybris-egl-platform.pc +hybris/egl/platforms/common/wayland-android-client-protocol.h +hybris/egl/platforms/common/wayland-android-protocol.c +hybris/egl/platforms/common/wayland-android-server-protocol.h +hybris/egl/platforms/common/wayland-egl.pc +hybris/egl/platforms/hwcomposer/hwcomposer-egl.pc +hybris/glesv1/glesv1_cm.pc +hybris/glesv2/glesv2.pc +hybris/hardware/libhardware.pc +hybris/input/libis.pc +hybris/libnfc_ndef_nxp/libnfc_ndef_nxp.pc +hybris/libnfc_nxp/libnfc_nxp.pc +hybris/libsync/libsync.pc +hybris/properties/libandroid-properties.pc +hybris/sf/libsf.pc +hybris/vibrator/libvibrator.pc + +# Util binaries +hybris/utils/getprop +hybris/utils/setprop + +# Test binaries +hybris/tests/test_camera +hybris/tests/test_egl_configs +hybris/tests/test_gps +hybris/tests/test_input +hybris/tests/test_nfc +hybris/tests/test_sf hybris/tests/test_egl hybris/tests/test_glesv2 hybris/tests/test_lights hybris/tests/test_offscreen_rendering hybris/tests/test_sensors hybris/tests/test_ui + diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/camera/camera.c libhybris-0.1.0+git20151016+6d424c9/hybris/camera/camera.c --- libhybris-0.1.0+git20131207+e452e83/hybris/camera/camera.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/camera/camera.c 2015-07-30 07:51:13.000000000 +0000 @@ -17,10 +17,11 @@ * Ricardo Salveti de Araujo */ +#include #include #include -#include +#include #include #include #include diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/camera/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/camera/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/camera/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/camera/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -2,7 +2,7 @@ libcamera.la libcamera_la_SOURCES = camera.c -libcamera_la_CFLAGS = -I$(top_srcdir)/include +libcamera_la_CFLAGS = -I$(top_srcdir)/include $(ANDROID_HEADERS_CFLAGS) if WANT_TRACE libcamera_la_CFLAGS += -DDEBUG endif diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/common/dlfcn.c libhybris-0.1.0+git20151016+6d424c9/hybris/common/dlfcn.c --- libhybris-0.1.0+git20131207+e452e83/hybris/common/dlfcn.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/dlfcn.c 2015-07-30 07:51:13.000000000 +0000 @@ -16,7 +16,7 @@ */ #include <../include/hybris/dlfcn/dlfcn.h> -#include <../include/hybris/internal/binding.h> +#include <../include/hybris/common/binding.h> void *hybris_dlopen(const char *filename, int flag) { diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/common/gingerbread/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/common/gingerbread/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/common/gingerbread/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/gingerbread/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -16,6 +16,7 @@ rt.c libandroid_linker_la_CFLAGS = \ -I$(top_srcdir)/include \ + $(ANDROID_HEADERS_CFLAGS) \ -I$(top_srcdir)/common \ -DLINKER_TEXT_BASE=0xB0000100 \ -DLINKER_AREA_SIZE=0x01000000 \ diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/common/hooks.c libhybris-0.1.0+git20151016+6d424c9/hybris/common/hooks.c --- libhybris-0.1.0+git20131207+e452e83/hybris/common/hooks.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/hooks.c 2015-07-30 07:51:13.000000000 +0000 @@ -17,7 +17,7 @@ * */ -#include +#include #include "hooks_shm.h" @@ -32,20 +32,24 @@ #include #include #include +#include +#include #include #include #include #include -#include -#include +#include #include #include +#include #include #include #include #include +#include +#include #include @@ -181,6 +185,11 @@ return strlen(s); } +static pid_t my_gettid( void ) +{ + return syscall( __NR_gettid ); +} + /* * Main pthread functions * @@ -495,7 +504,6 @@ *((int *)__mutex) = (int) realmutex; } - /* TODO: Android uses CLOCK_MONOTONIC here but I am not sure which one to use */ clock_gettime(CLOCK_REALTIME, &tv); tv.tv_sec += __msecs/1000; tv.tv_nsec += (__msecs % 1000) * 1000000; @@ -712,7 +720,6 @@ *((unsigned int *) mutex) = (unsigned int) realmutex; } - /* TODO: Android uses CLOCK_MONOTONIC here but I am not sure which one to use */ struct timespec tv; clock_gettime(CLOCK_REALTIME, &tv); tv.tv_sec += reltime->tv_sec; @@ -1175,38 +1182,81 @@ return 0; } -long my_sysconf(int name) +/* "struct dirent" from bionic/libc/include/dirent.h */ +struct bionic_dirent { + uint64_t d_ino; + int64_t d_off; + unsigned short d_reclen; + unsigned char d_type; + char d_name[256]; +}; + +static struct bionic_dirent *my_readdir(DIR *dirp) +{ + /** + * readdir(3) manpage says: + * The data returned by readdir() may be overwritten by subsequent calls + * to readdir() for the same directory stream. + * + * XXX: At the moment, for us, the data will be overwritten even by + * subsequent calls to /different/ directory streams. Eventually fix that + * (e.g. by storing per-DIR * bionic_dirent structs, and removing them on + * closedir, requires hooking of all funcs returning/taking DIR *) and + * handling the additional data attachment there) + **/ + + static struct bionic_dirent result; + + struct dirent *real_result = readdir(dirp); + if (!real_result) { + return NULL; + } + + result.d_ino = real_result->d_ino; + result.d_off = real_result->d_off; + result.d_reclen = real_result->d_reclen; + result.d_type = real_result->d_type; + memcpy(result.d_name, real_result->d_name, sizeof(result.d_name)); + + // Make sure the string is zero-terminated, even if cut off (which + // shouldn't happen, as both bionic and glibc have d_name defined + // as fixed array of 256 chars) + result.d_name[sizeof(result.d_name)-1] = '\0'; + return &result; +} + +static int my_readdir_r(DIR *dir, struct bionic_dirent *entry, + struct bionic_dirent **result) { - /* - * bionic has different values for the values below. - * TODO: compare the values between glibc and bionic and complete the mapping - */ - switch (name) { - case 0x27: - return sysconf(_SC_PAGESIZE); - case 0x28: - return sysconf(_SC_PAGE_SIZE); - case 0x60: - return sysconf(_SC_NPROCESSORS_CONF); - case 0x61: - return sysconf(_SC_NPROCESSORS_ONLN); - default: - break; - } - - - long rv = sysconf(name); - -#ifdef DEBUG - if (rv == -1) { - printf("sysconf failed for %li\n", name); - exit(-1); - } -#endif + struct dirent entry_r; + struct dirent *result_r; + + int res = readdir_r(dir, &entry_r, &result_r); + + if (res == 0) { + if (result_r != NULL) { + *result = entry; + + entry->d_ino = entry_r.d_ino; + entry->d_off = entry_r.d_off; + entry->d_reclen = entry_r.d_reclen; + entry->d_type = entry_r.d_type; + memcpy(entry->d_name, entry_r.d_name, sizeof(entry->d_name)); + + // Make sure the string is zero-terminated, even if cut off (which + // shouldn't happen, as both bionic and glibc have d_name defined + // as fixed array of 256 chars) + entry->d_name[sizeof(entry->d_name) - 1] = '\0'; + } else { + *result = NULL; + } + } - return rv; + return res; } +extern long my_sysconf(int name); + FP_ATTRIB static double my_strtod(const char *nptr, char **endptr) { if (locale_inited == 0) @@ -1218,10 +1268,71 @@ } extern int __cxa_atexit(void (*)(void*), void*, void*); +extern void __cxa_finalize(void * d); + +struct open_redirect { + const char *from; + const char *to; +}; + +struct open_redirect open_redirects[] = { + { "/dev/log/main", "/dev/log_main" }, + { "/dev/log/radio", "/dev/log_radio" }, + { "/dev/log/system", "/dev/log_system" }, + { "/dev/log/events", "/dev/log_events" }, + { NULL, NULL } +}; + +int my_open(const char *pathname, int flags, ...) +{ + va_list ap; + mode_t mode = 0; + const char *target_path = pathname; + + if (pathname != NULL) { + struct open_redirect *entry = &open_redirects[0]; + while (entry->from != NULL) { + if (strcmp(pathname, entry->from) == 0) { + target_path = entry->to; + break; + } + entry++; + } + } + + if (flags & O_CREAT) { + va_start(ap, flags); + mode = va_arg(ap, mode_t); + va_end(ap); + } + + return open(target_path, flags, mode); +} + +/** + * NOTE: Normally we don't have to wrap __system_property_get (libc.so) as it is only used + * through the property_get (libcutils.so) function. However when property_get is used + * internally in libcutils.so we don't have any chance to hook our replacement in. + * Therefore we have to hook __system_property_get too and just replace it with the + * implementation of our internal property handling + */ + +int my_system_property_get(const char *name, const char *value) +{ + return property_get(name, value, NULL); +} + +static __thread void *tls_hooks[16]; + +void *__get_tls_hooks() +{ + return tls_hooks; +} static struct _hook hooks[] = { {"property_get", property_get }, {"property_set", property_set }, + {"__system_property_get", my_system_property_get }, {"getenv", getenv }, {"printf", printf }, {"malloc", my_malloc }, @@ -1289,6 +1400,9 @@ {"opendir", opendir}, {"closedir", closedir}, /* pthread.h */ + {"getauxval", getauxval}, + {"gettid", my_gettid}, + {"getpid", getpid}, {"pthread_atfork", pthread_atfork}, {"pthread_create", my_pthread_create}, {"pthread_kill", pthread_kill}, @@ -1307,7 +1421,7 @@ {"pthread_mutex_lock_timeout_np", my_pthread_mutex_lock_timeout_np}, {"pthread_mutexattr_init", pthread_mutexattr_init}, {"pthread_mutexattr_destroy", pthread_mutexattr_destroy}, - {"pthread_mutexattr_getttype", pthread_mutexattr_gettype}, + {"pthread_mutexattr_gettype", pthread_mutexattr_gettype}, {"pthread_mutexattr_settype", pthread_mutexattr_settype}, {"pthread_mutexattr_getpshared", pthread_mutexattr_getpshared}, {"pthread_mutexattr_setpshared", my_pthread_mutexattr_setpshared}, @@ -1429,6 +1543,25 @@ {"gethostent", gethostent}, {"strftime", strftime}, {"sysconf", my_sysconf}, + {"dlopen", android_dlopen}, + {"dlerror", android_dlerror}, + {"dlsym", android_dlsym}, + {"dladdr", android_dladdr}, + {"dlclose", android_dlclose}, + /* dirent.h */ + {"opendir", opendir}, + {"fdopendir", fdopendir}, + {"closedir", closedir}, + {"readdir", my_readdir}, + {"readdir_r", my_readdir_r}, + {"rewinddir", rewinddir}, + {"seekdir", seekdir}, + {"telldir", telldir}, + {"dirfd", dirfd}, + /* fcntl.h */ + {"open", my_open}, + // TODO: scandir, scandirat, alphasort, versionsort + {"__get_tls_hooks", __get_tls_hooks}, {"sscanf", sscanf}, {"scanf", scanf}, {"vscanf", vscanf}, @@ -1449,6 +1582,7 @@ /* grp.h */ {"getgrgid", getgrgid}, {"__cxa_atexit", __cxa_atexit}, + {"__cxa_finalize", __cxa_finalize}, {NULL, NULL}, }; diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/common/ics/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/common/ics/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/common/ics/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/ics/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -16,6 +16,7 @@ rt.c libandroid_linker_la_CFLAGS = \ -I$(top_srcdir)/include \ + $(ANDROID_HEADERS_CFLAGS)\ -I$(top_srcdir)/common \ -DLINKER_TEXT_BASE=0xB0000100 \ -DLINKER_AREA_SIZE=0x01000000 \ diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/common/jb/dlfcn.c libhybris-0.1.0+git20151016+6d424c9/hybris/common/jb/dlfcn.c --- libhybris-0.1.0+git20131207+e452e83/hybris/common/jb/dlfcn.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/jb/dlfcn.c 2015-07-30 07:51:13.000000000 +0000 @@ -43,7 +43,7 @@ #define likely(expr) __builtin_expect (expr, 1) #define unlikely(expr) __builtin_expect (expr, 0) -static pthread_mutex_t dl_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t dl_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; static void set_dlerror(int err) { @@ -165,11 +165,13 @@ return 0; } +int android_dl_iterate_phdr(int (*cb)(struct dl_phdr_info *info, size_t size, void *data),void *data); + #if defined(ANDROID_ARM_LINKER) // 0000000 00011111 111112 22222222 2333333 333344444444445555555 // 0123456 78901234 567890 12345678 9012345 678901234567890123456 #define ANDROID_LIBDL_STRTAB \ - "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_unwind_find_exidx\0" + "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_unwind_find_exidx\0dl_iterate_phdr\0" _Unwind_Ptr android_dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount); @@ -178,9 +180,6 @@ // 0123456 78901234 567890 12345678 9012345 6789012345678901 #define ANDROID_LIBDL_STRTAB \ "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_iterate_phdr\0" - -int android_dl_iterate_phdr(int (*cb)(struct dl_phdr_info *info, size_t size, void *data),void *data); - #elif defined(ANDROID_SH_LINKER) // 0000000 00011111 111112 22222222 2333333 3333444444444455 // 0123456 78901234 567890 12345678 9012345 6789012345678901 @@ -230,19 +229,14 @@ st_info: STB_GLOBAL << 4, st_shndx: 1, }, -#elif defined(ANDROID_X86_LINKER) - { st_name: 36, - st_value: (Elf32_Addr) &android_dl_iterate_phdr, - st_info: STB_GLOBAL << 4, - st_shndx: 1, - }, -#elif defined(ANDROID_SH_LINKER) + { st_name: 57, +#else { st_name: 36, +#endif st_value: (Elf32_Addr) &android_dl_iterate_phdr, st_info: STB_GLOBAL << 4, st_shndx: 1, }, -#endif }; /* Fake out a hash table with a single bucket. @@ -265,7 +259,11 @@ * stubbing them out in libdl. */ static unsigned libdl_buckets[1] = { 1 }; +#if defined(ANDROID_ARM_LINKER) +static unsigned libdl_chains[8] = { 0, 2, 3, 4, 5, 6, 7, 0 }; +#else static unsigned libdl_chains[7] = { 0, 2, 3, 4, 5, 6, 0 }; +#endif soinfo libdl_info = { name: "libdl.so", @@ -274,8 +272,13 @@ strtab: ANDROID_LIBDL_STRTAB, symtab: libdl_symtab, + refcount: 1, nbucket: 1, +#if defined(ANDROID_ARM_LINKER) + nchain: 8, +#else nchain: 7, +#endif bucket: libdl_buckets, chain: libdl_chains, }; diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/common/jb/linker.c libhybris-0.1.0+git20151016+6d424c9/hybris/common/jb/linker.c --- libhybris-0.1.0+git20131207+e452e83/hybris/common/jb/linker.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/jb/linker.c 2015-07-30 07:51:13.000000000 +0000 @@ -357,7 +357,7 @@ *pcount = 0; return NULL; } -#elif defined(ANDROID_X86_LINKER) +#endif /* Here, we only have to provide a callback to iterate across all the * loaded libraries. gcc_eh does the rest. */ int @@ -379,7 +379,6 @@ } return rv; } -#endif static Elf32_Sym *_elf_lookup(soinfo *si, unsigned hash, const char *name) { @@ -1340,7 +1339,7 @@ /* We only allow an undefined symbol if this is a weak reference.. */ s = &symtab[sym]; - if (ELF32_ST_BIND(s->st_info) != STB_WEAK) { + if (ELF32_ST_BIND(s->st_info) != STB_WEAK && strcmp(si->name, "libdsyscalls.so") != 0) { DL_ERR("%5d cannot locate '%s'...\n", pid, sym_name); return -1; } diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/common/jb/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/common/jb/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/common/jb/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/jb/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -16,7 +16,9 @@ rt.c libandroid_linker_la_CFLAGS = \ -I$(top_srcdir)/include \ + $(ANDROID_HEADERS_CFLAGS) \ -I$(top_srcdir)/common \ + -D_GNU_SOURCE \ -DLINKER_TEXT_BASE=0xB0000100 \ -DLINKER_AREA_SIZE=0x01000000 \ -DDEFAULT_HYBRIS_LD_LIBRARY_PATH="\"@DEFAULT_HYBRIS_LD_LIBRARY_PATH@\"" \ diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/common/logging.c libhybris-0.1.0+git20151016+6d424c9/hybris/common/logging.c --- libhybris-0.1.0+git20131207+e452e83/hybris/common/logging.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/logging.c 2015-07-30 07:51:13.000000000 +0000 @@ -23,6 +23,7 @@ #include #include #include +#include FILE *hybris_logging_target = NULL; @@ -109,6 +110,17 @@ return (void *)pthread_self(); } +double +hybris_get_thread_time() +{ + struct timespec now; + if(clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now) == 0) { + return (double)now.tv_sec + (double)now.tv_nsec / 1000000000.0; + } else { + return -1.0; + } +} + int hybris_should_trace(const char *module, const char *tracepoint) { diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/common/logging.h libhybris-0.1.0+git20151016+6d424c9/hybris/common/logging.h --- libhybris-0.1.0+git20131207+e452e83/hybris/common/logging.h 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/logging.h 2015-07-30 07:51:13.000000000 +0000 @@ -69,6 +69,9 @@ void * hybris_get_thread_id(); +double +hybris_get_thread_time(); + enum hybris_log_format hybris_logging_format(); int hybris_should_trace(const char *module, const char *tracepoint); @@ -93,13 +96,13 @@ ##__VA_ARGS__); \ fflush(hybris_logging_target); \ } else if (hybris_logging_format() == HYBRIS_LOG_FORMAT_SYSTRACE) { \ - fprintf(hybris_logging_target, "B|%i|%s(%s) %s:%d (%s) " message "\n", \ - getpid(), module, __PRETTY_FUNCTION__, __FILE__, __LINE__, \ + fprintf(hybris_logging_target, "B|%i|%.9f|%s(%s) %s:%d (%s) " message "\n", \ + getpid(), hybris_get_thread_time(), module, __PRETTY_FUNCTION__, __FILE__, __LINE__, \ #level + 11 /* + 11 = strip leading "HYBRIS_LOG_" */, \ ##__VA_ARGS__); \ fflush(hybris_logging_target); \ - fprintf(hybris_logging_target, "E|%i|%s(%s) %s:%d (%s) " message "\n", \ - getpid(), module, __PRETTY_FUNCTION__, __FILE__, __LINE__, \ + fprintf(hybris_logging_target, "E|%i|%.9f|%s(%s) %s:%d (%s) " message "\n", \ + getpid(), hybris_get_thread_time(), module, __PRETTY_FUNCTION__, __FILE__, __LINE__, \ #level + 11 /* + 11 = strip leading "HYBRIS_LOG_" */, \ ##__VA_ARGS__); \ fflush(hybris_logging_target); \ @@ -113,19 +116,19 @@ pthread_mutex_lock(&hybris_logging_mutex); \ if (hybris_logging_format() == HYBRIS_LOG_FORMAT_NORMAL) \ { \ - fprintf(hybris_logging_target, "PID: %i Tracepoint-%c/%s::%s" message "\n", \ - getpid(), what, tracepoint, module, \ + fprintf(hybris_logging_target, "PID: %i TTIME: %.9f Tracepoint-%c/%s::%s" message "\n", \ + getpid(), hybris_get_thread_time(), what, tracepoint, module, \ ##__VA_ARGS__); \ fflush(hybris_logging_target); \ } else if (hybris_logging_format() == HYBRIS_LOG_FORMAT_SYSTRACE) { \ if (what == 'B') \ - fprintf(hybris_logging_target, "B|%i|%s::%s" message "", \ - getpid(), tracepoint, module, ##__VA_ARGS__); \ + fprintf(hybris_logging_target, "B|%i|%.9f|%s::%s" message "", \ + getpid(), hybris_get_thread_time(), tracepoint, module, ##__VA_ARGS__); \ else if (what == 'E') \ fprintf(hybris_logging_target, "E"); \ else \ - fprintf(hybris_logging_target, "C|%i|%s::%s-%i|" message "", \ - getpid(), tracepoint, module, getpid(), ##__VA_ARGS__); \ + fprintf(hybris_logging_target, "C|%i|%.9f|%s::%s-%i|" message "", \ + getpid(), hybris_get_thread_time(), tracepoint, module, getpid(), ##__VA_ARGS__); \ fflush(hybris_logging_target); \ } \ pthread_mutex_unlock(&hybris_logging_mutex); \ diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/common/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/common/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/common/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -6,11 +6,16 @@ SUBDIRS = jb libhybris_common_la_LIBADD= jb/libandroid-linker.la else +if HAS_ANDROID_5_0_0 +SUBDIRS = jb +libhybris_common_la_LIBADD= jb/libandroid-linker.la +else if HAS_ANDROID_2_3_0 SUBDIRS = gingerbread libhybris_common_la_LIBADD= gingerbread/libandroid-linker.la else -ERROR +$(error No Android Version is defined) +endif endif endif @@ -19,9 +24,11 @@ hooks_shm.c \ strlcpy.c \ dlfcn.c \ - logging.c + logging.c \ + sysconf.c libhybris_common_la_CFLAGS = \ -I$(top_srcdir)/include \ + $(ANDROID_HEADERS_CFLAGS) \ -I$(top_srcdir)/common if WANT_TRACE libhybris_common_la_CFLAGS += -DDEBUG diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/common/sysconf.c libhybris-0.1.0+git20151016+6d424c9/hybris/common/sysconf.c --- libhybris-0.1.0+git20131207+e452e83/hybris/common/sysconf.c 1970-01-01 00:00:00.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/common/sysconf.c 2015-07-30 07:51:13.000000000 +0000 @@ -0,0 +1,376 @@ +#include + +/* + * bionic/libc/include/sys/sysconf.h processed with s/define _\(\w*\)\(.*\)/define \1\2\r#ifdef _\1\rMAP_TO_UNISTD(\1),\r#endif/g + */ +#define MAP_TO_UNISTD(a) [a]=_##a +static int sysconf_map[]= { +#define SC_ARG_MAX 0x0000 +#ifdef _SC_ARG_MAX +MAP_TO_UNISTD(SC_ARG_MAX), +#endif +#define SC_BC_BASE_MAX 0x0001 +#ifdef _SC_BC_BASE_MAX +MAP_TO_UNISTD(SC_BC_BASE_MAX), +#endif +#define SC_BC_DIM_MAX 0x0002 +#ifdef _SC_BC_DIM_MAX +MAP_TO_UNISTD(SC_BC_DIM_MAX), +#endif +#define SC_BC_SCALE_MAX 0x0003 +#ifdef _SC_BC_SCALE_MAX +MAP_TO_UNISTD(SC_BC_SCALE_MAX), +#endif +#define SC_BC_STRING_MAX 0x0004 +#ifdef _SC_BC_STRING_MAX +MAP_TO_UNISTD(SC_BC_STRING_MAX), +#endif +#define SC_CHILD_MAX 0x0005 +#ifdef _SC_CHILD_MAX +MAP_TO_UNISTD(SC_CHILD_MAX), +#endif +#define SC_CLK_TCK 0x0006 +#ifdef _SC_CLK_TCK +MAP_TO_UNISTD(SC_CLK_TCK), +#endif +#define SC_COLL_WEIGHTS_MAX 0x0007 +#ifdef _SC_COLL_WEIGHTS_MAX +MAP_TO_UNISTD(SC_COLL_WEIGHTS_MAX), +#endif +#define SC_EXPR_NEST_MAX 0x0008 +#ifdef _SC_EXPR_NEST_MAX +MAP_TO_UNISTD(SC_EXPR_NEST_MAX), +#endif +#define SC_LINE_MAX 0x0009 +#ifdef _SC_LINE_MAX +MAP_TO_UNISTD(SC_LINE_MAX), +#endif +#define SC_NGROUPS_MAX 0x000a +#ifdef _SC_NGROUPS_MAX +MAP_TO_UNISTD(SC_NGROUPS_MAX), +#endif +#define SC_OPEN_MAX 0x000b +#ifdef _SC_OPEN_MAX +MAP_TO_UNISTD(SC_OPEN_MAX), +#endif +#define SC_PASS_MAX 0x000c +#ifdef _SC_PASS_MAX +MAP_TO_UNISTD(SC_PASS_MAX), +#endif +#define SC_2_C_BIND 0x000d +#ifdef _SC_2_C_BIND +MAP_TO_UNISTD(SC_2_C_BIND), +#endif +#define SC_2_C_DEV 0x000e +#ifdef _SC_2_C_DEV +MAP_TO_UNISTD(SC_2_C_DEV), +#endif +#define SC_2_C_VERSION 0x000f +#ifdef _SC_2_C_VERSION +MAP_TO_UNISTD(SC_2_C_VERSION), +#endif +#define SC_2_CHAR_TERM 0x0010 +#ifdef _SC_2_CHAR_TERM +MAP_TO_UNISTD(SC_2_CHAR_TERM), +#endif +#define SC_2_FORT_DEV 0x0011 +#ifdef _SC_2_FORT_DEV +MAP_TO_UNISTD(SC_2_FORT_DEV), +#endif +#define SC_2_FORT_RUN 0x0012 +#ifdef _SC_2_FORT_RUN +MAP_TO_UNISTD(SC_2_FORT_RUN), +#endif +#define SC_2_LOCALEDEF 0x0013 +#ifdef _SC_2_LOCALEDEF +MAP_TO_UNISTD(SC_2_LOCALEDEF), +#endif +#define SC_2_SW_DEV 0x0014 +#ifdef _SC_2_SW_DEV +MAP_TO_UNISTD(SC_2_SW_DEV), +#endif +#define SC_2_UPE 0x0015 +#ifdef _SC_2_UPE +MAP_TO_UNISTD(SC_2_UPE), +#endif +#define SC_2_VERSION 0x0016 +#ifdef _SC_2_VERSION +MAP_TO_UNISTD(SC_2_VERSION), +#endif +#define SC_JOB_CONTROL 0x0017 +#ifdef _SC_JOB_CONTROL +MAP_TO_UNISTD(SC_JOB_CONTROL), +#endif +#define SC_SAVED_IDS 0x0018 +#ifdef _SC_SAVED_IDS +MAP_TO_UNISTD(SC_SAVED_IDS), +#endif +#define SC_VERSION 0x0019 +#ifdef _SC_VERSION +MAP_TO_UNISTD(SC_VERSION), +#endif +#define SC_RE_DUP_MAX 0x001a +#ifdef _SC_RE_DUP_MAX +MAP_TO_UNISTD(SC_RE_DUP_MAX), +#endif +#define SC_STREAM_MAX 0x001b +#ifdef _SC_STREAM_MAX +MAP_TO_UNISTD(SC_STREAM_MAX), +#endif +#define SC_TZNAME_MAX 0x001c +#ifdef _SC_TZNAME_MAX +MAP_TO_UNISTD(SC_TZNAME_MAX), +#endif +#define SC_XOPEN_CRYPT 0x001d +#ifdef _SC_XOPEN_CRYPT +MAP_TO_UNISTD(SC_XOPEN_CRYPT), +#endif +#define SC_XOPEN_ENH_I18N 0x001e +#ifdef _SC_XOPEN_ENH_I18N +MAP_TO_UNISTD(SC_XOPEN_ENH_I18N), +#endif +#define SC_XOPEN_SHM 0x001f +#ifdef _SC_XOPEN_SHM +MAP_TO_UNISTD(SC_XOPEN_SHM), +#endif +#define SC_XOPEN_VERSION 0x0020 +#ifdef _SC_XOPEN_VERSION +MAP_TO_UNISTD(SC_XOPEN_VERSION), +#endif +#define SC_XOPEN_XCU_VERSION 0x0021 +#ifdef _SC_XOPEN_XCU_VERSION +MAP_TO_UNISTD(SC_XOPEN_XCU_VERSION), +#endif +#define SC_XOPEN_REALTIME 0x0022 +#ifdef _SC_XOPEN_REALTIME +MAP_TO_UNISTD(SC_XOPEN_REALTIME), +#endif +#define SC_XOPEN_REALTIME_THREADS 0x0023 +#ifdef _SC_XOPEN_REALTIME_THREADS +MAP_TO_UNISTD(SC_XOPEN_REALTIME_THREADS), +#endif +#define SC_XOPEN_LEGACY 0x0024 +#ifdef _SC_XOPEN_LEGACY +MAP_TO_UNISTD(SC_XOPEN_LEGACY), +#endif +#define SC_ATEXIT_MAX 0x0025 +#ifdef _SC_ATEXIT_MAX +MAP_TO_UNISTD(SC_ATEXIT_MAX), +#endif +#define SC_IOV_MAX 0x0026 +#ifdef _SC_IOV_MAX +MAP_TO_UNISTD(SC_IOV_MAX), +#endif +#define SC_PAGESIZE 0x0027 +#ifdef _SC_PAGESIZE +MAP_TO_UNISTD(SC_PAGESIZE), +#endif +#define SC_PAGE_SIZE 0x0028 +#ifdef _SC_PAGE_SIZE +MAP_TO_UNISTD(SC_PAGE_SIZE), +#endif +#define SC_XOPEN_UNIX 0x0029 +#ifdef _SC_XOPEN_UNIX +MAP_TO_UNISTD(SC_XOPEN_UNIX), +#endif +#define SC_XBS5_ILP32_OFF32 0x002a +#ifdef _SC_XBS5_ILP32_OFF32 +MAP_TO_UNISTD(SC_XBS5_ILP32_OFF32), +#endif +#define SC_XBS5_ILP32_OFFBIG 0x002b +#ifdef _SC_XBS5_ILP32_OFFBIG +MAP_TO_UNISTD(SC_XBS5_ILP32_OFFBIG), +#endif +#define SC_XBS5_LP64_OFF64 0x002c +#ifdef _SC_XBS5_LP64_OFF64 +MAP_TO_UNISTD(SC_XBS5_LP64_OFF64), +#endif +#define SC_XBS5_LPBIG_OFFBIG 0x002d +#ifdef _SC_XBS5_LPBIG_OFFBIG +MAP_TO_UNISTD(SC_XBS5_LPBIG_OFFBIG), +#endif +#define SC_AIO_LISTIO_MAX 0x002e +#ifdef _SC_AIO_LISTIO_MAX +MAP_TO_UNISTD(SC_AIO_LISTIO_MAX), +#endif +#define SC_AIO_MAX 0x002f +#ifdef _SC_AIO_MAX +MAP_TO_UNISTD(SC_AIO_MAX), +#endif +#define SC_AIO_PRIO_DELTA_MAX 0x0030 +#ifdef _SC_AIO_PRIO_DELTA_MAX +MAP_TO_UNISTD(SC_AIO_PRIO_DELTA_MAX), +#endif +#define SC_DELAYTIMER_MAX 0x0031 +#ifdef _SC_DELAYTIMER_MAX +MAP_TO_UNISTD(SC_DELAYTIMER_MAX), +#endif +#define SC_MQ_OPEN_MAX 0x0032 +#ifdef _SC_MQ_OPEN_MAX +MAP_TO_UNISTD(SC_MQ_OPEN_MAX), +#endif +#define SC_MQ_PRIO_MAX 0x0033 +#ifdef _SC_MQ_PRIO_MAX +MAP_TO_UNISTD(SC_MQ_PRIO_MAX), +#endif +#define SC_RTSIG_MAX 0x0034 +#ifdef _SC_RTSIG_MAX +MAP_TO_UNISTD(SC_RTSIG_MAX), +#endif +#define SC_SEM_NSEMS_MAX 0x0035 +#ifdef _SC_SEM_NSEMS_MAX +MAP_TO_UNISTD(SC_SEM_NSEMS_MAX), +#endif +#define SC_SEM_VALUE_MAX 0x0036 +#ifdef _SC_SEM_VALUE_MAX +MAP_TO_UNISTD(SC_SEM_VALUE_MAX), +#endif +#define SC_SIGQUEUE_MAX 0x0037 +#ifdef _SC_SIGQUEUE_MAX +MAP_TO_UNISTD(SC_SIGQUEUE_MAX), +#endif +#define SC_TIMER_MAX 0x0038 +#ifdef _SC_TIMER_MAX +MAP_TO_UNISTD(SC_TIMER_MAX), +#endif +#define SC_ASYNCHRONOUS_IO 0x0039 +#ifdef _SC_ASYNCHRONOUS_IO +MAP_TO_UNISTD(SC_ASYNCHRONOUS_IO), +#endif +#define SC_FSYNC 0x003a +#ifdef _SC_FSYNC +MAP_TO_UNISTD(SC_FSYNC), +#endif +#define SC_MAPPED_FILES 0x003b +#ifdef _SC_MAPPED_FILES +MAP_TO_UNISTD(SC_MAPPED_FILES), +#endif +#define SC_MEMLOCK 0x003c +#ifdef _SC_MEMLOCK +MAP_TO_UNISTD(SC_MEMLOCK), +#endif +#define SC_MEMLOCK_RANGE 0x003d +#ifdef _SC_MEMLOCK_RANGE +MAP_TO_UNISTD(SC_MEMLOCK_RANGE), +#endif +#define SC_MEMORY_PROTECTION 0x003e +#ifdef _SC_MEMORY_PROTECTION +MAP_TO_UNISTD(SC_MEMORY_PROTECTION), +#endif +#define SC_MESSAGE_PASSING 0x003f +#ifdef _SC_MESSAGE_PASSING +MAP_TO_UNISTD(SC_MESSAGE_PASSING), +#endif +#define SC_PRIORITIZED_IO 0x0040 +#ifdef _SC_PRIORITIZED_IO +MAP_TO_UNISTD(SC_PRIORITIZED_IO), +#endif +#define SC_PRIORITY_SCHEDULING 0x0041 +#ifdef _SC_PRIORITY_SCHEDULING +MAP_TO_UNISTD(SC_PRIORITY_SCHEDULING), +#endif +#define SC_REALTIME_SIGNALS 0x0042 +#ifdef _SC_REALTIME_SIGNALS +MAP_TO_UNISTD(SC_REALTIME_SIGNALS), +#endif +#define SC_SEMAPHORES 0x0043 +#ifdef _SC_SEMAPHORES +MAP_TO_UNISTD(SC_SEMAPHORES), +#endif +#define SC_SHARED_MEMORY_OBJECTS 0x0044 +#ifdef _SC_SHARED_MEMORY_OBJECTS +MAP_TO_UNISTD(SC_SHARED_MEMORY_OBJECTS), +#endif +#define SC_SYNCHRONIZED_IO 0x0045 +#ifdef _SC_SYNCHRONIZED_IO +MAP_TO_UNISTD(SC_SYNCHRONIZED_IO), +#endif +#define SC_TIMERS 0x0046 +#ifdef _SC_TIMERS +MAP_TO_UNISTD(SC_TIMERS), +#endif +#define SC_GETGR_R_SIZE_MAX 0x0047 +#ifdef _SC_GETGR_R_SIZE_MAX +MAP_TO_UNISTD(SC_GETGR_R_SIZE_MAX), +#endif +#define SC_GETPW_R_SIZE_MAX 0x0048 +#ifdef _SC_GETPW_R_SIZE_MAX +MAP_TO_UNISTD(SC_GETPW_R_SIZE_MAX), +#endif +#define SC_LOGIN_NAME_MAX 0x0049 +#ifdef _SC_LOGIN_NAME_MAX +MAP_TO_UNISTD(SC_LOGIN_NAME_MAX), +#endif +#define SC_THREAD_DESTRUCTOR_ITERATIONS 0x004a +#ifdef _SC_THREAD_DESTRUCTOR_ITERATIONS +MAP_TO_UNISTD(SC_THREAD_DESTRUCTOR_ITERATIONS), +#endif +#define SC_THREAD_KEYS_MAX 0x004b +#ifdef _SC_THREAD_KEYS_MAX +MAP_TO_UNISTD(SC_THREAD_KEYS_MAX), +#endif +#define SC_THREAD_STACK_MIN 0x004c +#ifdef _SC_THREAD_STACK_MIN +MAP_TO_UNISTD(SC_THREAD_STACK_MIN), +#endif +#define SC_THREAD_THREADS_MAX 0x004d +#ifdef _SC_THREAD_THREADS_MAX +MAP_TO_UNISTD(SC_THREAD_THREADS_MAX), +#endif +#define SC_TTY_NAME_MAX 0x004e +#ifdef _SC_TTY_NAME_MAX +MAP_TO_UNISTD(SC_TTY_NAME_MAX), +#endif + +#define SC_THREADS 0x004f +#ifdef _SC_THREADS +MAP_TO_UNISTD(SC_THREADS), +#endif +#define SC_THREAD_ATTR_STACKADDR 0x0050 +#ifdef _SC_THREAD_ATTR_STACKADDR +MAP_TO_UNISTD(SC_THREAD_ATTR_STACKADDR), +#endif +#define SC_THREAD_ATTR_STACKSIZE 0x0051 +#ifdef _SC_THREAD_ATTR_STACKSIZE +MAP_TO_UNISTD(SC_THREAD_ATTR_STACKSIZE), +#endif +#define SC_THREAD_PRIORITY_SCHEDULING 0x0052 +#ifdef _SC_THREAD_PRIORITY_SCHEDULING +MAP_TO_UNISTD(SC_THREAD_PRIORITY_SCHEDULING), +#endif +#define SC_THREAD_PRIO_INHERIT 0x0053 +#ifdef _SC_THREAD_PRIO_INHERIT +MAP_TO_UNISTD(SC_THREAD_PRIO_INHERIT), +#endif +#define SC_THREAD_PRIO_PROTECT 0x0054 +#ifdef _SC_THREAD_PRIO_PROTECT +MAP_TO_UNISTD(SC_THREAD_PRIO_PROTECT), +#endif +#define SC_THREAD_SAFE_FUNCTIONS 0x0055 +#ifdef _SC_THREAD_SAFE_FUNCTIONS +MAP_TO_UNISTD(SC_THREAD_SAFE_FUNCTIONS), +#endif + +#define SC_NPROCESSORS_CONF 0x0060 +#ifdef _SC_NPROCESSORS_CONF +MAP_TO_UNISTD(SC_NPROCESSORS_CONF), +#endif +#define SC_NPROCESSORS_ONLN 0x0061 +#ifdef _SC_NPROCESSORS_ONLN +MAP_TO_UNISTD(SC_NPROCESSORS_ONLN), +#endif +#define SC_PHYS_PAGES 0x0062 +#ifdef _SC_PHYS_PAGES +MAP_TO_UNISTD(SC_PHYS_PAGES), +#endif +#define SC_AVPHYS_PAGES 0x0063 +#ifdef _SC_AVPHYS_PAGES +MAP_TO_UNISTD(SC_AVPHYS_PAGES), +#endif +}; +#undef MAP_TO_UNISTD + +long my_sysconf(int name) +{ + return sysconf(sysconf_map[name]); +} diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/configure.ac libhybris-0.1.0+git20151016+6d424c9/hybris/configure.ac --- libhybris-0.1.0+git20131207+e452e83/hybris/configure.ac 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/configure.ac 2015-07-30 07:51:13.000000000 +0000 @@ -67,6 +67,11 @@ [wayland="no"]) AM_CONDITIONAL( [WANT_WAYLAND], [test x"$wayland" = x"yes"]) +AC_ARG_ENABLE(wayland_serverside_buffers, + [ --enable-wayland_serverside_buffers Enable serverside buffer allocation for wayland (default=enabled)], + [wayland_serverside_buffers=$enableval], + [wayland_serverside_buffers=yes]) +AM_CONDITIONAL( [WANT_WL_SERVERSIDE_BUFFERS], [test x"$wayland_serverside_buffers" = x"yes"]) AC_ARG_ENABLE(arch, [ --enable-arch[=arch] Compile specific CPU target(default=arm) @@ -102,50 +107,76 @@ [ ]) AC_SUBST(DEFAULT_HYBRIS_LD_LIBRARY_PATH) - -android_headers_path="" AC_ARG_WITH(android-headers, [ --with-android-headers=DIR Use android headers available in DIR. See utils/extract-headers.sh ], [ - if [ ! test -e $withval/android-version.h ]; then - echo "Error! missing android-version.h in android header path" - exit 1 - fi - rm -f include/android - ln -sf $withval include/android - android_headers_path="$withval" - - # According to http://en.wikipedia.org/wiki/Android_version_history#Version_history_by_API_level - android_headers_major=`grep -E "define ANDROID_VERSION_MAJOR " $android_headers_path/android-version.h | sed "s|^\#define ANDROID_VERSION_MAJOR \(.*\)$|\1|g"` - - android_headers_minor=`grep -E "define ANDROID_VERSION_MINOR " $android_headers_path/android-version.h | sed "s|^\#define ANDROID_VERSION_MINOR \(.*\)$|\1|g"` - - android_headers_patch=`grep -E "define ANDROID_VERSION_PATCH " $android_headers_path/android-version.h | sed "s|^\#define ANDROID_VERSION_PATCH \(.*\)$|\1|g"` - - if [ test "x$android_headers_major" = x ]; then - echo "Error! Was unable to locate define ANDROID_VERSION_MAJOR in $android_headers_path/android-version.h" - fi - - AC_SUBST(ANDROID_VERSION_MAJOR, [$android_headers_major]) - AC_SUBST(ANDROID_VERSION_MINOR, [$android_headers_minor]) - AC_SUBST(ANDROID_VERSION_PATCH, [$android_headers_patch]) - - echo "Android headers version is $android_headers_major.$android_headers_minor.$android_headers_patch" + AM_CONDITIONAL([HAS_LIBNFC_NXP_HEADERS], [test -f $withval/libnfc-nxp/phLibNfc.h]) + AS_IF([test -f $withval/libnfc-nxp/phLibNfc.h], [ANDROID_HEADERS_CFLAGS="-I$withval -I$withval/libnfc-nxp"],[ANDROID_HEADERS_CFLAGS="-I$withval"]) + AC_SUBST([ANDROID_HEADERS_CFLAGS]) ], - [ - echo "Error! need to provide path to Android headers --with-android-headers=DIR. See utils/extract-headers.sh" - exit 1 - ] - ) + [ PKG_CHECK_MODULES(ANDROID_HEADERS, android-headers,, exit) ] +) +CPPFLAGS="$CPPFLAGS $ANDROID_HEADERS_CFLAGS" + +AC_CHECK_HEADERS(android-config.h,,AC_MSG_ERROR(required header file is missing)) +AC_CHECK_HEADERS(android-version.h,,AC_MSG_ERROR(required header file is missing)) + +# AC_AWK_CPP +AC_DEFUN([AC_AWK_CPP], +[AC_LANG_PREPROC_REQUIRE()dnl +AC_REQUIRE([AC_PROG_AWK])dnl +AC_LANG_CONFTEST([AC_LANG_SOURCE([[$2]])]) + +ac_awk_cpp_out="`$CPP $CPPFLAGS conftest.$ac_ext|$AWK '$1'`" +AS_IF([test "x$ac_awk_cpp_out" = x], [$4], [$3]) +rm -f conftest* +])# AC_AWK_CPP + + +# According to http://en.wikipedia.org/wiki/Android_version_history#Version_history_by_API_level +########################### +AC_AWK_CPP([/has_ANDROID_VERSION_MAJOR/ {print \$2;}], +[ +#include +has_ANDROID_VERSION_MAJOR ANDROID_VERSION_MAJOR +], +[android_headers_major=$ac_awk_cpp_out], +[AC_MSG_ERROR(required 'major' version is missing)]) + + +########################### +AC_AWK_CPP([/has_ANDROID_VERSION_MINOR/ {print \$2;}], +[ +#include +has_ANDROID_VERSION_MINOR ANDROID_VERSION_MINOR +], +[android_headers_minor=$ac_awk_cpp_out], +[AC_MSG_ERROR(required 'minor' version is missing)]) + +########################### +AC_AWK_CPP([/has_ANDROID_VERSION_PATCH/ {print \$2;}], +[ +#include +has_ANDROID_VERSION_PATCH ANDROID_VERSION_PATCH +], +[android_headers_patch=$ac_awk_cpp_out], +[AC_MSG_ERROR(require 'patch' version is missing)]) + +AC_MSG_NOTICE("Android headers version is $android_headers_major.$android_headers_minor.$android_headers_patch.$ac_awk_cpp_out") +########################### +AC_SUBST(ANDROID_VERSION_MAJOR, [$android_headers_major]) +AC_SUBST(ANDROID_VERSION_MINOR, [$android_headers_minor]) +AC_SUBST(ANDROID_VERSION_PATCH, [$android_headers_patch]) -# Add automake tests for version/API needs here that you need in code, including test .am's +AC_MSG_NOTICE("Android headers version is $android_headers_major.$android_headers_minor.$android_headers_patch") +# Add automake tests for version/API needs here that you need in code, including test .am's +AM_CONDITIONAL([HAS_ANDROID_5_0_0], [test $android_headers_major -ge 5 -a $android_headers_minor -ge 0 ]) AM_CONDITIONAL([HAS_ANDROID_4_2_0], [test $android_headers_major -ge 4 -a $android_headers_minor -ge 2 ]) AM_CONDITIONAL([HAS_ANDROID_4_1_0], [test $android_headers_major -ge 4 -a $android_headers_minor -ge 1 ]) AM_CONDITIONAL([HAS_ANDROID_4_0_0], [test $android_headers_major -ge 4 -a $android_headers_minor -ge 0 ]) AM_CONDITIONAL([HAS_ANDROID_2_3_0], [test $android_headers_major -ge 2 -a $android_headers_minor -ge 3 ]) -AM_CONDITIONAL([HAS_LIBNFC_NXP_HEADERS], [test -f ${android_headers_path}/libnfc-nxp/phLibNfc.h]) AC_CONFIG_FILES([ Makefile @@ -184,6 +215,8 @@ input/libis.pc camera/Makefile camera/libcamera.pc + vibrator/Makefile + vibrator/libvibrator.pc include/Makefile utils/Makefile tests/Makefile @@ -216,4 +249,3 @@ echo "------------------------------------------------------------------------" echo echo "Now type 'make' to compile and 'make install' to install this package." - diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/egl.c libhybris-0.1.0+git20151016+6d424c9/hybris/egl/egl.c --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/egl.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/egl.c 2015-07-30 07:51:13.000000000 +0000 @@ -17,6 +17,8 @@ /* EGL function pointers */ #define EGL_EGLEXT_PROTOTYPES +/* For RTLD_DEFAULT */ +#define _GNU_SOURCE #include #include #include @@ -30,14 +32,17 @@ #include -#include +#include #include -#include +#include #include "logging.h" static void *_libegl = NULL; static void *_libgles = NULL; +static void *_hybris_libgles1 = NULL; +static void *_hybris_libgles2 = NULL; +static int _egl_context_client_version = 1; static EGLint (*_eglGetError)(void) = NULL; @@ -120,8 +125,22 @@ _libgles = (void *) android_dlopen(getenv("LIBGLESV2") ? getenv("LIBGLESV2") : "libGLESv2.so", RTLD_LAZY); } -#define EGL_DLSYM(fptr, sym) do { if (_libegl == NULL) { _init_androidegl(); }; if (*(fptr) == NULL) { *(fptr) = (void *) android_dlsym(_libegl, sym); } } while (0) -#define GLESv2_DLSYM(fptr, sym) do { if (_libgles == NULL) { _init_androidegl(); }; if (*(fptr) == NULL) { *(fptr) = (void *) android_dlsym(_libgles, sym); } } while (0) +static void * _android_egl_dlsym(const char *symbol) +{ + if (_libegl == NULL) + _init_androidegl(); + + return android_dlsym(_libegl, symbol); +} + +struct ws_egl_interface hybris_egl_interface = { + _android_egl_dlsym, + egl_helper_has_mapping, + egl_helper_get_mapping, +}; + +#define EGL_DLSYM(fptr, sym) do { if (_libegl == NULL) { _init_androidegl(); }; if (*(fptr) == NULL) { *(fptr) = (void *) android_dlsym(_libegl, sym); } } while (0) +#define GLESv2_DLSYM(fptr, sym) do { if (_libgles == NULL) { _init_androidegl(); }; if (*(fptr) == NULL) { *(fptr) = (void *) android_dlsym(_libgles, sym); } } while (0) EGLint eglGetError(void) { @@ -129,40 +148,33 @@ return (*_eglGetError)(); } -struct _eglDisplayMapping { - EGLNativeDisplayType ndt; - EGLDisplay display; -}; - #define _EGL_MAX_DISPLAYS 100 -struct _eglDisplayMapping *_displayMappings[_EGL_MAX_DISPLAYS]; +struct _EGLDisplay *_displayMappings[_EGL_MAX_DISPLAYS]; -void _addMapping(EGLNativeDisplayType display_id, EGLDisplay display) +void _addMapping(struct _EGLDisplay *display_id) { int i; for (i = 0; i < _EGL_MAX_DISPLAYS; i++) { if (_displayMappings[i] == NULL) { - _displayMappings[i] = (struct _eglDisplayMapping *) malloc(sizeof(struct _eglDisplayMapping)); - _displayMappings[i]->ndt = display_id; - _displayMappings[i]->display = display; + _displayMappings[i] = display_id; return; } } } -EGLNativeDisplayType _egldisplay2NDT(EGLDisplay display) +struct _EGLDisplay *hybris_egl_display_get_mapping(EGLDisplay display) { int i; for (i = 0; i < _EGL_MAX_DISPLAYS; i++) { if (_displayMappings[i]) { - if (_displayMappings[i]->display == display) + if (_displayMappings[i]->dpy == display) { - return _displayMappings[i]->ndt; + return _displayMappings[i]; } } @@ -175,17 +187,22 @@ EGL_DLSYM(&_eglGetDisplay, "eglGetDisplay"); EGLNativeDisplayType real_display; - if (!ws_IsValidDisplay(display_id)) - { - return EGL_NO_DISPLAY; - } - real_display = (*_eglGetDisplay)(EGL_DEFAULT_DISPLAY); if (real_display == EGL_NO_DISPLAY) { return EGL_NO_DISPLAY; } - _addMapping(display_id, real_display); + + struct _EGLDisplay *dpy = hybris_egl_display_get_mapping(real_display); + if (!dpy) { + dpy = ws_GetDisplay(display_id); + if (!dpy) { + return EGL_NO_DISPLAY; + } + dpy->dpy = real_display; + _addMapping(dpy); + } + return real_display; } @@ -198,6 +215,9 @@ EGLBoolean eglTerminate(EGLDisplay dpy) { EGL_DLSYM(&_eglTerminate, "eglTerminate"); + + struct _EGLDisplay *display = hybris_egl_display_get_mapping(dpy); + ws_Terminate(display); return (*_eglTerminate)(dpy); } @@ -238,12 +258,18 @@ { EGL_DLSYM(&_eglCreateWindowSurface, "eglCreateWindowSurface"); - win = ws_CreateWindow(win, _egldisplay2NDT(dpy)); - + HYBRIS_TRACE_BEGIN("hybris-egl", "eglCreateWindowSurface", ""); + struct _EGLDisplay *display = hybris_egl_display_get_mapping(dpy); + win = ws_CreateWindow(win, display); + assert(((struct ANativeWindowBuffer *) win)->common.magic == ANDROID_NATIVE_WINDOW_MAGIC); + HYBRIS_TRACE_BEGIN("native-egl", "eglCreateWindowSurface", ""); EGLSurface result = (*_eglCreateWindowSurface)(dpy, config, win, attrib_list); + HYBRIS_TRACE_END("native-egl", "eglCreateWindowSurface", ""); egl_helper_push_mapping(result, win); + + HYBRIS_TRACE_END("hybris-egl", "eglCreateWindowSurface", ""); return result; } @@ -339,8 +365,26 @@ EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) { + EGLBoolean ret; + EGLSurface surface; + EGLNativeWindowType win; + HYBRIS_TRACE_BEGIN("hybris-egl", "eglSwapInterval", "=%d", interval); + + /* Some egl implementations don't pass through the setSwapInterval + * call. Since we may support various swap intervals internally, we'll + * call it anyway and then give the wrapped egl implementation a chance + * to chage it. */ + EGL_DLSYM(&_eglGetCurrentSurface, "eglGetCurrentSurface"); + surface = (*_eglGetCurrentSurface)(EGL_DRAW); + if (egl_helper_has_mapping(surface)) + ws_setSwapInterval(dpy, egl_helper_get_mapping(surface), interval); + + HYBRIS_TRACE_BEGIN("native-egl", "eglSwapInterval", "=%d", interval); EGL_DLSYM(&_eglSwapInterval, "eglSwapInterval"); - return (*_eglSwapInterval)(dpy, interval); + ret = (*_eglSwapInterval)(dpy, interval); + HYBRIS_TRACE_END("native-egl", "eglSwapInterval", ""); + HYBRIS_TRACE_END("hybris-egl", "eglSwapInterval", ""); + return ret; } EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, @@ -348,6 +392,15 @@ const EGLint *attrib_list) { EGL_DLSYM(&_eglCreateContext, "eglCreateContext"); + + EGLint *p = attrib_list; + while (p != NULL && *p != EGL_NONE) { + if (*p == EGL_CONTEXT_CLIENT_VERSION) { + _egl_context_client_version = p[1]; + } + p += 2; + } + return (*_eglCreateContext)(dpy, config, share_context, attrib_list); } @@ -398,15 +451,33 @@ EGLBoolean eglWaitNative(EGLint engine) { EGL_DLSYM(&_eglWaitNative, "eglWaitNative"); - return (*_eglWaitNative)(engine); + return (*_eglWaitNative)(engine); +} + +EGLBoolean _my_eglSwapBuffersWithDamageEXT(EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects) +{ + EGLNativeWindowType win; + EGLBoolean ret; + HYBRIS_TRACE_BEGIN("hybris-egl", "eglSwapBuffersWithDamageEXT", ""); + EGL_DLSYM(&_eglSwapBuffers, "eglSwapBuffers"); + + if (egl_helper_has_mapping(surface)) { + win = egl_helper_get_mapping(surface); + ws_prepareSwap(dpy, win, rects, n_rects); + ret = (*_eglSwapBuffers)(dpy, surface); + ws_finishSwap(dpy, win); + } else { + ret = (*_eglSwapBuffers)(dpy, surface); + } + HYBRIS_TRACE_END("hybris-egl", "eglSwapBuffersWithDamageEXT", ""); + return ret; } EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) { - EGLBoolean ret; + EGLBoolean ret; HYBRIS_TRACE_BEGIN("hybris-egl", "eglSwapBuffers", ""); - EGL_DLSYM(&_eglSwapBuffers, "eglSwapBuffers"); - ret = (*_eglSwapBuffers)(dpy, surface); + ret = _my_eglSwapBuffersWithDamageEXT(dpy, surface, NULL, 0); HYBRIS_TRACE_END("hybris-egl", "eglSwapBuffers", ""); return ret; } @@ -418,6 +489,7 @@ return (*_eglCopyBuffers)(dpy, surface, target); } + static EGLImageKHR _my_eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) { EGL_DLSYM(&_eglCreateImageKHR, "eglCreateImageKHR"); @@ -427,14 +499,27 @@ const EGLint *newattrib_list = attrib_list; ws_passthroughImageKHR(&newctx, &newtarget, &newbuffer, &newattrib_list); - return (*_eglCreateImageKHR)(dpy, newctx, newtarget, newbuffer, newattrib_list); + + EGLImageKHR eik = (*_eglCreateImageKHR)(dpy, newctx, newtarget, newbuffer, newattrib_list); + + if (eik == EGL_NO_IMAGE_KHR) { + return EGL_NO_IMAGE_KHR; + } + + struct egl_image *image; + image = malloc(sizeof *image); + image->egl_image = eik; + image->egl_buffer = buffer; + image->target = target; + + return (EGLImageKHR)image; } static void _my_glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) { GLESv2_DLSYM(&_glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES"); - (*_glEGLImageTargetTexture2DOES)(target, image); - return; + struct egl_image *img = image; + (*_glEGLImageTargetTexture2DOES)(target, img ? img->egl_image : NULL); } __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) @@ -443,22 +528,64 @@ if (strcmp(procname, "eglCreateImageKHR") == 0) { return _my_eglCreateImageKHR; - } + } + else if (strcmp(procname, "eglDestroyImageKHR") == 0) + { + return eglDestroyImageKHR; + } + else if (strcmp(procname, "eglSwapBuffersWithDamageEXT") == 0) + { + return _my_eglSwapBuffersWithDamageEXT; + } else if (strcmp(procname, "glEGLImageTargetTexture2DOES") == 0) { return _my_glEGLImageTargetTexture2DOES; } - __eglMustCastToProperFunctionPointerType ret = ws_eglGetProcAddress(procname); - if (ret == NULL) - return (*_eglGetProcAddress)(procname); - else return ret; + + __eglMustCastToProperFunctionPointerType ret = NULL; + + switch (_egl_context_client_version) { + case 1: // OpenGL ES 1.x API + if (_hybris_libgles1 == NULL) { + _hybris_libgles1 = (void *) dlopen(getenv("HYBRIS_LIBGLESV1") ?: "libGLESv1_CM.so.1", RTLD_LAZY); + } + ret = _hybris_libgles1 ? dlsym(_hybris_libgles1, procname) : NULL; + break; + case 2: // OpenGL ES 2.0 API + if (_hybris_libgles2 == NULL) { + _hybris_libgles2 = (void *) dlopen(getenv("HYBRIS_LIBGLESV2") ?: "libGLESv2.so.2", RTLD_LAZY); + } + ret = _hybris_libgles2 ? dlsym(_hybris_libgles2, procname) : NULL; + break; + case 3: // OpenGL ES 3.x API + // TODO: Load from libGLESv3.so once we have OpenGL ES 3.0/3.1 support + break; + default: + HYBRIS_WARN("Unknown EGL context client version: %d", _egl_context_client_version); + break; + } + + if (ret == NULL) { + ret = ws_eglGetProcAddress(procname); + } + + if (ret == NULL) { + ret = (*_eglGetProcAddress)(procname); + } + + return ret; } EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image) { EGL_DLSYM(&_eglDestroyImageKHR, "eglDestroyImageKHR"); - return (*_eglDestroyImageKHR)(dpy, image); + struct egl_image *img = image; + EGLBoolean ret = (*_eglDestroyImageKHR)(dpy, img ? img->egl_image : NULL); + if (ret == EGL_TRUE) { + free(img); + return EGL_TRUE; + } + return ret; } - // vim:ts=4:sw=4:noexpandtab diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/eglhybris.h libhybris-0.1.0+git20151016+6d424c9/hybris/egl/eglhybris.h --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/eglhybris.h 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/eglhybris.h 2015-07-30 07:51:13.000000000 +0000 @@ -18,10 +18,10 @@ #ifndef EGL_HYBRIS_H_ #define EGL_HYBRIS_H_ -#include +#include /* Needed for ICS window.h */ #include -#include +#include #ifdef __cplusplus extern "C" { @@ -31,6 +31,12 @@ int hybris_unregister_buffer_handle(buffer_handle_t handle); void hybris_dump_buffer_to_file(struct ANativeWindowBuffer *buf); +void *hybris_android_egl_dlsym(const char *symbol); +int hybris_egl_has_mapping(EGLSurface surface); +EGLNativeWindowType hybris_egl_get_mapping(EGLSurface surface); + +struct _EGLDisplay *hybris_egl_display_get_mapping(EGLDisplay dpy); + #ifdef __cplusplus } #endif diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/helper.cpp libhybris-0.1.0+git20151016+6d424c9/hybris/egl/helper.cpp --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/helper.cpp 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/helper.cpp 2015-07-30 07:51:13.000000000 +0000 @@ -40,6 +40,17 @@ return (_surface_window_map.find(surface) != _surface_window_map.end()); } +EGLNativeWindowType egl_helper_get_mapping(EGLSurface surface) +{ + std::map::iterator it; + it = _surface_window_map.find(surface); + + /* Caller must check with egl_helper_has_mapping() before */ + assert(it != _surface_window_map.end()); + + return it->second; +} + EGLNativeWindowType egl_helper_pop_mapping(EGLSurface surface) { std::map::iterator it; diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/helper.h libhybris-0.1.0+git20151016+6d424c9/hybris/egl/helper.h --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/helper.h 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/helper.h 2015-07-30 07:51:13.000000000 +0000 @@ -36,6 +36,9 @@ /* Check if a mapping for a surface exist */ int egl_helper_has_mapping(EGLSurface surface); +/* Return (without removing) the mapping for a surface */ +EGLNativeWindowType egl_helper_get_mapping(EGLSurface surface); + /* Return and remove the mapping for a surface */ EGLNativeWindowType egl_helper_pop_mapping(EGLSurface surface); diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/egl/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -11,7 +11,7 @@ pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = egl.pc -libEGL_la_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/android -DPKGLIBDIR="\"$(pkglibdir)/\"" -I$(top_srcdir)/common -DDEFAULT_EGL_PLATFORM="\"@DEFAULT_EGL_PLATFORM@\"" +libEGL_la_CFLAGS = -I$(top_srcdir)/include $(ANDROID_HEADERS_CFLAGS) -DPKGLIBDIR="\"$(pkglibdir)/\"" -I$(top_srcdir)/common -DDEFAULT_EGL_PLATFORM="\"@DEFAULT_EGL_PLATFORM@\"" if WANT_MESA libEGL_la_CFLAGS += -DLIBHYBRIS_WANTS_MESA_X11_HEADERS endif @@ -22,7 +22,7 @@ libEGL_la_CFLAGS += -ggdb -O0 endif -libEGL_la_CXXFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/android -I$(top_srcdir)/common -DPKGLIBDIR="\"$(pkglibdir)/\"" +libEGL_la_CXXFLAGS = -I$(top_srcdir)/include $(ANDROID_HEADERS_CFLAGS) -I$(top_srcdir)/common -DPKGLIBDIR="\"$(pkglibdir)/\"" if WANT_MESA libEGL_la_CXXFLAGS += -DLIBHYBRIS_WANTS_MESA_X11_HEADERS endif diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/eglplatformcommon.cpp libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/eglplatformcommon.cpp --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/eglplatformcommon.cpp 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/eglplatformcommon.cpp 2015-07-30 07:51:13.000000000 +0000 @@ -1,8 +1,9 @@ +#include #include #include #include #include -#include +#include #include #include #include "config.h" @@ -21,15 +22,32 @@ #include "windowbuffer.h" +static struct ws_egl_interface *my_egl_interface; static gralloc_module_t *my_gralloc = 0; static alloc_device_t *my_alloc = 0; -extern "C" void eglplatformcommon_init(gralloc_module_t *gralloc, alloc_device_t *allocdevice) +extern "C" void eglplatformcommon_init(struct ws_egl_interface *egl_iface, gralloc_module_t *gralloc, alloc_device_t *allocdevice) { + my_egl_interface = egl_iface; my_gralloc = gralloc; my_alloc = allocdevice; } +extern "C" void *hybris_android_egl_dlsym(const char *symbol) +{ + return (*my_egl_interface->android_egl_dlsym)(symbol); +} + +extern "C" int hybris_egl_has_mapping(EGLSurface surface) +{ + return (*my_egl_interface->has_mapping)(surface); +} + +EGLNativeWindowType hybris_egl_get_mapping(EGLSurface surface) +{ + return (*my_egl_interface->get_mapping)(surface); +} + extern "C" int hybris_register_buffer_handle(buffer_handle_t handle) { if (!my_gralloc) @@ -64,6 +82,8 @@ snprintf(b, 1020, "vaddr.%p.%p.%i.%is%ix%ix%i", buf, vaddr, cnt, buf->width, buf->stride, buf->height, bytes_pp); cnt++; int fd = ::open(b, O_WRONLY|O_CREAT, S_IRWXU); + if(fd < 0) + return; ::write(fd, vaddr, buf->stride * buf->height * bytes_pp); ::close(fd); @@ -75,7 +95,7 @@ extern "C" EGLBoolean eglplatformcommon_eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display) { assert(my_gralloc != NULL); - server_wlegl_create(display, my_gralloc); + server_wlegl_create(display, my_gralloc, my_alloc); return EGL_TRUE; } @@ -85,7 +105,7 @@ } extern "C" EGLBoolean eglplatformcommon_eglQueryWaylandBufferWL(EGLDisplay dpy, - struct wl_buffer *buffer, EGLint attribute, EGLint *value) + struct wl_resource *buffer, EGLint attribute, EGLint *value) { server_wlegl_buffer *buf = server_wlegl_buffer_from(buffer); ANativeWindowBuffer* anwb = (ANativeWindowBuffer *) buf->buf; @@ -114,8 +134,73 @@ return EGL_FALSE ; } +// Added as part of EGL_HYBRIS_WL_acquire_native_buffer. Buffers are released +// and decRef'ed using eglHybrisReleaseNativeBuffer +extern "C" EGLBoolean eglplatformcommon_eglHybrisAcquireNativeBufferWL(EGLDisplay dpy, struct wl_resource *wlBuffer, EGLClientBuffer *buffer) + { + if (!buffer) + return EGL_FALSE; + server_wlegl_buffer *buf = server_wlegl_buffer_from(wlBuffer); + if (!buf->buf->isAllocated()) { + // We only return the handles from buffers which are allocated server side. This is because some + // hardware compositors have problems with client-side allocated buffers. + buffer = 0; + return EGL_FALSE; + } + ANativeWindowBuffer* anwb = (ANativeWindowBuffer *) buf->buf; + anwb->common.incRef(&anwb->common); + *buffer = (EGLClientBuffer *) anwb; + return EGL_TRUE; +} + #endif +// Added as part of EGL_HYBRIS_native_buffer2 +extern "C" EGLBoolean eglplatformcommon_eglHybrisNativeBufferHandle(EGLDisplay dpy, EGLClientBuffer buffer, void **handle) +{ + if (!buffer || !handle) + return EGL_FALSE; + ANativeWindowBuffer *anwb = (ANativeWindowBuffer *) buffer; + *handle = (void *) anwb->handle; + return EGL_TRUE; +} + +extern "C" void eglplatformcommon_eglHybrisGetNativeBufferInfo(EGLClientBuffer buffer, int *num_ints, int *num_fds) +{ + RemoteWindowBuffer *buf = static_cast((ANativeWindowBuffer *) buffer); + *num_ints = buf->handle->numInts; + *num_fds = buf->handle->numFds; +} + +extern "C" void eglplatformcommon_eglHybrisSerializeNativeBuffer(EGLClientBuffer buffer, int *ints, int *fds) +{ + RemoteWindowBuffer *buf = static_cast((ANativeWindowBuffer *) buffer); + memcpy(ints, buf->handle->data + buf->handle->numFds, buf->handle->numInts * sizeof(int)); + memcpy(fds, buf->handle->data, buf->handle->numFds * sizeof(int)); +} + +extern "C" EGLBoolean eglplatformcommon_eglHybrisCreateRemoteBuffer(EGLint width, EGLint height, EGLint usage, EGLint format, EGLint stride, + int num_ints, int *ints, int num_fds, int *fds, EGLClientBuffer *buffer) +{ + assert(my_gralloc != NULL); + + native_handle_t *native = native_handle_create(num_fds, num_ints); + memcpy(&native->data[0], fds, num_fds * sizeof(int)); + memcpy(&native->data[num_fds], ints, num_ints * sizeof(int)); + + int ret = my_gralloc->registerBuffer(my_gralloc, (buffer_handle_t)native); + + if (ret == 0) + { + RemoteWindowBuffer *buf = new RemoteWindowBuffer(width, height, stride, format, usage, (buffer_handle_t)native, my_gralloc, my_alloc); + buf->common.incRef(&buf->common); + *buffer = (EGLClientBuffer) static_cast(buf); + return EGL_TRUE; + } + else + return EGL_FALSE; +} + extern "C" EGLBoolean eglplatformcommon_eglHybrisCreateNativeBuffer(EGLint width, EGLint height, EGLint usage, EGLint format, EGLint *stride, EGLClientBuffer *buffer) { int ret; @@ -129,8 +214,9 @@ if (ret == 0) { - RemoteWindowBuffer *buf = new RemoteWindowBuffer(width, height, _stride, format, usage, _handle, my_gralloc); + RemoteWindowBuffer *buf = new RemoteWindowBuffer(width, height, _stride, format, usage, _handle, my_gralloc, my_alloc); buf->common.incRef(&buf->common); + buf->setAllocated(true); *buffer = (EGLClientBuffer) static_cast(buf); *stride = _stride; return EGL_TRUE; @@ -185,9 +271,9 @@ static int debugenvchecked = 0; if (*target == EGL_WAYLAND_BUFFER_WL) { - server_wlegl_buffer *buf = server_wlegl_buffer_from((struct wl_buffer *)*buffer); - HYBRIS_TRACE_BEGIN("eglplatformcommon", "Wayland_eglImageKHR", "-resource@%i", ((struct wl_buffer *)*buffer)->resource.object.id); - HYBRIS_TRACE_END("eglplatformcommon", "Wayland_eglImageKHR", "-resource@%i", ((struct wl_buffer *)*buffer)->resource.object.id); + server_wlegl_buffer *buf = server_wlegl_buffer_from((struct wl_resource *)*buffer); + HYBRIS_TRACE_BEGIN("eglplatformcommon", "Wayland_eglImageKHR", "-resource@%i", wl_resource_get_id((struct wl_resource *)*buffer)); + HYBRIS_TRACE_END("eglplatformcommon", "Wayland_eglImageKHR", "-resource@%i", wl_resource_get_id((struct wl_resource *)*buffer)); if (debugenvchecked == 0) { if (getenv("HYBRIS_WAYLAND_KHR_DUMP_BUFFERS") != NULL) @@ -223,6 +309,11 @@ return (__eglMustCastToProperFunctionPointerType)eglplatformcommon_eglQueryWaylandBufferWL; } else + if (strcmp(procname, "eglHybrisAcquireNativeBufferWL") == 0) + { + return (__eglMustCastToProperFunctionPointerType) eglplatformcommon_eglHybrisAcquireNativeBufferWL; + } + else #endif if (strcmp(procname, "eglHybrisCreateNativeBuffer") == 0) { @@ -243,6 +334,26 @@ { return (__eglMustCastToProperFunctionPointerType)eglplatformcommon_eglHybrisReleaseNativeBuffer; } + else + if (strcmp(procname, "eglHybrisGetNativeBufferInfo") == 0) + { + return (__eglMustCastToProperFunctionPointerType)eglplatformcommon_eglHybrisGetNativeBufferInfo; + } + else + if (strcmp(procname, "eglHybrisSerializeNativeBuffer") == 0) + { + return (__eglMustCastToProperFunctionPointerType)eglplatformcommon_eglHybrisSerializeNativeBuffer; + } + else + if (strcmp(procname, "eglHybrisCreateRemoteBuffer") == 0) + { + return (__eglMustCastToProperFunctionPointerType)eglplatformcommon_eglHybrisCreateRemoteBuffer; + } + else + if (strcmp(procname, "eglHybrisNativeBufferHandle") == 0) + { + return (__eglMustCastToProperFunctionPointerType)eglplatformcommon_eglHybrisNativeBufferHandle; + } return NULL; } @@ -253,8 +364,7 @@ { const char *ret = (*real_eglQueryString)(dpy, name); static char eglextensionsbuf[512]; - assert(ret != NULL); - snprintf(eglextensionsbuf, 510, "%sEGL_HYBRIS_native_buffer %s", ret, + snprintf(eglextensionsbuf, 510, "%sEGL_HYBRIS_native_buffer2 EGL_HYBRIS_WL_acquire_native_buffer %s", ret ? ret : "", #ifdef WANT_WAYLAND "EGL_WL_bind_wayland_display " #else diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/eglplatformcommon.h libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/eglplatformcommon.h --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/eglplatformcommon.h 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/eglplatformcommon.h 2015-07-30 07:51:13.000000000 +0000 @@ -1,10 +1,10 @@ #ifndef __EGLPLATFORMCOMMON_H #define __EGLPLATFORMCOMMON_H #include -#include +#include #include -void eglplatformcommon_init(gralloc_module_t *gralloc, alloc_device_t *allocdevice); +void eglplatformcommon_init(struct ws_egl_interface *egl_iface, gralloc_module_t *gralloc, alloc_device_t *allocdevice); __eglMustCastToProperFunctionPointerType eglplatformcommon_eglGetProcAddress(const char *procname); void eglplatformcommon_passthroughImageKHR(EGLContext *ctx, EGLenum *target, EGLClientBuffer *buffer, const EGLint **attrib_list); const char *eglplatformcommon_eglQueryString(EGLDisplay dpy, EGLint name, const char *(*real_eglQueryString)(EGLDisplay dpy, EGLint name)); diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/hybris_nativebufferext.h libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/hybris_nativebufferext.h --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/hybris_nativebufferext.h 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/hybris_nativebufferext.h 2015-07-30 07:51:13.000000000 +0000 @@ -24,6 +24,12 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLHYBRISUNLOCKNATIVEBUFFERPROC)(EGLClientBuffer buffer); typedef EGLBoolean (EGLAPIENTRYP PFNEGLHYBRISRELEASENATIVEBUFFERPROC)(EGLClientBuffer buffer); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLHYBRISGETNATIVEBUFFERINFOPROC)(EGLClientBuffer buffer, int *num_ints, int *num_fds); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLHYBRISSERIALIZENATIVEBUFFERPROC)(EGLClientBuffer buffer, int *ints, int *fds); + +typedef EGLBoolean (EGLAPIENTRYP PFNEGLHYBRISCREATEREMOTEBUFFERPROC)(EGLint width, EGLint height, EGLint usage, EGLint format, EGLint stride, + int num_ints, int *ints, int num_fds, int *fds, EGLClientBuffer *buffer); + enum { /* buffer is never read in software */ HYBRIS_USAGE_SW_READ_NEVER = 0x00000000, diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -37,7 +37,7 @@ libwayland_egl_la_SOURCES = wayland-egl.c -libwayland_egl_la_CFLAGS = -I. -I$(top_srcdir)/include -I$(top_srcdir)/include/android $(WAYLAND_CLIENT_CFLAGS) $(WAYLAND_SERVER_CFLAGS) +libwayland_egl_la_CFLAGS = -I. -I$(top_srcdir)/include $(ANDROID_HEADERS_CFLAGS) $(WAYLAND_CLIENT_CFLAGS) $(WAYLAND_SERVER_CFLAGS) if WANT_TRACE libwayland_egl_la_CFLAGS += -DDEBUG endif @@ -45,7 +45,7 @@ libwayland_egl_la_CFLAGS += -ggdb -O0 endif -libwayland_egl_la_CXXFLAGS = -I. -I$(top_srcdir)/include -I$(top_srcdir)/include/android $(WAYLAND_CLIENT_CFLAGS) $(WAYLAND_SERVER_CFLAGS) +libwayland_egl_la_CXXFLAGS = -I. -I$(top_srcdir)/include $(ANDROID_HEADERS_CFLAGS) $(WAYLAND_CLIENT_CFLAGS) $(WAYLAND_SERVER_CFLAGS) if WANT_TRACE libwayland_egl_la_CXXFLAGS += -DDEBUG endif @@ -57,9 +57,9 @@ endif -libhybris_eglplatformcommon_la_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/android -I$(top_srcdir)/egl -I$(top_srcdir)/common/ +libhybris_eglplatformcommon_la_CFLAGS = -I$(top_srcdir)/include $(ANDROID_HEADERS_CFLAGS) -I$(top_srcdir)/egl -I$(top_srcdir)/common/ if WANT_WAYLAND -libhybris_eglplatformcommon_la_CFLAGS += $(WAYLAND_CLIENT_CFLAGS) $(WAYLAND_SERVER_CFLAGS) -I$(top_srcdir)/include/android +libhybris_eglplatformcommon_la_CFLAGS += $(WAYLAND_CLIENT_CFLAGS) $(WAYLAND_SERVER_CFLAGS) $(ANDROID_HEADERS_CFLAGS) endif if WANT_MESA @@ -73,13 +73,13 @@ endif -libhybris_eglplatformcommon_la_CXXFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/egl -I$(top_srcdir)/include/android -I$(top_srcdir)/common/ +libhybris_eglplatformcommon_la_CXXFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/egl $(ANDROID_HEADERS_CFLAGS) -I$(top_srcdir)/common/ if WANT_MESA libhybris_eglplatformcommon_la_CXXFLAGS += -DLIBHYBRIS_WANTS_MESA_X11_HEADERS endif if WANT_WAYLAND -libhybris_eglplatformcommon_la_CXXFLAGS += $(WAYLAND_CLIENT_CFLAGS) $(WAYLAND_SERVER_CFLAGS) -I$(top_srcdir)/include/android +libhybris_eglplatformcommon_la_CXXFLAGS += $(WAYLAND_CLIENT_CFLAGS) $(WAYLAND_SERVER_CFLAGS) $(ANDROID_HEADERS_CFLAGS) endif if WANT_TRACE @@ -92,6 +92,15 @@ $(top_builddir)/common/libhybris-common.la \ -version-info "1":"0":"0" +if HAS_ANDROID_4_2_0 +libhybris_eglplatformcommon_la_LDFLAGS += $(top_builddir)/libsync/libsync.la +endif + +if HAS_ANDROID_5_0_0 +libhybris_eglplatformcommon_la_LDFLAGS += $(top_builddir)/libsync/libsync.la +endif + + eglplatformcommondir = $(includedir)/hybris/eglplatformcommon eglplatformcommon_HEADERS = \ support.h \ diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/native_handle.c libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/native_handle.c --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/native_handle.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/native_handle.c 2015-07-30 07:51:13.000000000 +0000 @@ -16,13 +16,14 @@ #define LOG_TAG "NativeHandle" +#include #include #include #include #include #include -#include +#include native_handle_t* native_handle_create(int numFds, int numInts) { diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/nativewindowbase.cpp libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/nativewindowbase.cpp --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/nativewindowbase.cpp 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/nativewindowbase.cpp 2015-07-30 07:51:13.000000000 +0000 @@ -1,17 +1,25 @@ +#include #include -#include -#include +#include +#include #include "support.h" #include +#if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=2 || ANDROID_VERSION_MAJOR>=5 +extern "C" { +#include +} +#endif + + #include "nativewindowbase.h" #include "logging.h" -#include - #define TRACE(message, ...) HYBRIS_DEBUG_LOG(EGL, message, ##__VA_ARGS__) + + BaseNativeWindowBuffer::BaseNativeWindowBuffer() { TRACE("%p", this); @@ -91,7 +99,7 @@ ANativeWindow::setSwapInterval = _setSwapInterval; -#if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=2 +#if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=2 || ANDROID_VERSION_MAJOR>=5 ANativeWindow::lockBuffer_DEPRECATED = &_lockBuffer_DEPRECATED; ANativeWindow::dequeueBuffer_DEPRECATED = &_dequeueBuffer_DEPRECATED; ANativeWindow::queueBuffer_DEPRECATED = &_queueBuffer_DEPRECATED; @@ -153,7 +161,17 @@ BaseNativeWindowBuffer* temp = static_cast(*buffer); int fenceFd = -1; int ret = static_cast(window)->dequeueBuffer(&temp, &fenceFd); + *buffer = static_cast(temp); + +#if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=2 || ANDROID_VERSION_MAJOR>=5 + if (fenceFd >= 0) + { + sync_wait(fenceFd, -1); + close(fenceFd); + } +#endif + return ret; } @@ -239,7 +257,7 @@ case NATIVE_WINDOW_DEFAULT_WIDTH: return "NATIVE_WINDOW_DEFAULT_WIDTH"; case NATIVE_WINDOW_DEFAULT_HEIGHT: return "NATIVE_WINDOW_DEFAULT_HEIGHT"; case NATIVE_WINDOW_TRANSFORM_HINT: return "NATIVE_WINDOW_TRANSFORM_HINT"; -#if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=1 +#if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=1 || ANDROID_VERSION_MAJOR>=5 case NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND: return "NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND"; #endif default: return "NATIVE_UNKNOWN_QUERY"; @@ -353,7 +371,7 @@ case NATIVE_WINDOW_API_DISCONNECT : // 14, /* private */ TRACE("api disconnect"); break; -#if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=1 +#if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=1 || ANDROID_VERSION_MAJOR>=5 case NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS : // 15, /* private */ TRACE("set buffers user dimensions"); break; diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/nativewindowbase.h libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/nativewindowbase.h --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/nativewindowbase.h 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/nativewindowbase.h 2015-07-30 07:51:13.000000000 +0000 @@ -3,7 +3,7 @@ /* for ICS window.h */ #include -#include +#include #include #include "support.h" #include diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/server_wlegl_buffer.cpp libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/server_wlegl_buffer.cpp --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/server_wlegl_buffer.cpp 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/server_wlegl_buffer.cpp 2015-07-30 07:51:13.000000000 +0000 @@ -20,6 +20,7 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include #include #include @@ -37,27 +38,22 @@ }; server_wlegl_buffer * -server_wlegl_buffer_from(struct wl_buffer *buffer) +server_wlegl_buffer_from(struct wl_resource *buffer) { - if (buffer->resource.object.implementation != - (void (**)(void)) &server_wlegl_buffer_impl) - return NULL; - - return container_of(buffer, server_wlegl_buffer, base); + return static_cast(wl_resource_get_user_data(buffer)); } static void server_wlegl_buffer_dtor(struct wl_resource *resource) { - struct wl_buffer *base = - reinterpret_cast(resource->data); - server_wlegl_buffer *buffer = server_wlegl_buffer_from(base); + server_wlegl_buffer *buffer = server_wlegl_buffer_from(resource); buffer->buf->common.decRef(&buffer->buf->common); delete buffer; } server_wlegl_buffer * -server_wlegl_buffer_create(uint32_t id, +server_wlegl_buffer_create(wl_client *client, + uint32_t id, int32_t width, int32_t height, int32_t stride, @@ -69,29 +65,42 @@ server_wlegl_buffer *buffer = new server_wlegl_buffer; int ret; - memset(buffer, 0, sizeof(*buffer)); - buffer->wlegl = wlegl; - - buffer->base.resource.object.id = id; - buffer->base.resource.object.interface = &wl_buffer_interface; - buffer->base.resource.object.implementation = - (void (**)(void)) &server_wlegl_buffer_impl; - - buffer->base.resource.data = &buffer->base; - buffer->base.resource.destroy = server_wlegl_buffer_dtor; - - buffer->base.width = width; - buffer->base.height = height; + buffer->resource = wl_resource_create(client, &wl_buffer_interface, 1, id); + wl_resource_set_implementation(buffer->resource, &server_wlegl_buffer_impl, buffer, server_wlegl_buffer_dtor); ret = wlegl->gralloc->registerBuffer(wlegl->gralloc, handle); if (ret) { delete buffer; return NULL; } - + + buffer->buf = new RemoteWindowBuffer( + width, height, stride, format, usage, handle, wlegl->gralloc, NULL); + buffer->buf->common.incRef(&buffer->buf->common); + return buffer; +} + +server_wlegl_buffer * +server_wlegl_buffer_create_server(wl_client *client, + int32_t width, + int32_t height, + int32_t stride, + int32_t format, + int32_t usage, + buffer_handle_t handle, + server_wlegl *wlegl) +{ + server_wlegl_buffer *buffer = new server_wlegl_buffer; + int ret; + + buffer->wlegl = wlegl; + buffer->resource = wl_resource_create(client, &wl_buffer_interface, 1, 0); + wl_resource_set_implementation(buffer->resource, &server_wlegl_buffer_impl, buffer, server_wlegl_buffer_dtor); + buffer->buf = new RemoteWindowBuffer( - width, height, stride, format, usage, handle, wlegl->gralloc); + width, height, stride, format, usage, handle, wlegl->gralloc, wlegl->alloc); + buffer->buf->setAllocated(true); buffer->buf->common.incRef(&buffer->buf->common); return buffer; } diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/server_wlegl_buffer.h libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/server_wlegl_buffer.h --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/server_wlegl_buffer.h 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/server_wlegl_buffer.h 2015-07-30 07:51:13.000000000 +0000 @@ -33,18 +33,23 @@ struct server_wlegl; struct server_wlegl_buffer { - struct wl_buffer base; + struct wl_resource *resource; server_wlegl *wlegl; RemoteWindowBuffer *buf; }; server_wlegl_buffer * -server_wlegl_buffer_create(uint32_t id, int32_t width, int32_t height, +server_wlegl_buffer_create(wl_client *client, uint32_t id, int32_t width, int32_t height, int32_t stride, int32_t format, int32_t usage, buffer_handle_t handle, server_wlegl *wlegl); server_wlegl_buffer * -server_wlegl_buffer_from(struct wl_buffer *); +server_wlegl_buffer_create_server(wl_client *client, int32_t width, int32_t height, + int32_t stride, int32_t format, int32_t usage, + buffer_handle_t handle, server_wlegl *wlegl); + +server_wlegl_buffer * +server_wlegl_buffer_from(struct wl_resource *); #endif /* SERVER_WLEGL_BUFFER_H */ diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/server_wlegl.cpp libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/server_wlegl.cpp --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/server_wlegl.cpp 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/server_wlegl.cpp 2015-07-30 07:51:13.000000000 +0000 @@ -20,6 +20,7 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include #include #include @@ -39,7 +40,7 @@ static inline server_wlegl * server_wlegl_from(struct wl_resource *resource) { - return reinterpret_cast(resource->data); + return reinterpret_cast(wl_resource_get_user_data(resource)); } static void @@ -97,7 +98,7 @@ return; } - buffer = server_wlegl_buffer_create(id, width, height, stride, + buffer = server_wlegl_buffer_create(client, id, width, height, stride, format, usage, native, wlegl); if (!buffer) { native_handle_close((native_handle_t *)native); @@ -107,13 +108,49 @@ "invalid native handle"); return; } +} + +static void +server_wlegl_get_server_buffer_handle(wl_client *client, wl_resource *res, uint32_t id, int32_t width, int32_t height, int32_t format, int32_t usage) +{ + if (width == 0 || height == 0) { + wl_resource_post_error(res, 0, "invalid buffer size: %u,%u\n", width, height); + return; + } + + server_wlegl *wlegl = server_wlegl_from(res); + + wl_resource *resource = wl_resource_create(client, &android_wlegl_server_buffer_handle_interface, wl_resource_get_version(res), id); + + buffer_handle_t _handle; + int _stride; + + usage |= GRALLOC_USAGE_HW_COMPOSER; + + int ret = wlegl->alloc->alloc(wlegl->alloc, width, height, format, usage, &_handle, &_stride); + server_wlegl_buffer *buffer = server_wlegl_buffer_create_server(client, width, height, _stride, format, usage, _handle, wlegl); + + struct wl_array ints; + int *ints_data; + wl_array_init(&ints); + ints_data = (int*) wl_array_add(&ints, _handle->numInts * sizeof(int)); + memcpy(ints_data, _handle->data + _handle->numFds, _handle->numInts * sizeof(int)); + + android_wlegl_server_buffer_handle_send_buffer_ints(resource, &ints); + wl_array_release(&ints); + + for (int i = 0; i < _handle->numFds; i++) { + android_wlegl_server_buffer_handle_send_buffer_fd(resource, _handle->data[i]); + } - wl_client_add_resource(client, &buffer->base.resource); + android_wlegl_server_buffer_handle_send_buffer(resource, buffer->resource, format, _stride); + wl_resource_destroy(resource); } static const struct android_wlegl_interface server_wlegl_impl = { server_wlegl_create_handle, server_wlegl_create_buffer, + server_wlegl_get_server_buffer_handle, }; static void @@ -123,12 +160,12 @@ server_wlegl *wlegl = reinterpret_cast(data); struct wl_resource *resource; - resource = wl_client_add_object(client, &android_wlegl_interface, - &server_wlegl_impl, id, wlegl); + resource = wl_resource_create(client, &android_wlegl_interface, version, id); + wl_resource_set_implementation(resource, &server_wlegl_impl, wlegl, 0); } server_wlegl * -server_wlegl_create(struct wl_display *display, gralloc_module_t *gralloc) +server_wlegl_create(struct wl_display *display, gralloc_module_t *gralloc, alloc_device_t *alloc) { struct server_wlegl *wlegl; int ret; @@ -136,10 +173,10 @@ wlegl = new server_wlegl; wlegl->display = display; - wlegl->global = wl_display_add_global(display, - &android_wlegl_interface, + wlegl->global = wl_global_create(display, &android_wlegl_interface, 2, wlegl, server_wlegl_bind); wlegl->gralloc = (const gralloc_module_t *)gralloc; + wlegl->alloc = alloc; return wlegl; } diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/server_wlegl.h libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/server_wlegl.h --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/server_wlegl.h 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/server_wlegl.h 2015-07-30 07:51:13.000000000 +0000 @@ -37,14 +37,9 @@ struct server_wlegl; server_wlegl * -server_wlegl_create(struct wl_display *wldpy, gralloc_module_t *gralloc); +server_wlegl_create(struct wl_display *wldpy, gralloc_module_t *gralloc, alloc_device_t *alloc); void server_wlegl_destroy(server_wlegl *wlegl); -EGLImageKHR -egl_create_image_wl(EGLDisplay egldisplay, - struct wl_buffer *user_buffer, - const EGLint *attrib_list); - #endif /* SERVER_WLEGL_H */ diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/server_wlegl_handle.cpp libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/server_wlegl_handle.cpp --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/server_wlegl_handle.cpp 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/server_wlegl_handle.cpp 2015-07-30 07:51:13.000000000 +0000 @@ -20,6 +20,7 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include #include #include #include diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/server_wlegl_private.h libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/server_wlegl_private.h --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/server_wlegl_private.h 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/server_wlegl_private.h 2015-07-30 07:51:13.000000000 +0000 @@ -34,6 +34,7 @@ struct wl_global *global; const gralloc_module_t *gralloc; + alloc_device_t *alloc; }; #endif /* SERVER_WLEGL_PRIVATE_H */ diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/wayland-android-client-protocol.h libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/wayland-android-client-protocol.h --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/wayland-android-client-protocol.h 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/wayland-android-client-protocol.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,149 +0,0 @@ -/* - * Copyright © 2012 Collabora, Ltd. - * - * Permission to use, copy, modify, distribute, and sell this - * software and its documentation for any purpose is hereby granted - * without fee, provided that the above copyright notice appear in - * all copies and that both that copyright notice and this permission - * notice appear in supporting documentation, and that the name of - * the copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF - * THIS SOFTWARE. - */ - -#ifndef ANDROID_CLIENT_PROTOCOL_H -#define ANDROID_CLIENT_PROTOCOL_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include "wayland-client.h" - -struct wl_client; -struct wl_resource; - -struct android_wlegl; -struct android_wlegl_handle; - -extern const struct wl_interface android_wlegl_interface; -extern const struct wl_interface android_wlegl_handle_interface; - -#ifndef ANDROID_WLEGL_ERROR_ENUM -#define ANDROID_WLEGL_ERROR_ENUM -enum android_wlegl_error { - ANDROID_WLEGL_ERROR_BAD_HANDLE = 0, - ANDROID_WLEGL_ERROR_BAD_VALUE = 1, -}; -#endif /* ANDROID_WLEGL_ERROR_ENUM */ - -#define ANDROID_WLEGL_CREATE_HANDLE 0 -#define ANDROID_WLEGL_CREATE_BUFFER 1 - -static inline void -android_wlegl_set_user_data(struct android_wlegl *android_wlegl, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) android_wlegl, user_data); -} - -static inline void * -android_wlegl_get_user_data(struct android_wlegl *android_wlegl) -{ - return wl_proxy_get_user_data((struct wl_proxy *) android_wlegl); -} - -static inline void -android_wlegl_destroy(struct android_wlegl *android_wlegl) -{ - wl_proxy_destroy((struct wl_proxy *) android_wlegl); -} - -static inline struct android_wlegl_handle * -android_wlegl_create_handle(struct android_wlegl *android_wlegl, int32_t num_fds, struct wl_array *ints) -{ - struct wl_proxy *id; - - id = wl_proxy_create((struct wl_proxy *) android_wlegl, - &android_wlegl_handle_interface); - if (!id) - return NULL; - - wl_proxy_marshal((struct wl_proxy *) android_wlegl, - ANDROID_WLEGL_CREATE_HANDLE, id, num_fds, ints); - - return (struct android_wlegl_handle *) id; -} - -static inline struct wl_buffer * -android_wlegl_create_buffer(struct android_wlegl *android_wlegl, int32_t width, int32_t height, int32_t stride, int32_t format, int32_t usage, struct android_wlegl_handle *native_handle) -{ - struct wl_proxy *id; - - id = wl_proxy_create((struct wl_proxy *) android_wlegl, - &wl_buffer_interface); - if (!id) - return NULL; - - wl_proxy_marshal((struct wl_proxy *) android_wlegl, - ANDROID_WLEGL_CREATE_BUFFER, id, width, height, stride, format, usage, native_handle); - - return (struct wl_buffer *) id; -} - -#ifndef ANDROID_WLEGL_HANDLE_ERROR_ENUM -#define ANDROID_WLEGL_HANDLE_ERROR_ENUM -enum android_wlegl_handle_error { - ANDROID_WLEGL_HANDLE_ERROR_TOO_MANY_FDS = 0, -}; -#endif /* ANDROID_WLEGL_HANDLE_ERROR_ENUM */ - -#define ANDROID_WLEGL_HANDLE_ADD_FD 0 -#define ANDROID_WLEGL_HANDLE_DESTROY 1 - -static inline void -android_wlegl_handle_set_user_data(struct android_wlegl_handle *android_wlegl_handle, void *user_data) -{ - wl_proxy_set_user_data((struct wl_proxy *) android_wlegl_handle, user_data); -} - -static inline void * -android_wlegl_handle_get_user_data(struct android_wlegl_handle *android_wlegl_handle) -{ - return wl_proxy_get_user_data((struct wl_proxy *) android_wlegl_handle); -} - -static inline void -android_wlegl_handle_add_fd(struct android_wlegl_handle *android_wlegl_handle, int32_t fd) -{ - wl_proxy_marshal((struct wl_proxy *) android_wlegl_handle, - ANDROID_WLEGL_HANDLE_ADD_FD, fd); -} - -static inline void -android_wlegl_handle_destroy(struct android_wlegl_handle *android_wlegl_handle) -{ - wl_proxy_marshal((struct wl_proxy *) android_wlegl_handle, - ANDROID_WLEGL_HANDLE_DESTROY); - - wl_proxy_destroy((struct wl_proxy *) android_wlegl_handle); -} - -#ifdef __cplusplus -} -#endif - -#endif diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/wayland-android-protocol.c libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/wayland-android-protocol.c --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/wayland-android-protocol.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/wayland-android-protocol.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,69 +0,0 @@ -/* - * Copyright © 2012 Collabora, Ltd. - * - * Permission to use, copy, modify, distribute, and sell this - * software and its documentation for any purpose is hereby granted - * without fee, provided that the above copyright notice appear in - * all copies and that both that copyright notice and this permission - * notice appear in supporting documentation, and that the name of - * the copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF - * THIS SOFTWARE. - */ - -#include -#include -#include "wayland-util.h" - -extern const struct wl_interface android_wlegl_handle_interface; -extern const struct wl_interface wl_buffer_interface; -extern const struct wl_interface android_wlegl_handle_interface; - -static const struct wl_interface *types[] = { - NULL, - &android_wlegl_handle_interface, - NULL, - NULL, - &wl_buffer_interface, - NULL, - NULL, - NULL, - NULL, - NULL, - &android_wlegl_handle_interface, -}; - -static const struct wl_message android_wlegl_requests[] = { - { "create_handle", "nia", types + 1 }, - { "create_buffer", "niiiiio", types + 4 }, -}; - -WL_EXPORT const struct wl_interface android_wlegl_interface = { - "android_wlegl", 1, - 2, android_wlegl_requests, - 0, NULL, -}; - -static const struct wl_message android_wlegl_handle_requests[] = { - { "add_fd", "h", types + 0 }, - { "destroy", "", types + 0 }, -}; - -WL_EXPORT const struct wl_interface android_wlegl_handle_interface = { - "android_wlegl_handle", 1, - 2, android_wlegl_handle_requests, - 0, NULL, -}; - diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/wayland-android-server-protocol.h libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/wayland-android-server-protocol.h --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/wayland-android-server-protocol.h 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/wayland-android-server-protocol.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,142 +0,0 @@ -/* - * Copyright © 2012 Collabora, Ltd. - * - * Permission to use, copy, modify, distribute, and sell this - * software and its documentation for any purpose is hereby granted - * without fee, provided that the above copyright notice appear in - * all copies and that both that copyright notice and this permission - * notice appear in supporting documentation, and that the name of - * the copyright holders not be used in advertising or publicity - * pertaining to distribution of the software without specific, - * written prior permission. The copyright holders make no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied - * warranty. - * - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS - * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND - * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN - * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, - * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF - * THIS SOFTWARE. - */ - -#ifndef ANDROID_SERVER_PROTOCOL_H -#define ANDROID_SERVER_PROTOCOL_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include "wayland-util.h" - -struct wl_client; -struct wl_resource; - -struct android_wlegl; -struct android_wlegl_handle; - -extern const struct wl_interface android_wlegl_interface; -extern const struct wl_interface android_wlegl_handle_interface; - -#ifndef ANDROID_WLEGL_ERROR_ENUM -#define ANDROID_WLEGL_ERROR_ENUM -enum android_wlegl_error { - ANDROID_WLEGL_ERROR_BAD_HANDLE = 0, - ANDROID_WLEGL_ERROR_BAD_VALUE = 1, -}; -#endif /* ANDROID_WLEGL_ERROR_ENUM */ - -/** - * android_wlegl - Android EGL graphics buffer support - * @create_handle: Create an Android native_handle_t object - * @create_buffer: Create a wl_buffer from the native handle - * - * Interface used in the Android wrapper libEGL to share graphics buffers - * between the server and the client. - */ -struct android_wlegl_interface { - /** - * create_handle - Create an Android native_handle_t object - * @id: (none) - * @num_fds: (none) - * @ints: an array of int32_t - * - * This creator method initialises the native_handle_t object - * with everything except the file descriptors, which have to be - * submitted separately. - */ - void (*create_handle)(struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - int32_t num_fds, - struct wl_array *ints); - /** - * create_buffer - Create a wl_buffer from the native handle - * @id: (none) - * @width: (none) - * @height: (none) - * @stride: (none) - * @format: (none) - * @usage: (none) - * @native_handle: (none) - * - * Pass the Android native_handle_t to the server and attach it - * to the new wl_buffer object. - * - * The android_wlegl_handle object must be destroyed immediately - * after this request. - */ - void (*create_buffer)(struct wl_client *client, - struct wl_resource *resource, - uint32_t id, - int32_t width, - int32_t height, - int32_t stride, - int32_t format, - int32_t usage, - struct wl_resource *native_handle); -}; - -#ifndef ANDROID_WLEGL_HANDLE_ERROR_ENUM -#define ANDROID_WLEGL_HANDLE_ERROR_ENUM -enum android_wlegl_handle_error { - ANDROID_WLEGL_HANDLE_ERROR_TOO_MANY_FDS = 0, -}; -#endif /* ANDROID_WLEGL_HANDLE_ERROR_ENUM */ - -/** - * android_wlegl_handle - An Android native_handle_t object - * @add_fd: (none) - * @destroy: (none) - * - * The Android native_handle_t is a semi-opaque object, that contains an - * EGL implementation specific number of int32 values and file descriptors. - * - * We cannot send a variable size array of file descriptors over the - * Wayland protocol, so we send them one by one. - */ -struct android_wlegl_handle_interface { - /** - * add_fd - (none) - * @fd: (none) - */ - void (*add_fd)(struct wl_client *client, - struct wl_resource *resource, - int32_t fd); - /** - * destroy - (none) - */ - void (*destroy)(struct wl_client *client, - struct wl_resource *resource); -}; - -#ifdef __cplusplus -} -#endif - -#endif diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/wayland-android.xml libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/wayland-android.xml --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/wayland-android.xml 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/wayland-android.xml 2015-07-30 07:51:13.000000000 +0000 @@ -26,7 +26,7 @@ THIS SOFTWARE. - + Interface used in the Android wrapper libEGL to share graphics buffers between the server and the client. @@ -67,6 +67,15 @@ + + + + + + + + + @@ -91,4 +100,28 @@ + + + + On creation a server_side_buffer object will immediately send + the "buffer_fd" and "buffer_ints" events needed by the client to + reference the gralloc buffer, followed by the "buffer" event carrying + the wl_buffer object. + + + + + + + + + + This event will be sent after the ints and all the fds have been sent + + + + + + + diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/wayland-egl.c libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/wayland-egl.c --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/wayland-egl.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/wayland-egl.c 2015-07-30 07:51:13.000000000 +0000 @@ -1,3 +1,4 @@ +#include #include #include @@ -30,6 +31,7 @@ egl_window->surface = surface; egl_window->resize_callback = NULL; + egl_window->free_callback = NULL; wl_egl_window_resize(egl_window, width, height, 0, 0); egl_window->attached_width = 0; egl_window->attached_height = 0; @@ -42,6 +44,8 @@ WL_EGL_EXPORT void wl_egl_window_destroy(struct wl_egl_window *egl_window) { + if (egl_window->free_callback) + egl_window->free_callback(egl_window, NULL); free(egl_window); } diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/wayland-egl-priv.h libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/wayland-egl-priv.h --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/wayland-egl-priv.h 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/wayland-egl-priv.h 2015-07-30 07:51:13.000000000 +0000 @@ -27,6 +27,7 @@ void *nativewindow; void (*resize_callback)(struct wl_egl_window *, void *); + void (*free_callback)(struct wl_egl_window *, void *); }; #ifdef __cplusplus diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/windowbuffer.cpp libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/windowbuffer.cpp --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/windowbuffer.cpp 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/windowbuffer.cpp 2015-07-30 07:51:13.000000000 +0000 @@ -20,13 +20,18 @@ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include #include #include #include "windowbuffer.h" RemoteWindowBuffer::~RemoteWindowBuffer() { + if (!m_allocated) { this->m_gralloc->unregisterBuffer(this->m_gralloc, this->handle); native_handle_close(this->handle); native_handle_delete(const_cast(this->handle)); + } else if (this->m_alloc) { + this->m_alloc->free((alloc_device_t *)this->m_alloc, this->handle); + } } diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/windowbuffer.h libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/windowbuffer.h --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/common/windowbuffer.h 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/common/windowbuffer.h 2015-07-30 07:51:13.000000000 +0000 @@ -38,7 +38,8 @@ unsigned int format, unsigned int usage, buffer_handle_t handle, - const gralloc_module_t *gralloc + const gralloc_module_t *gralloc, + const alloc_device_t *alloc = NULL ) { // Base members ANativeWindowBuffer::width = width; @@ -48,9 +49,17 @@ ANativeWindowBuffer::stride = stride; ANativeWindowBuffer::handle = handle; this->m_gralloc = gralloc; + this->m_alloc = alloc; + this->m_allocated = false; }; ~RemoteWindowBuffer(); + + void setAllocated(bool allocated) { m_allocated = allocated; } + bool isAllocated() const { return m_allocated; } + private: const gralloc_module_t *m_gralloc; + const alloc_device_t *m_alloc; + bool m_allocated; }; #endif /* WINDOWBUFFER_H */ diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/fbdev/eglplatform_fbdev.cpp libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/fbdev/eglplatform_fbdev.cpp --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/fbdev/eglplatform_fbdev.cpp 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/fbdev/eglplatform_fbdev.cpp 2015-07-30 07:51:13.000000000 +0000 @@ -1,3 +1,4 @@ +#include #include #include "fbdev_window.h" #include @@ -13,48 +14,58 @@ #include "logging.h" -static int inited = 0; static gralloc_module_t *gralloc = 0; static framebuffer_device_t *framebuffer = 0; static alloc_device_t *alloc = 0; static FbDevNativeWindow *_nativewindow = NULL; -extern "C" int fbdevws_IsValidDisplay(EGLNativeDisplayType display) +extern "C" void fbdevws_init_module(struct ws_egl_interface *egl_iface) { - if (__sync_fetch_and_add(&inited,1)==0) - { - int err; - err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **) &gralloc); - if (gralloc==NULL) { - fprintf(stderr, "failed to get gralloc module: (%s)\n",strerror(-err)); - assert(0); - } - - err = framebuffer_open((hw_module_t *) gralloc, &framebuffer); - if (err) { - fprintf(stderr, "ERROR: failed to open framebuffer: (%s)\n",strerror(-err)); - assert(0); - } - TRACE("** framebuffer_open: status=(%s) format=x%x", strerror(-err), framebuffer->format); - - err = gralloc_open((const hw_module_t *) gralloc, &alloc); - if (err) { - fprintf(stderr, "ERROR: failed to open gralloc: (%s)\n",strerror(-err)); - assert(0); - } - TRACE("** gralloc_open %p status=%s", gralloc, strerror(-err)); - eglplatformcommon_init(gralloc, alloc); + int err; + err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **) &gralloc); + if (gralloc==NULL) { + fprintf(stderr, "failed to get gralloc module: (%s)\n",strerror(-err)); + assert(0); } - return display == EGL_DEFAULT_DISPLAY; + err = framebuffer_open((hw_module_t *) gralloc, &framebuffer); + if (err) { + fprintf(stderr, "ERROR: failed to open framebuffer: (%s)\n",strerror(-err)); + assert(0); + } + TRACE("** framebuffer_open: status=(%s) format=x%x", strerror(-err), framebuffer->format); + + err = gralloc_open((const hw_module_t *) gralloc, &alloc); + if (err) { + fprintf(stderr, "ERROR: failed to open gralloc: (%s)\n",strerror(-err)); + assert(0); + } + TRACE("** gralloc_open %p status=%s", gralloc, strerror(-err)); + eglplatformcommon_init(egl_iface, gralloc, alloc); +} + +extern "C" _EGLDisplay *fbdevws_GetDisplay(EGLNativeDisplayType display) +{ + assert (gralloc != NULL); + + _EGLDisplay *dpy = 0; + if (display == EGL_DEFAULT_DISPLAY) { + dpy = new _EGLDisplay; + } + return dpy; +} + +extern "C" void fbdevws_Terminate(_EGLDisplay *dpy) +{ + delete dpy; } -extern "C" EGLNativeWindowType fbdevws_CreateWindow(EGLNativeWindowType win, EGLNativeDisplayType display) +extern "C" EGLNativeWindowType fbdevws_CreateWindow(EGLNativeWindowType win, _EGLDisplay *display) { - assert (inited >= 1); + assert (gralloc != NULL); assert (_nativewindow == NULL); - _nativewindow = new FbDevNativeWindow(gralloc, alloc, framebuffer); + _nativewindow = new FbDevNativeWindow(alloc, framebuffer); _nativewindow->common.incRef(&_nativewindow->common); return (EGLNativeWindowType) static_cast(_nativewindow); } @@ -79,13 +90,24 @@ eglplatformcommon_passthroughImageKHR(ctx, target, buffer, attrib_list); } +extern "C" void fbdevws_setSwapInterval(EGLDisplay dpy, EGLNativeWindowType win, EGLint interval) +{ + FbDevNativeWindow *window = static_cast((struct ANativeWindow *)win); + window->setSwapInterval(interval); +} + struct ws_module ws_module_info = { - fbdevws_IsValidDisplay, + fbdevws_init_module, + fbdevws_GetDisplay, + fbdevws_Terminate, fbdevws_CreateWindow, fbdevws_DestroyWindow, fbdevws_eglGetProcAddress, fbdevws_passthroughImageKHR, - eglplatformcommon_eglQueryString + eglplatformcommon_eglQueryString, + NULL, + NULL, + fbdevws_setSwapInterval, }; // vim:ts=4:sw=4:noexpandtab diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/fbdev/fbdev_window.cpp libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/fbdev/fbdev_window.cpp --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/fbdev/fbdev_window.cpp 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/fbdev/fbdev_window.cpp 2015-07-30 07:51:13.000000000 +0000 @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include "fbdev_window.h" #include "logging.h" @@ -22,8 +23,6 @@ #include #include -#include - #define FRAMEBUFFER_PARTITIONS 2 static pthread_cond_t _cond = PTHREAD_COND_INITIALIZER; @@ -65,16 +64,17 @@ //////////////////////////////////////////////////////////////////////////////// -FbDevNativeWindow::FbDevNativeWindow(gralloc_module_t* gralloc, - alloc_device_t* alloc, +FbDevNativeWindow::FbDevNativeWindow( alloc_device_t* alloc, framebuffer_device_t* fbDev) { m_alloc = alloc; m_fbDev = fbDev; m_bufFormat = m_fbDev->format; m_usage = GRALLOC_USAGE_HW_FB; + m_bufferCount = 0; + m_allocateBuffers = true; -#if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=2 +#if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=2 || ANDROID_VERSION_MAJOR>=5 if (m_fbDev->numFramebuffers>0) setBufferCount(m_fbDev->numFramebuffers); else @@ -151,6 +151,9 @@ pthread_mutex_lock(&_mutex); + if (m_allocateBuffers) + reallocateBuffers(); + HYBRIS_TRACE_BEGIN("fbdev-platform", "dequeueBuffer-wait", ""); #if defined(DEBUG) @@ -453,12 +456,9 @@ */ int FbDevNativeWindow::setUsage(int usage) { - int need_realloc = (m_usage != usage); - TRACE("usage=x%x realloc=%d", usage, need_realloc); + m_allocateBuffers = (m_usage != usage); + TRACE("usage=x%x m_allocateBuffers=%d", usage, m_allocateBuffers); m_usage = usage; - if (need_realloc) - this->setBufferCount(m_bufList.size()); - return NO_ERROR; } @@ -471,11 +471,9 @@ */ int FbDevNativeWindow::setBuffersFormat(int format) { - int need_realloc = (format != m_bufFormat); - TRACE("format=x%x realloc=%d", format, need_realloc); + m_allocateBuffers |= (format != m_bufFormat); + TRACE("format=x%x m_allocateBuffers=%d", format, m_allocateBuffers); m_bufFormat = format; - if (need_realloc) - this->setBufferCount(m_bufList.size()); return NO_ERROR; } @@ -487,12 +485,18 @@ int FbDevNativeWindow::setBufferCount(int cnt) { TRACE("cnt=%d", cnt); - int err=NO_ERROR; - pthread_mutex_lock(&_mutex); + if (m_bufferCount != cnt) { + m_bufferCount = cnt; + m_allocateBuffers = true; + } + return NO_ERROR; +} +void FbDevNativeWindow::reallocateBuffers() +{ destroyBuffers(); - for(unsigned int i = 0; i < cnt; i++) + for(unsigned int i = 0; i < m_bufferCount; i++) { FbDevNativeWindowBuffer *fbnb = new FbDevNativeWindowBuffer(m_alloc, m_fbDev->width, m_fbDev->height, m_fbDev->format, @@ -507,16 +511,15 @@ if (fbnb->status) { fbnb->common.decRef(&fbnb->common); - fprintf(stderr,"WARNING: %s: allocated only %d buffers out of %d\n", __PRETTY_FUNCTION__, m_freeBufs, cnt); + fprintf(stderr,"WARNING: %s: allocated only %d buffers out of %d\n", __PRETTY_FUNCTION__, m_freeBufs, m_bufferCount); break; } m_freeBufs++; m_bufList.push_back(fbnb); } - pthread_mutex_unlock(&_mutex); - return err; + m_allocateBuffers = false; } /* diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/fbdev/fbdev_window.h libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/fbdev/fbdev_window.h --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/fbdev/fbdev_window.h 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/fbdev/fbdev_window.h 2015-07-30 07:51:13.000000000 +0000 @@ -19,7 +19,7 @@ #include "nativewindowbase.h" #include -#include +#include #include @@ -44,13 +44,13 @@ class FbDevNativeWindow : public BaseNativeWindow { public: - FbDevNativeWindow(gralloc_module_t* gralloc, alloc_device_t* alloc, + FbDevNativeWindow(alloc_device_t* alloc, framebuffer_device_t* fbDev); ~FbDevNativeWindow(); -protected: // overloads from BaseNativeWindow virtual int setSwapInterval(int interval); +protected: virtual int dequeueBuffer(BaseNativeWindowBuffer** buffer, int* fenceFd); virtual int queueBuffer(BaseNativeWindowBuffer* buffer, int fenceFd); @@ -73,13 +73,17 @@ private: void destroyBuffers(); + void reallocateBuffers(); private: framebuffer_device_t* m_fbDev; alloc_device_t* m_alloc; unsigned int m_usage; unsigned int m_bufFormat; + unsigned int m_bufferCount; int m_freeBufs; + bool m_allocateBuffers; + std::list m_bufList; FbDevNativeWindowBuffer* m_frontBuf; }; diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/fbdev/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/fbdev/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/fbdev/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/fbdev/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -9,7 +9,7 @@ -I$(top_srcdir)/common \ -I$(top_srcdir)/egl \ -I$(top_srcdir)/egl/platforms/common \ - -I$(top_srcdir)/include/android + $(ANDROID_HEADERS_CFLAGS) if WANT_TRACE eglplatform_fbdev_la_CXXFLAGS += -DDEBUG diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/hwcomposer/eglplatform_hwcomposer.cpp libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/hwcomposer/eglplatform_hwcomposer.cpp --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/hwcomposer/eglplatform_hwcomposer.cpp 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/hwcomposer/eglplatform_hwcomposer.cpp 2015-07-30 07:51:13.000000000 +0000 @@ -1,3 +1,4 @@ +#include #include #include "hwcomposer_window.h" #include @@ -13,37 +14,46 @@ #include "logging.h" -static int inited = 0; static gralloc_module_t *gralloc = 0; static alloc_device_t *alloc = 0; static HWComposerNativeWindow *_nativewindow = NULL; -extern "C" int hwcomposerws_IsValidDisplay(EGLNativeDisplayType display) +extern "C" void hwcomposerws_init_module(struct ws_egl_interface *egl_iface) { - if (__sync_fetch_and_add(&inited,1)==0) - { - int err; - err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **) &gralloc); - if (gralloc==NULL) { - fprintf(stderr, "failed to get gralloc module: (%s)\n",strerror(-err)); - assert(0); - } - - err = gralloc_open((const hw_module_t *) gralloc, &alloc); - if (err) { - fprintf(stderr, "ERROR: failed to open gralloc: (%s)\n",strerror(-err)); - assert(0); - } - TRACE("** gralloc_open %p status=%s", gralloc, strerror(-err)); - eglplatformcommon_init(gralloc, alloc); + int err; + err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **) &gralloc); + if (gralloc==NULL) { + fprintf(stderr, "failed to get gralloc module: (%s)\n",strerror(-err)); + assert(0); } - return display == EGL_DEFAULT_DISPLAY; + err = gralloc_open((const hw_module_t *) gralloc, &alloc); + if (err) { + fprintf(stderr, "ERROR: failed to open gralloc: (%s)\n",strerror(-err)); + assert(0); + } + TRACE("** gralloc_open %p status=%s", gralloc, strerror(-err)); + eglplatformcommon_init(egl_iface, gralloc, alloc); +} + +extern "C" _EGLDisplay *hwcomposerws_GetDisplay(EGLNativeDisplayType display) +{ + assert (gralloc != NULL); + _EGLDisplay *dpy = 0; + if (display == EGL_DEFAULT_DISPLAY) { + dpy = new _EGLDisplay; + } + return dpy; +} + +extern "C" void hwcomposerws_Terminate(_EGLDisplay *dpy) +{ + delete dpy; } -extern "C" EGLNativeWindowType hwcomposerws_CreateWindow(EGLNativeWindowType win, EGLNativeDisplayType display) +extern "C" EGLNativeWindowType hwcomposerws_CreateWindow(EGLNativeWindowType win, _EGLDisplay *display) { - assert (inited >= 1); + assert (gralloc != NULL); assert (_nativewindow == NULL); HWComposerNativeWindow *window = static_cast((ANativeWindow *) win); @@ -74,7 +84,9 @@ } struct ws_module ws_module_info = { - hwcomposerws_IsValidDisplay, + hwcomposerws_init_module, + hwcomposerws_GetDisplay, + hwcomposerws_Terminate, hwcomposerws_CreateWindow, hwcomposerws_DestroyWindow, hwcomposerws_eglGetProcAddress, diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/hwcomposer/hwcomposer_window.cpp libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/hwcomposer/hwcomposer_window.cpp --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/hwcomposer/hwcomposer_window.cpp 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/hwcomposer/hwcomposer_window.cpp 2015-07-30 07:51:13.000000000 +0000 @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include "hwcomposer_window.h" #include "logging.h" @@ -23,10 +24,8 @@ #include #include -#include - extern "C" { -#include +#include }; static pthread_cond_t _cond = PTHREAD_COND_INITIALIZER; @@ -76,7 +75,7 @@ m_width = width; m_height = height; m_bufFormat = format; - m_usage = GRALLOC_USAGE_HW_COMPOSER; + m_usage = GRALLOC_USAGE_HW_COMPOSER|GRALLOC_USAGE_HW_FB; m_frontBuf = NULL; } @@ -163,44 +162,33 @@ } #endif - - while (m_freeBufs==0) - { - pthread_cond_wait(&_cond, &_mutex); - } - - while (1) + std::list::iterator it = m_bufList.begin(); + for (; it != m_bufList.end(); ++it) { - std::list::iterator it = m_bufList.begin(); - for (; it != m_bufList.end(); ++it) - { - if (*it==m_frontBuf) - continue; - if ((*it)->busy==0) - { - TRACE("Found a free non-front buffer"); - break; - } - } - if (it == m_bufList.end()) - { - // have to wait once again - pthread_cond_wait(&_cond, &_mutex); + if (*it==m_frontBuf) continue; + if ((*it)->busy==0) + { + TRACE("Found a free non-front buffer"); + break; } - + } + if (it == m_bufList.end()) + { + fbnb = m_frontBuf; + } + else + { fbnb = *it; - break; } HYBRIS_TRACE_END("hwcomposer-platform", "dequeueBuffer-wait", ""); assert(fbnb!=NULL); fbnb->busy = 1; - m_freeBufs--; *buffer = fbnb; - *fenceFd = -1; - + *fenceFd = dup(fbnb->fenceFd); + close(fbnb->fenceFd); TRACE("%lu DONE --> %p", pthread_self(), fbnb); pthread_mutex_unlock(&_mutex); HYBRIS_TRACE_END("hwcomposer-platform", "dequeueBuffer", ""); @@ -233,67 +221,29 @@ HWComposerNativeWindowBuffer* fbnb = (HWComposerNativeWindowBuffer*) buffer; HYBRIS_TRACE_BEGIN("hwcomposer-platform", "queueBuffer", "-%p", fbnb); - fbnb->fenceFd = fenceFd; - + pthread_mutex_lock(&_mutex); - - /* Front buffer hasn't yet been picked up for posting */ - while (m_frontBuf && m_frontBuf->busy >= 2) - { - pthread_cond_wait(&_cond, &_mutex); - } - - assert(fbnb->busy==1); - fbnb->busy = 2; m_frontBuf = fbnb; - m_freeBufs++; - - sync_wait(fenceFd, -1); - ::close(fenceFd); - - pthread_cond_signal(&_cond); - - TRACE("%lu %p %p",pthread_self(), m_frontBuf, fbnb); + fbnb->fenceFd = fenceFd; + this->present(fbnb); + fbnb->busy = 0; pthread_mutex_unlock(&_mutex); + + // After this, we expect fenceFd to be equal to the release fd + TRACE("%lu %p %p",pthread_self(), m_frontBuf, fbnb); HYBRIS_TRACE_END("hwcomposer-platform", "queueBuffer", "-%p", fbnb); return 0; } -void HWComposerNativeWindow::lockFrontBuffer(HWComposerNativeWindowBuffer **buffer) +int HWComposerNativeWindow::getFenceBufferFd(HWComposerNativeWindowBuffer *buffer) { - TRACE(""); - HWComposerNativeWindowBuffer *buf; - pthread_mutex_lock(&_mutex); - - while (!m_frontBuf) - { - pthread_cond_wait(&_cond, &_mutex); - } - - assert(m_frontBuf->busy == 2); - - m_frontBuf->busy = 3; - buf = m_frontBuf; - pthread_mutex_unlock(&_mutex); - - *buffer = buf; - return; - + return buffer->fenceFd; } -void HWComposerNativeWindow::unlockFrontBuffer(HWComposerNativeWindowBuffer *buffer) +void HWComposerNativeWindow::setFenceBufferFd(HWComposerNativeWindowBuffer *buffer, int fd) { - TRACE(""); - pthread_mutex_lock(&_mutex); - - assert(buffer == m_frontBuf); - m_frontBuf->busy = 0; - - pthread_cond_signal(&_cond); - pthread_mutex_unlock(&_mutex); - - return; + buffer->fenceFd = fd; } /* @@ -330,11 +280,7 @@ fbnb->busy=0; - m_freeBufs++; - - pthread_cond_signal(&_cond); - pthread_mutex_unlock(&_mutex); - + pthread_mutex_unlock(&_mutex); return 0; } @@ -494,7 +440,7 @@ { HWComposerNativeWindowBuffer *fbnb = new HWComposerNativeWindowBuffer(m_alloc, m_width, m_height, m_bufFormat, - m_usage|GRALLOC_USAGE_HW_COMPOSER); + m_usage|GRALLOC_USAGE_HW_COMPOSER|GRALLOC_USAGE_HW_FB); fbnb->common.incRef(&fbnb->common); diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/hwcomposer/hwcomposer_window.h libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/hwcomposer/hwcomposer_window.h --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/hwcomposer/hwcomposer_window.h 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/hwcomposer/hwcomposer_window.h 2015-07-30 07:51:13.000000000 +0000 @@ -19,7 +19,7 @@ #include "nativewindowbase.h" #include -#include +#include #include @@ -50,9 +50,8 @@ void setup(gralloc_module_t* gralloc, alloc_device_t* alloc); - void lockFrontBuffer(HWComposerNativeWindowBuffer **buffer); - void unlockFrontBuffer(HWComposerNativeWindowBuffer *buffer); - + int getFenceBufferFd(HWComposerNativeWindowBuffer *buffer); + void setFenceBufferFd(HWComposerNativeWindowBuffer *buffer, int fd); protected: // overloads from BaseNativeWindow virtual int setSwapInterval(int interval); @@ -75,7 +74,7 @@ virtual int setBuffersFormat(int format); virtual int setBuffersDimensions(int width, int height); virtual int setBufferCount(int cnt); - + virtual void present(HWComposerNativeWindowBuffer *buffer) = 0; private: void destroyBuffers(); diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/hwcomposer/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/hwcomposer/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/hwcomposer/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/hwcomposer/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -15,7 +15,7 @@ -I$(top_srcdir)/common \ -I$(top_srcdir)/egl \ -I$(top_srcdir)/egl/platforms/common \ - -I$(top_srcdir)/include/android + $(ANDROID_HEADERS_CFLAGS) if WANT_TRACE libhybris_hwcomposerwindow_la_CXXFLAGS += -DDEBUG @@ -32,7 +32,9 @@ if HAS_ANDROID_4_2_0 libhybris_hwcomposerwindow_la_LDFLAGS += $(top_builddir)/libsync/libsync.la endif - +if HAS_ANDROID_5_0_0 +libhybris_hwcomposerwindow_la_LDFLAGS += $(top_builddir)/libsync/libsync.la +endif pkglib_LTLIBRARIES = eglplatform_hwcomposer.la eglplatform_hwcomposer_la_SOURCES = \ @@ -43,7 +45,7 @@ -I$(top_srcdir)/common \ -I$(top_srcdir)/egl \ -I$(top_srcdir)/egl/platforms/common \ - -I$(top_srcdir)/include/android + $(ANDROID_HEADERS_CFLAGS) if WANT_TRACE eglplatform_hwcomposer_la_CXXFLAGS += -DDEBUG diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -3,6 +3,9 @@ if HAS_ANDROID_4_2_0 SUBDIRS += hwcomposer endif +if HAS_ANDROID_5_0_0 +SUBDIRS += hwcomposer +endif if WANT_WAYLAND SUBDIRS += wayland diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/null/eglplatform_null.c libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/null/eglplatform_null.c --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/null/eglplatform_null.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/null/eglplatform_null.c 2015-07-30 07:51:13.000000000 +0000 @@ -1,13 +1,19 @@ +#include #include #include #include -#include +#include +#include +#include "logging.h" static void * (*_androidCreateDisplaySurface)(); static void *_libui = NULL; +static gralloc_module_t *gralloc = 0; +static alloc_device_t *alloc = 0; + static void _init_androidui() { _libui = (void *) android_dlopen("/system/lib/libui.so", RTLD_LAZY); @@ -22,13 +28,27 @@ } +static void nullws_init_module(struct ws_egl_interface *egl_iface) +{ + int err; + hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **) &gralloc); + err = gralloc_open((const hw_module_t *) gralloc, &alloc); + TRACE("++ %lu wayland: got gralloc %p err:%s", pthread_self(), gralloc, strerror(-err)); + eglplatformcommon_init(egl_iface, gralloc, alloc); -static int nullws_IsValidDisplay(EGLNativeDisplayType display) +} + +static struct _EGLDisplay *nullws_GetDisplay(EGLNativeDisplayType display) { - return 1; + return malloc(sizeof(struct _EGLDisplay)); } -static EGLNativeWindowType nullws_CreateWindow(EGLNativeWindowType win, EGLNativeDisplayType display) +static void nullws_Terminate(struct _EGLDisplay *dpy) +{ + free(dpy); +} + +static EGLNativeWindowType nullws_CreateWindow(EGLNativeWindowType win, struct _EGLDisplay *display) { if (win == 0) { @@ -43,27 +63,14 @@ // TODO: Cleanup? } -static __eglMustCastToProperFunctionPointerType nullws_eglGetProcAddress(const char *procname) -{ - return NULL; -} - -static void nullws_passthroughImageKHR(EGLContext *ctx, EGLenum *target, EGLClientBuffer *buffer, const EGLint **attrib_list) -{ -} - -const char *nullws_eglQueryString(EGLDisplay dpy, EGLint name, const char *(*real_eglQueryString)(EGLDisplay dpy, EGLint name)) -{ - return (*real_eglQueryString)(dpy, name); -} - - struct ws_module ws_module_info = { - nullws_IsValidDisplay, + nullws_init_module, + nullws_GetDisplay, + nullws_Terminate, nullws_CreateWindow, nullws_DestroyWindow, - nullws_eglGetProcAddress, - nullws_passthroughImageKHR, - nullws_eglQueryString + eglplatformcommon_eglGetProcAddress, + eglplatformcommon_passthroughImageKHR, + eglplatformcommon_eglQueryString }; diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/null/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/null/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/null/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/null/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -2,8 +2,25 @@ eglplatform_null_la_SOURCES = eglplatform_null.c -eglplatform_null_la_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/egl +eglplatform_null_la_CFLAGS = \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/common \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/egl \ + -I$(top_srcdir)/egl/platforms/common \ + $(ANDROID_HEADERS_CFLAGS) \ + $(WAYLAND_SERVER_CFLAGS) -eglplatform_null_la_LDFLAGS = -avoid-version -module -shared -export-dynamic +eglplatform_null_la_LDFLAGS = \ + -avoid-version -module -shared -export-dynamic \ + $(top_builddir)/egl/platforms/common/libhybris-eglplatformcommon.la \ + $(top_builddir)/hardware/libhardware.la \ + $(WAYLAND_SERVER_LIBS) +if WANT_DEBUG +eglplatform_null_la_CFLAGS += -I$(top_srcdir)/common -ggdb -O0 +endif +if WANT_TRACE +eglplatform_null_la_CFLAGS += -DDEBUG +endif diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/wayland/eglplatform_wayland.cpp libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/wayland/eglplatform_wayland.cpp --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/wayland/eglplatform_wayland.cpp 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/wayland/eglplatform_wayland.cpp 2015-07-30 07:51:13.000000000 +0000 @@ -16,25 +16,31 @@ ** License version 2.1 as published by the Free Software Foundation ** and appearing in the file license.lgpl included in the packaging ** of this file. - ** + ** ** This library is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** Lesser General Public License for more details. - ** + ** ****************************************************************************************/ +#include #include #include #include #include #include +#include #include #include #include +#include extern "C" { #include }; +#include + +#include extern "C" { #include @@ -44,28 +50,146 @@ #include "wayland_window.h" #include "logging.h" #include "wayland-egl-priv.h" +#include "server_wlegl_buffer.h" +#include "wayland-android-client-protocol.h" -static int inited = 0; static gralloc_module_t *gralloc = 0; static alloc_device_t *alloc = 0; -extern "C" int waylandws_IsValidDisplay(EGLNativeDisplayType display) + +static const char * (*_eglQueryString)(EGLDisplay dpy, EGLint name) = NULL; +static __eglMustCastToProperFunctionPointerType (*_eglGetProcAddress)(const char *procname) = NULL; +static EGLSyncKHR (*_eglCreateSyncKHR)(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) = NULL; +static EGLBoolean (*_eglDestroySyncKHR)(EGLDisplay dpy, EGLSyncKHR sync) = NULL; +static EGLint (*_eglClientWaitSyncKHR)(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout) = NULL; + +struct WaylandDisplay { + _EGLDisplay base; + + wl_display *wl_dpy; + wl_event_queue *queue; + wl_registry *registry; + android_wlegl *wlegl; +}; + +extern "C" void waylandws_init_module(struct ws_egl_interface *egl_iface) { int err; - if ( __sync_fetch_and_add(&inited,1)==0) - { - hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **) &gralloc); - err = gralloc_open((const hw_module_t *) gralloc, &alloc); - TRACE("++ %lu wayland: got gralloc %p err:%s", pthread_self(), gralloc, strerror(-err)); - eglplatformcommon_init(gralloc, alloc); + hw_get_module(GRALLOC_HARDWARE_MODULE_ID, (const hw_module_t **) &gralloc); + err = gralloc_open((const hw_module_t *) gralloc, &alloc); + TRACE("++ %lu wayland: got gralloc %p err:%s", pthread_self(), gralloc, strerror(-err)); + eglplatformcommon_init(egl_iface, gralloc, alloc); +} + +static void _init_egl_funcs(EGLDisplay display) +{ + if (_eglQueryString != NULL) + return; + + _eglQueryString = (const char * (*)(void*, int)) + hybris_android_egl_dlsym("eglQueryString"); + assert(_eglQueryString); + _eglGetProcAddress = (__eglMustCastToProperFunctionPointerType (*)(const char *)) + hybris_android_egl_dlsym("eglGetProcAddress"); + assert(_eglGetProcAddress); + + const char *extensions = (*_eglQueryString)(display, EGL_EXTENSIONS); + + if (strstr(extensions, "EGL_KHR_fence_sync")) { + _eglCreateSyncKHR = (PFNEGLCREATESYNCKHRPROC) + (*_eglGetProcAddress)("eglCreateSyncKHR"); + assert(_eglCreateSyncKHR); + _eglDestroySyncKHR = (PFNEGLDESTROYSYNCKHRPROC) + (*_eglGetProcAddress)("eglDestroySyncKHR"); + assert(_eglDestroySyncKHR); + _eglClientWaitSyncKHR = (PFNEGLCLIENTWAITSYNCKHRPROC) + (*_eglGetProcAddress)("eglClientWaitSyncKHR"); + assert(_eglClientWaitSyncKHR); } +} + +static void registry_handle_global(void *data, wl_registry *registry, uint32_t name, const char *interface, uint32_t version) +{ + WaylandDisplay *dpy = (WaylandDisplay *)data; + + if (strcmp(interface, "android_wlegl") == 0) { + dpy->wlegl = static_cast(wl_registry_bind(registry, name, &android_wlegl_interface, std::min(2u, version))); + } +} - return 1; +static const wl_registry_listener registry_listener = { + registry_handle_global +}; + +static void callback_done(void *data, wl_callback *cb, uint32_t d) +{ + WaylandDisplay *dpy = (WaylandDisplay *)data; + + wl_callback_destroy(cb); + if (!dpy->wlegl) { + fprintf(stderr, "Fatal: the server doesn't advertise the android_wlegl global!"); + abort(); + } +} + +static const wl_callback_listener callback_listener = { + callback_done +}; + +extern "C" _EGLDisplay *waylandws_GetDisplay(EGLNativeDisplayType display) +{ + WaylandDisplay *wdpy = new WaylandDisplay; + wdpy->wl_dpy = (wl_display *)display; + wdpy->wlegl = NULL; + wdpy->queue = wl_display_create_queue(wdpy->wl_dpy); + wdpy->registry = wl_display_get_registry(wdpy->wl_dpy); + wl_proxy_set_queue((wl_proxy *) wdpy->registry, wdpy->queue); + wl_registry_add_listener(wdpy->registry, ®istry_listener, wdpy); + + wl_callback *cb = wl_display_sync(wdpy->wl_dpy); + wl_proxy_set_queue((wl_proxy *) cb, wdpy->queue); + wl_callback_add_listener(cb, &callback_listener, wdpy); + + return &wdpy->base; +} + +extern "C" void waylandws_Terminate(_EGLDisplay *dpy) +{ + WaylandDisplay *wdpy = (WaylandDisplay *)dpy; + int ret = 0; + // We still have the sync callback on flight, wait for it to arrive + while (ret == 0 && !wdpy->wlegl) { + ret = wl_display_dispatch_queue(wdpy->wl_dpy, wdpy->queue); + } + assert(ret >= 0); + android_wlegl_destroy(wdpy->wlegl); + wl_registry_destroy(wdpy->registry); + wl_event_queue_destroy(wdpy->queue); + delete wdpy; } -extern "C" EGLNativeWindowType waylandws_CreateWindow(EGLNativeWindowType win, EGLNativeDisplayType display) +extern "C" EGLNativeWindowType waylandws_CreateWindow(EGLNativeWindowType win, _EGLDisplay *display) { - WaylandNativeWindow *window = new WaylandNativeWindow((struct wl_egl_window *) win, (struct wl_display *) display, gralloc, alloc); + struct wl_egl_window *wl_window = (struct wl_egl_window*) win; + struct wl_display *wl_display = (struct wl_display*) display; + + if (wl_window == 0 || wl_display == 0) { + HYBRIS_ERROR("Running with EGL_PLATFORM=wayland without setup wayland environment is not possible"); + HYBRIS_ERROR("If you want to run a standlone EGL client do it like this:"); + HYBRIS_ERROR(" $ export EGL_PLATFORM=null"); + HYBRIS_ERROR(" $ test_glevs2"); + abort(); + } + + WaylandDisplay *wdpy = (WaylandDisplay *)display; + + int ret = 0; + while (ret == 0 && !wdpy->wlegl) { + ret = wl_display_dispatch_queue(wdpy->wl_dpy, wdpy->queue); + } + assert(ret >= 0); + + WaylandNativeWindow *window = new WaylandNativeWindow((struct wl_egl_window *) win, wdpy->wl_dpy, wdpy->wlegl, alloc, gralloc); window->common.incRef(&window->common); return (EGLNativeWindowType) static_cast(window); } @@ -83,12 +207,37 @@ return ((WaylandNativeWindow *) eglwin->nativewindow)->postBuffer((ANativeWindowBuffer *) buffer); } -extern "C" __eglMustCastToProperFunctionPointerType waylandws_eglGetProcAddress(const char *procname) +extern "C" wl_buffer *waylandws_createWlBuffer(EGLDisplay dpy, EGLImageKHR image) +{ + egl_image *img = reinterpret_cast(image); + if (!img) { + // The spec says we should send a EGL_BAD_PARAMETER error here, but we don't have the + // means, as of now. + return NULL; + } + if (img->target == EGL_WAYLAND_BUFFER_WL) { + WaylandDisplay *wdpy = (WaylandDisplay *)hybris_egl_display_get_mapping(dpy); + server_wlegl_buffer *buf = server_wlegl_buffer_from((wl_resource *)img->egl_buffer); + WaylandNativeWindowBuffer wnb(buf->buf); + // The buffer will be managed by the app, so pass NULL as the queue so that + // it will be assigned to the default queue + wnb.wlbuffer_from_native_handle(wdpy->wlegl, wdpy->wl_dpy, NULL); + return wnb.wlbuffer; + } + // EGL_BAD_MATCH + return NULL; +} + +extern "C" __eglMustCastToProperFunctionPointerType waylandws_eglGetProcAddress(const char *procname) { if (strcmp(procname, "eglHybrisWaylandPostBuffer") == 0) { return (__eglMustCastToProperFunctionPointerType) waylandws_post; } + else if (strcmp(procname, "eglCreateWaylandBufferFromImageWL") == 0) + { + return (__eglMustCastToProperFunctionPointerType) waylandws_createWlBuffer; + } else return eglplatformcommon_eglGetProcAddress(procname); } @@ -98,13 +247,56 @@ eglplatformcommon_passthroughImageKHR(ctx, target, buffer, attrib_list); } +extern "C" const char *waylandws_eglQueryString(EGLDisplay dpy, EGLint name, const char *(*real_eglQueryString)(EGLDisplay dpy, EGLint name)) +{ + const char *ret = eglplatformcommon_eglQueryString(dpy, name, real_eglQueryString); + if (ret && name == EGL_EXTENSIONS) + { + static char eglextensionsbuf[512]; + snprintf(eglextensionsbuf, 510, "%s %s", ret, + "EGL_EXT_swap_buffers_with_damage EGL_WL_create_wayland_buffer_from_image" + ); + ret = eglextensionsbuf; + } + return ret; +} + +extern "C" void waylandws_prepareSwap(EGLDisplay dpy, EGLNativeWindowType win, EGLint *damage_rects, EGLint damage_n_rects) +{ + WaylandNativeWindow *window = static_cast((struct ANativeWindow *)win); + window->prepareSwap(damage_rects, damage_n_rects); +} + +extern "C" void waylandws_finishSwap(EGLDisplay dpy, EGLNativeWindowType win) +{ + _init_egl_funcs(dpy); + WaylandNativeWindow *window = static_cast((struct ANativeWindow *)win); + if (_eglCreateSyncKHR) { + EGLSyncKHR sync = (*_eglCreateSyncKHR)(dpy, EGL_SYNC_FENCE_KHR, NULL); + (*_eglClientWaitSyncKHR)(dpy, sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR); + (*_eglDestroySyncKHR)(dpy, sync); + } + window->finishSwap(); +} + +extern "C" void waylandws_setSwapInterval(EGLDisplay dpy, EGLNativeWindowType win, EGLint interval) +{ + WaylandNativeWindow *window = static_cast((struct ANativeWindow *)win); + window->setSwapInterval(interval); +} + struct ws_module ws_module_info = { - waylandws_IsValidDisplay, + waylandws_init_module, + waylandws_GetDisplay, + waylandws_Terminate, waylandws_CreateWindow, waylandws_DestroyWindow, waylandws_eglGetProcAddress, waylandws_passthroughImageKHR, - eglplatformcommon_eglQueryString + waylandws_eglQueryString, + waylandws_prepareSwap, + waylandws_finishSwap, + waylandws_setSwapInterval, }; diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/wayland/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/wayland/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/wayland/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/wayland/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -6,7 +6,7 @@ -I$(top_srcdir)/include \ -I$(top_srcdir)/egl \ -I$(top_srcdir)/egl/platforms/common \ - -I$(top_srcdir)/include/android \ + $(ANDROID_HEADERS_CFLAGS) \ $(WAYLAND_CLIENT_CFLAGS) if WANT_DEBUG @@ -21,6 +21,10 @@ eglplatform_wayland_la_CXXFLAGS += -ggdb -O0 endif +if !WANT_WL_SERVERSIDE_BUFFERS +eglplatform_wayland_la_CXXFLAGS += -DHYBRIS_NO_SERVER_SIDE_BUFFERS +endif + eglplatform_wayland_la_LDFLAGS = \ @@ -28,7 +32,11 @@ $(top_builddir)/egl/platforms/common/libhybris-eglplatformcommon.la \ $(top_builddir)/hardware/libhardware.la \ $(WAYLAND_CLIENT_LIBS) - if HAS_ANDROID_4_2_0 eglplatform_wayland_la_LDFLAGS += $(top_builddir)/libsync/libsync.la endif + +if HAS_ANDROID_5_0_0 +eglplatform_wayland_la_LDFLAGS += $(top_builddir)/libsync/libsync.la +endif + diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/wayland/wayland_window.cpp libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/wayland/wayland_window.cpp --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/wayland/wayland_window.cpp 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/wayland/wayland_window.cpp 2015-07-30 07:51:13.000000000 +0000 @@ -25,6 +25,7 @@ ****************************************************************************************/ +#include #include "wayland_window.h" #include "wayland-egl-priv.h" #include @@ -32,18 +33,29 @@ #include #include "logging.h" -#include #include -#if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=2 +#if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=2 || ANDROID_VERSION_MAJOR>=5 extern "C" { -#include +#include } #endif +static void +buffer_create_sync_callback(void *data, struct wl_callback *callback, uint32_t serial) +{ + struct wl_callback **created_callback = static_cast(data); + + *created_callback = NULL; + wl_callback_destroy(callback); +} +static const struct wl_callback_listener buffer_create_sync_listener = { + buffer_create_sync_callback +}; -void WaylandNativeWindowBuffer::wlbuffer_from_native_handle(struct android_wlegl *android_wlegl) +void WaylandNativeWindowBuffer::wlbuffer_from_native_handle(struct android_wlegl *android_wlegl, + struct wl_display *display, struct wl_event_queue *queue) { struct wl_array ints; int *ints_data; @@ -64,16 +76,32 @@ wlbuffer = android_wlegl_create_buffer(android_wlegl, width, height, stride, format, usage, wlegl_handle); + wl_proxy_set_queue((struct wl_proxy *) wlbuffer, queue); android_wlegl_handle_destroy(wlegl_handle); + + creation_callback = wl_display_sync(display); + wl_callback_add_listener(creation_callback, &buffer_create_sync_listener, &creation_callback); + wl_proxy_set_queue((struct wl_proxy *)creation_callback, queue); +} + +void WaylandNativeWindow::resize(unsigned int width, unsigned int height) +{ + lock(); + this->m_defaultWidth = width; + this->m_defaultHeight = height; + unlock(); } void WaylandNativeWindow::resize_callback(struct wl_egl_window *egl_window, void *) { TRACE("%dx%d",egl_window->width,egl_window->height); - native_window_set_buffers_dimensions( - (WaylandNativeWindow*)egl_window->nativewindow, - egl_window->width,egl_window->height); + ((WaylandNativeWindow *) egl_window->nativewindow)->resize(egl_window->width, egl_window->height); +} + +void WaylandNativeWindow::free_callback(struct wl_egl_window *egl_window, void *) +{ + ((WaylandNativeWindow*)(egl_window->nativewindow))->m_window = 0; } void WaylandNativeWindow::lock() @@ -86,23 +114,7 @@ pthread_mutex_unlock(&this->mutex); } - void -WaylandNativeWindow::registry_handle_global(void *data, struct wl_registry *registry, uint32_t name, - const char *interface, uint32_t version) -{ - WaylandNativeWindow *nw = static_cast(data); - - if (strcmp(interface, "android_wlegl") == 0) { - nw->m_android_wlegl = static_cast(wl_registry_bind(registry, name, &android_wlegl_interface, 1)); - } -} - -static const struct wl_registry_listener registry_listener = { - WaylandNativeWindow::registry_handle_global -}; - - - void +void WaylandNativeWindow::sync_callback(void *data, struct wl_callback *callback, uint32_t serial) { int *done = static_cast(data); @@ -115,7 +127,7 @@ WaylandNativeWindow::sync_callback }; - int +int WaylandNativeWindow::wayland_roundtrip(WaylandNativeWindow *display) { struct wl_callback *callback; @@ -125,7 +137,7 @@ callback = wl_display_sync(display->m_display); wl_callback_add_listener(callback, &sync_listener, &done); wl_proxy_set_queue((struct wl_proxy *) callback, display->wl_queue); - while (ret == 0 && !done) + while (ret >= 0 && !done) ret = wl_display_dispatch_queue(display->m_display, display->wl_queue); return ret; @@ -147,7 +159,7 @@ abort(); } - static void +static void wayland_frame_callback(void *data, struct wl_callback *callback, uint32_t time) { WaylandNativeWindow *surface = static_cast(data); @@ -159,7 +171,8 @@ wayland_frame_callback }; -WaylandNativeWindow::WaylandNativeWindow(struct wl_egl_window *window, struct wl_display *display, const gralloc_module_t* gralloc, alloc_device_t* alloc_device) +WaylandNativeWindow::WaylandNativeWindow(struct wl_egl_window *window, struct wl_display *display, android_wlegl *wlegl, alloc_device_t* alloc_device, gralloc_module_t *gralloc) + : m_android_wlegl(wlegl) { int wayland_ok; @@ -172,25 +185,27 @@ this->m_defaultWidth = window->width; this->m_defaultHeight = window->height; this->m_window->resize_callback = resize_callback; - this->m_format = 1; - this->wl_queue = wl_display_create_queue(display); + this->m_window->free_callback = free_callback; this->frame_callback = NULL; - this->registry = wl_display_get_registry(display); - wl_proxy_set_queue((struct wl_proxy *) this->registry, - this->wl_queue); - wl_registry_add_listener(this->registry, ®istry_listener, this); - - wayland_ok = wayland_roundtrip(this); - assert(wayland_ok >= 0); - assert(this->m_android_wlegl != NULL); + this->wl_queue = wl_display_create_queue(display); + this->m_format = 1; + + const_cast(ANativeWindow::minSwapInterval) = 0; + const_cast(ANativeWindow::maxSwapInterval) = 1; + // This is the default as per the EGL documentation + this->m_swap_interval = 1; - this->m_gralloc = gralloc; this->m_alloc = alloc_device; + m_gralloc = gralloc; m_usage=GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; pthread_mutex_init(&mutex, NULL); pthread_cond_init(&cond, NULL); + m_queueReads = 0; m_freeBufs = 0; + m_damage_rects = NULL; + m_damage_n_rects = 0; + m_lastBuffer = 0; setBufferCount(3); HYBRIS_TRACE_END("wayland-platform", "create_window", ""); } @@ -198,19 +213,15 @@ WaylandNativeWindow::~WaylandNativeWindow() { std::list::iterator it = m_bufList.begin(); - for (; it != m_bufList.end(); it++) - { - WaylandNativeWindowBuffer* buf=*it; - if (buf->wlbuffer) - wl_buffer_destroy(buf->wlbuffer); - buf->wlbuffer = NULL; - buf->common.decRef(&buf->common); - } + destroyBuffers(); if (frame_callback) wl_callback_destroy(frame_callback); - wl_registry_destroy(registry); wl_event_queue_destroy(wl_queue); - android_wlegl_destroy(m_android_wlegl); + if (m_window) { + m_window->nativewindow = NULL; + m_window->resize_callback = NULL; + m_window->free_callback = NULL; + } } void WaylandNativeWindow::frame() { @@ -221,10 +232,23 @@ HYBRIS_TRACE_END("wayland-platform", "frame_event", ""); } - // overloads from BaseNativeWindow int WaylandNativeWindow::setSwapInterval(int interval) { TRACE("interval:%i", interval); + + if (interval < 0) + interval = 0; + if (interval > 1) + interval = 1; + + HYBRIS_TRACE_BEGIN("wayland-platform", "swap_interval", "=%d", interval); + + lock(); + m_swap_interval = interval; + unlock(); + + HYBRIS_TRACE_END("wayland-platform", "swap_interval", ""); + return 0; } @@ -241,7 +265,6 @@ void WaylandNativeWindow::releaseBuffer(struct wl_buffer *buffer) { - lock(); std::list::iterator it = posted.begin(); for (; it != posted.end(); it++) @@ -256,7 +279,6 @@ posted.erase(it); TRACE("released posted buffer: %p", buffer); pwnb->busy = 0; - pthread_cond_signal(&cond); unlock(); return; } @@ -288,15 +310,13 @@ ++m_freeBufs; HYBRIS_TRACE_COUNTER("wayland-platform", "m_freeBufs", "%i", m_freeBufs); for (it = m_bufList.begin(); it != m_bufList.end(); it++) - { + { (*it)->youngest = 0; } - wnb->youngest = 1; + wnb->youngest = 1; - pthread_cond_signal(&cond); HYBRIS_TRACE_END("wayland-platform", "releaseBuffer", "-%p", wnb); - unlock(); } @@ -307,15 +327,17 @@ TRACE("%p", buffer); lock(); + readQueue(false); + HYBRIS_TRACE_BEGIN("wayland-platform", "dequeueBuffer_wait_for_buffer", ""); HYBRIS_TRACE_COUNTER("wayland-platform", "m_freeBufs", "%i", m_freeBufs); while (m_freeBufs==0) { HYBRIS_TRACE_COUNTER("wayland-platform", "m_freeBufs", "%i", m_freeBufs); - - pthread_cond_wait(&cond,&mutex); + readQueue(true); } + std::list::iterator it = m_bufList.begin(); for (; it != m_bufList.end(); it++) { @@ -333,7 +355,7 @@ it = m_bufList.begin(); for (; it != m_bufList.end() && (*it)->busy; it++) {} - + } if (it==m_bufList.end()) { unlock(); @@ -362,6 +384,7 @@ wnb->busy = 1; *buffer = wnb; + queue.push_back(wnb); --m_freeBufs; HYBRIS_TRACE_COUNTER("wayland-platform", "m_freeBufs", "%i", m_freeBufs); @@ -408,26 +431,16 @@ lock(); wnb->busy = 1; - unlock(); - /* XXX locking/something is a bit fishy here */ - while (this->frame_callback && ret != -1) { - ret = wl_display_dispatch_queue(m_display, this->wl_queue); - } + ret = readQueue(false); if (ret < 0) { - TRACE("wl_display_dispatch_queue returned an error:%i", ret); - check_fatal_error(m_display); + unlock(); return ret; } - lock(); - this->frame_callback = wl_surface_frame(m_window->surface); - wl_callback_add_listener(this->frame_callback, &frame_listener, this); - wl_proxy_set_queue((struct wl_proxy *) this->frame_callback, this->wl_queue); - if (wnb->wlbuffer == NULL) { - wnb->wlbuffer_from_native_handle(m_android_wlegl); + wnb->wlbuffer_from_native_handle(m_android_wlegl, m_display, wl_queue); TRACE("%p add listener with %p inside", wnb, wnb->wlbuffer); wl_buffer_add_listener(wnb->wlbuffer, &wl_buffer_listener, this); wl_proxy_set_queue((struct wl_proxy *) wnb->wlbuffer, this->wl_queue); @@ -437,43 +450,125 @@ wl_surface_attach(m_window->surface, wnb->wlbuffer, 0, 0); wl_surface_damage(m_window->surface, 0, 0, wnb->width, wnb->height); wl_surface_commit(m_window->surface); - //--m_freeBufs; - //pthread_cond_signal(&cond); + wl_display_flush(m_display); + posted.push_back(wnb); unlock(); return NO_ERROR; } -static int debugenvchecked = 0; - -int WaylandNativeWindow::queueBuffer(BaseNativeWindowBuffer* buffer, int fenceFd) +int WaylandNativeWindow::readQueue(bool block) { - WaylandNativeWindowBuffer *wnb = (WaylandNativeWindowBuffer*) buffer; int ret = 0; - HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer", "-%p", wnb); + if (++m_queueReads == 1) { + if (block) { + ret = wl_display_dispatch_queue(m_display, wl_queue); + } else { + ret = wl_display_dispatch_queue_pending(m_display, wl_queue); + } + + // all threads waiting on the false branch will wake and return now, so we + // can safely set m_queueReads to 0 here instead of relying on every thread + // to decrement it. This prevents a race condition when a thread enters readQueue() + // before the one in this thread returns. + // The new thread would go in the false branch, and there would be no thread in the + // true branch, blocking the new thread and any other that will call readQueue in + // the future. + m_queueReads = 0; + + pthread_cond_broadcast(&cond); + + if (ret < 0) { + TRACE("wl_display_dispatch_queue returned an error"); + check_fatal_error(m_display); + return ret; + } + } else if (block) { + while (m_queueReads > 0) { + pthread_cond_wait(&cond, &mutex); + } + } + + return ret; +} + +void WaylandNativeWindow::prepareSwap(EGLint *damage_rects, EGLint damage_n_rects) +{ lock(); - wnb->busy = 1; + m_damage_rects = damage_rects; + m_damage_n_rects = damage_n_rects; unlock(); - /* XXX locking/something is a bit fishy here */ - HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer_wait_for_frame_callback", "-%p", wnb); +} - while (this->frame_callback && ret != -1) { - ret = wl_display_dispatch_queue(m_display, this->wl_queue); - } +void WaylandNativeWindow::finishSwap() +{ + int ret = 0; + lock(); + WaylandNativeWindowBuffer *wnb = queue.front(); + if (!wnb) { + wnb = m_lastBuffer; + } else { + queue.pop_front(); + } + assert(wnb); + m_lastBuffer = wnb; + wnb->busy = 1; + ret = readQueue(false); + if (this->frame_callback) { + do { + ret = readQueue(true); + } while (this->frame_callback && ret != -1); + } if (ret < 0) { - TRACE("wl_display_dispatch_queue returned an error"); HYBRIS_TRACE_END("wayland-platform", "queueBuffer_wait_for_frame_callback", "-%p", wnb); - check_fatal_error(m_display); - return ret; + return; + } + + if (wnb->wlbuffer == NULL) + { + wnb->init(m_android_wlegl, m_display, wl_queue); + TRACE("%p add listener with %p inside", wnb, wnb->wlbuffer); + wl_buffer_add_listener(wnb->wlbuffer, &wl_buffer_listener, this); + wl_proxy_set_queue((struct wl_proxy *) wnb->wlbuffer, this->wl_queue); } - HYBRIS_TRACE_END("wayland-platform", "queueBuffer_wait_for_frame_callback", "-%p", wnb); + if (m_swap_interval > 0) { + this->frame_callback = wl_surface_frame(m_window->surface); + wl_callback_add_listener(this->frame_callback, &frame_listener, this); + wl_proxy_set_queue((struct wl_proxy *) this->frame_callback, this->wl_queue); + } + + wl_surface_attach(m_window->surface, wnb->wlbuffer, 0, 0); + wl_surface_damage(m_window->surface, 0, 0, wnb->width, wnb->height); + wl_surface_commit(m_window->surface); + // Some compositors, namely Weston, queue buffer release events instead + // of sending them immediately. If a frame event is used, this should + // not be a problem. Without a frame event, we need to send a sync + // request to ensure that they get flushed. + wl_callback_destroy(wl_display_sync(m_display)); + wl_display_flush(m_display); + fronted.push_back(wnb); + + m_window->attached_width = wnb->width; + m_window->attached_height = wnb->height; + + m_damage_rects = NULL; + m_damage_n_rects = 0; + unlock(); +} +static int debugenvchecked = 0; +int WaylandNativeWindow::queueBuffer(BaseNativeWindowBuffer* buffer, int fenceFd) +{ + WaylandNativeWindowBuffer *wnb = (WaylandNativeWindowBuffer*) buffer; + int ret = 0; + + HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer", "-%p", wnb); lock(); if (debugenvchecked == 0) @@ -491,59 +586,17 @@ } -#if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=2 +#if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=2 || ANDROID_VERSION_MAJOR>=5 HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer_waiting_for_fence", "-%p", wnb); - sync_wait(fenceFd, -1); - close(fenceFd); - HYBRIS_TRACE_END("wayland-platform", "queueBuffer_waiting_for_fence", "-%p", wnb); -#endif - - this->frame_callback = wl_surface_frame(m_window->surface); - wl_callback_add_listener(this->frame_callback, &frame_listener, this); - wl_proxy_set_queue((struct wl_proxy *) this->frame_callback, this->wl_queue); - - if (wnb->wlbuffer == NULL) + if (fenceFd >= 0) { - wnb->wlbuffer_from_native_handle(m_android_wlegl); - TRACE("%p add listener with %p inside", wnb, wnb->wlbuffer); - wl_buffer_add_listener(wnb->wlbuffer, &wl_buffer_listener, this); - wl_proxy_set_queue((struct wl_proxy *) wnb->wlbuffer, this->wl_queue); + sync_wait(fenceFd, -1); + close(fenceFd); } - TRACE("%p DAMAGE AREA: %dx%d", wnb, wnb->width, wnb->height); - HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer_attachdamagecommit", "-resource@%i", wl_proxy_get_id((struct wl_proxy *) wnb->wlbuffer)); - - wl_surface_attach(m_window->surface, wnb->wlbuffer, 0, 0); - wl_surface_damage(m_window->surface, 0, 0, wnb->width, wnb->height); - wl_surface_commit(m_window->surface); - wl_display_flush(m_display); - HYBRIS_TRACE_END("wayland-platform", "queueBuffer_attachdamagecommit", "-resource@%i", wl_proxy_get_id((struct wl_proxy *) wnb->wlbuffer)); + HYBRIS_TRACE_END("wayland-platform", "queueBuffer_waiting_for_fence", "-%p", wnb); +#endif - //--m_freeBufs; - //pthread_cond_signal(&cond); - fronted.push_back(wnb); HYBRIS_TRACE_COUNTER("wayland-platform", "fronted.size", "%i", fronted.size()); - - if (fronted.size() == m_bufList.size()) - { - HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer_wait_for_nonfronted_buffer", "-%p", wnb); - - /* We have fronted all our buffers, let's wait for one of them to be free */ - do { - unlock(); - ret = wl_display_dispatch_queue(m_display, this->wl_queue); - lock(); - if (ret == -1) - { - check_fatal_error(m_display); - break; - } - HYBRIS_TRACE_COUNTER("wayland-platform", "fronted.size", "%i", fronted.size()); - - if (fronted.size() != m_bufList.size()) - break; - } while (1); - HYBRIS_TRACE_END("wayland-platform", "queueBuffer_wait_for_nonfronted_buffer", "-%p", wnb); - } HYBRIS_TRACE_END("wayland-platform", "queueBuffer", "-%p", wnb); unlock(); @@ -575,10 +628,17 @@ } wnb->youngest = 1; - pthread_cond_signal(&cond); + if (m_queueReads != 0) { + // Some thread is waiting on wl_display_dispatch_queue(), possibly waiting for a wl_buffer.release + // event. Since we have now cancelled a buffer push an artificial event so that the dispatch returns + // and the thread can notice the cancelled buffer. This means there is a delay of one roundtrip, + // but I don't see other solution except having one dedicated thread for calling wl_display_dispatch_queue(). + wl_callback_destroy(wl_display_sync(m_display)); + } HYBRIS_TRACE_END("wayland-platform", "cancelBuffer", "-%p", wnb); unlock(); + return 0; } @@ -614,7 +674,7 @@ unsigned int WaylandNativeWindow::type() const { TRACE(""); -#if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=3 +#if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=3 || ANDROID_VERSION_MAJOR>=5 /* https://android.googlesource.com/platform/system/core/+/bcfa910611b42018db580b3459101c564f802552%5E!/ */ return NATIVE_WINDOW_SURFACE; #else @@ -644,6 +704,16 @@ TRACE("wnb:%p", wnb); assert(wnb != NULL); + + int ret = 0; + while (ret != -1 && wnb->creation_callback) + ret = wl_display_dispatch_queue(m_display, wl_queue); + + if (wnb->creation_callback) { + wl_callback_destroy(wnb->creation_callback); + wnb->creation_callback = NULL; + } + if (wnb->wlbuffer) wl_buffer_destroy(wnb->wlbuffer); wnb->wlbuffer = NULL; @@ -659,6 +729,7 @@ for (; it!=m_bufList.end(); ++it) { destroyBuffer(*it); + it = m_bufList.erase(it); } m_bufList.clear(); m_freeBufs = 0; @@ -666,9 +737,15 @@ WaylandNativeWindowBuffer *WaylandNativeWindow::addBuffer() { - WaylandNativeWindowBuffer *wnb = new WaylandNativeWindowBuffer(m_alloc, m_width, m_height, m_format, m_usage); + WaylandNativeWindowBuffer *wnb; + +#ifndef HYBRIS_NO_SERVER_SIDE_BUFFERS + wnb = new ServerWaylandBuffer(m_width, m_height, m_format, m_usage, m_gralloc, m_android_wlegl, wl_queue); + wayland_roundtrip(this); +#else + wnb = new ClientWaylandBuffer(m_alloc, m_width, m_height, m_format, m_usage); +#endif m_bufList.push_back(wnb); - wnb->common.incRef(&wnb->common); ++m_freeBufs; TRACE("wnb:%p width:%i height:%i format:x%x usage:x%x", @@ -717,8 +794,8 @@ if (m_width != width || m_height != height) { TRACE("old-size:%ix%i new-size:%ix%i", m_width, m_height, width, height); - m_width = m_defaultWidth = width; - m_height = m_defaultHeight = height; + m_width = width; + m_height = height; /* Buffers will be re-allocated when dequeued */ } else { TRACE("size:%ix%i", width, height); @@ -737,4 +814,102 @@ } return NO_ERROR; } + +#ifdef HYBRIS_NO_SERVER_SIDE_BUFFERS + +void ClientWaylandBuffer::init(struct android_wlegl *android_wlegl, + struct wl_display *display, + struct wl_event_queue *queue) +{ + wlbuffer_from_native_handle(android_wlegl, display, queue); +} + +#else // HYBRIS_NO_SERVER_SIDE_BUFFERS + +static void ssb_ints(void *data, android_wlegl_server_buffer_handle *, wl_array *ints) +{ + ServerWaylandBuffer *wsb = static_cast(data); + wl_array_copy(&wsb->ints, ints); +} + +static void ssb_fd(void *data, android_wlegl_server_buffer_handle *, int fd) +{ + ServerWaylandBuffer *wsb = static_cast(data); + int *ptr = (int *)wl_array_add(&wsb->fds, sizeof(int)); + *ptr = fd; +} + +static void ssb_buffer(void *data, android_wlegl_server_buffer_handle *, wl_buffer *buffer, int32_t format, int32_t stride) +{ + ServerWaylandBuffer *wsb = static_cast(data); + + native_handle_t *native; + int numFds = wsb->fds.size / sizeof(int); + int numInts = wsb->ints.size / sizeof(int32_t); + + native = native_handle_create(numFds, numInts); + + memcpy(&native->data[0], wsb->fds.data, wsb->fds.size); + memcpy(&native->data[numFds], wsb->ints.data, wsb->ints.size); + /* ownership of fds passed to native_handle_t */ + wsb->fds.size = 0; + + wsb->handle = (buffer_handle_t) native; + wsb->format = format; + wsb->stride = stride; + + int ret = wsb->m_gralloc->registerBuffer(wsb->m_gralloc, wsb->handle); + if (ret) { + fprintf(stderr,"failed to register buffer\n"); + return; + } + + wsb->common.incRef(&wsb->common); + wsb->m_buf = buffer; +} + +static const struct android_wlegl_server_buffer_handle_listener server_handle_listener = { + ssb_fd, + ssb_ints, + ssb_buffer, +}; + +ServerWaylandBuffer::ServerWaylandBuffer(unsigned int w, unsigned int h, int f, int u, gralloc_module_t *gralloc, android_wlegl *android_wlegl, struct wl_event_queue *queue) + : WaylandNativeWindowBuffer() + , m_buf(0) +{ + ANativeWindowBuffer::width = w; + ANativeWindowBuffer::height = h; + m_gralloc = gralloc; + usage = u; + + wl_array_init(&ints); + wl_array_init(&fds); + + android_wlegl_server_buffer_handle *ssb = android_wlegl_get_server_buffer_handle(android_wlegl, width, height, f, u); + wl_proxy_set_queue((struct wl_proxy *) ssb, queue); + android_wlegl_server_buffer_handle_add_listener(ssb, &server_handle_listener, this); +} + +ServerWaylandBuffer::~ServerWaylandBuffer() +{ + if (m_buf) + wl_buffer_destroy(m_buf); + + m_gralloc->unregisterBuffer(m_gralloc, handle); + native_handle_close(handle); + native_handle_delete(const_cast(handle)); + wl_array_release(&ints); + wl_array_release(&fds); +} + +void ServerWaylandBuffer::init(android_wlegl *, wl_display *, wl_event_queue *queue) +{ + wlbuffer = m_buf; + m_buf = 0; + wl_proxy_set_queue((struct wl_proxy *) wlbuffer, queue); +} + +#endif // HYBRIS_NO_SERVER_SIDE_BUFFERS + // vim: noai:ts=4:sw=4:ss=4:expandtab diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/wayland/wayland_window.h libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/wayland/wayland_window.h --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/platforms/wayland/wayland_window.h 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/platforms/wayland/wayland_window.h 2015-07-30 07:51:13.000000000 +0000 @@ -24,12 +24,11 @@ ** ****************************************************************************************/ - #ifndef Wayland_WINDOW_H #define Wayland_WINDOW_H #include "nativewindowbase.h" #include -#include +#include extern "C" { #include @@ -38,12 +37,53 @@ #include } #include +#include class WaylandNativeWindowBuffer : public BaseNativeWindowBuffer { +public: + WaylandNativeWindowBuffer() : wlbuffer(0), busy(0), youngest(0), other(0), creation_callback(0) {} + WaylandNativeWindowBuffer(ANativeWindowBuffer *other) + { + ANativeWindowBuffer::width = other->width; + ANativeWindowBuffer::height = other->height; + ANativeWindowBuffer::format = other->format; + ANativeWindowBuffer::usage = other->usage; + ANativeWindowBuffer::handle = other->handle; + ANativeWindowBuffer::stride = other->stride; + this->wlbuffer = NULL; + this->creation_callback = NULL; + this->busy = 0; + this->other = other; + this->youngest = 0; + } + + struct wl_buffer *wlbuffer; + int busy; + int youngest; + ANativeWindowBuffer *other; + struct wl_callback *creation_callback; + + void wlbuffer_from_native_handle(struct android_wlegl *android_wlegl, + struct wl_display *display, + struct wl_event_queue *queue); + + virtual void init(struct android_wlegl *android_wlegl, + struct wl_display *display, + struct wl_event_queue *queue) {} +}; + +#ifdef HYBRIS_NO_SERVER_SIDE_BUFFERS + +class ClientWaylandBuffer : public WaylandNativeWindowBuffer +{ friend class WaylandNativeWindow; protected: - WaylandNativeWindowBuffer(alloc_device_t* alloc_device, + ClientWaylandBuffer() + : m_alloc(0) + {} + + ClientWaylandBuffer(alloc_device_t* alloc_device, unsigned int width, unsigned int height, unsigned int format, @@ -55,6 +95,7 @@ ANativeWindowBuffer::format = format; ANativeWindowBuffer::usage = usage; this->wlbuffer = NULL; + this->creation_callback = NULL; this->busy = 0; this->other = NULL; this->m_alloc = alloc_device; @@ -64,60 +105,71 @@ &this->handle, &this->stride); assert(alloc_ok == 0); this->youngest = 0; + this->common.incRef(&this->common); } - WaylandNativeWindowBuffer(ANativeWindowBuffer *other) - { - ANativeWindowBuffer::width = other->width; - ANativeWindowBuffer::height = other->height; - ANativeWindowBuffer::format = other->format; - ANativeWindowBuffer::usage = other->usage; - ANativeWindowBuffer::handle = other->handle; - ANativeWindowBuffer::stride = other->stride; - this->wlbuffer = NULL; - this->busy = 0; - this->other = other; - this->m_alloc = NULL; - this->youngest = 0; - } - ~WaylandNativeWindowBuffer() + + ~ClientWaylandBuffer() { if (this->m_alloc) m_alloc->free(m_alloc, this->handle); } - void wlbuffer_from_native_handle(struct android_wlegl *android_wlegl); + + void init(struct android_wlegl *android_wlegl, + struct wl_display *display, + struct wl_event_queue *queue); protected: void* vaddr; alloc_device_t* m_alloc; public: - struct wl_buffer *wlbuffer; - int busy; - int youngest; - ANativeWindowBuffer *other; + }; +#else + +class ServerWaylandBuffer : public WaylandNativeWindowBuffer +{ +public: + ServerWaylandBuffer(unsigned int w, unsigned int h, int format, int usage, gralloc_module_t *gralloc, android_wlegl *android_wlegl, struct wl_event_queue *queue); + ~ServerWaylandBuffer(); + void init(struct android_wlegl *android_wlegl, + struct wl_display *display, + struct wl_event_queue *queue); + + struct wl_array ints; + struct wl_array fds; + gralloc_module_t *m_gralloc; + wl_buffer *m_buf; +}; + +#endif // HYBRIS_NO_SERVER_SIDE_BUFFERS class WaylandNativeWindow : public BaseNativeWindow { public: - WaylandNativeWindow(struct wl_egl_window *win, struct wl_display *display, const gralloc_module_t* gralloc, alloc_device_t* alloc_device); + WaylandNativeWindow(struct wl_egl_window *win, struct wl_display *display, android_wlegl *wlegl, alloc_device_t* alloc_device, gralloc_module_t *gralloc); ~WaylandNativeWindow(); void lock(); void unlock(); void frame(); + void resize(unsigned int width, unsigned int height); void releaseBuffer(struct wl_buffer *buffer); int postBuffer(ANativeWindowBuffer *buffer); + virtual int setSwapInterval(int interval); + void prepareSwap(EGLint *damage_rects, EGLint damage_n_rects); + void finishSwap(); + static void sync_callback(void *data, struct wl_callback *callback, uint32_t serial); static void registry_handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version); static void resize_callback(struct wl_egl_window *egl_window, void *); + static void free_callback(struct wl_egl_window *egl_window, void *); struct wl_event_queue *wl_queue; protected: // overloads from BaseNativeWindow - virtual int setSwapInterval(int interval); virtual int dequeueBuffer(BaseNativeWindowBuffer **buffer, int *fenceFd); virtual int lockBuffer(BaseNativeWindowBuffer* buffer); virtual int queueBuffer(BaseNativeWindowBuffer* buffer, int fenceFd); @@ -140,12 +192,16 @@ WaylandNativeWindowBuffer *addBuffer(); void destroyBuffer(WaylandNativeWindowBuffer *); void destroyBuffers(); + int readQueue(bool block); + std::list m_bufList; std::list fronted; std::list posted; std::list post_registered; + std::deque queue; struct wl_egl_window *m_window; struct wl_display *m_display; + WaylandNativeWindowBuffer *m_lastBuffer; unsigned int m_width; unsigned int m_height; unsigned int m_format; @@ -154,13 +210,15 @@ unsigned int m_usage; struct android_wlegl *m_android_wlegl; alloc_device_t* m_alloc; - struct wl_registry *registry; - const gralloc_module_t* m_gralloc; pthread_mutex_t mutex; pthread_cond_t cond; + int m_queueReads; int m_freeBufs; + EGLint *m_damage_rects, m_damage_n_rects; struct wl_callback *frame_callback; + int m_swap_interval; static int wayland_roundtrip(WaylandNativeWindow *display); + gralloc_module_t *m_gralloc; }; #endif diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/ws.c libhybris-0.1.0+git20151016+6d424c9/hybris/egl/ws.c --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/ws.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/ws.c 2015-07-30 07:51:13.000000000 +0000 @@ -50,17 +50,24 @@ } ws = dlsym(wsmod, "ws_module_info"); assert(ws != NULL); + ws->init_module(&hybris_egl_interface); } } -int ws_IsValidDisplay(EGLNativeDisplayType display) +struct _EGLDisplay *ws_GetDisplay(EGLNativeDisplayType display) { _init_ws(); - return ws->IsValidDisplay(display); + return ws->GetDisplay(display); } -EGLNativeWindowType ws_CreateWindow(EGLNativeWindowType win, EGLNativeDisplayType display) +void ws_Terminate(struct _EGLDisplay *dpy) +{ + _init_ws(); + ws->Terminate(dpy); +} + +EGLNativeWindowType ws_CreateWindow(EGLNativeWindowType win, struct _EGLDisplay *display) { _init_ws(); return ws->CreateWindow(win, display); @@ -90,4 +97,25 @@ return ws->eglQueryString(dpy, name, real_eglQueryString); } +void ws_prepareSwap(EGLDisplay dpy, EGLNativeWindowType win, EGLint *damage_rects, EGLint damage_n_rects) +{ + _init_ws(); + if (ws->prepareSwap) + ws->prepareSwap(dpy, win, damage_rects, damage_n_rects); +} + +void ws_finishSwap(EGLDisplay dpy, EGLNativeWindowType win) +{ + _init_ws(); + if (ws->finishSwap) + ws->finishSwap(dpy, win); +} + +void ws_setSwapInterval(EGLDisplay dpy, EGLNativeWindowType win, EGLint interval) +{ + _init_ws(); + if (ws->setSwapInterval) + ws->setSwapInterval(dpy, win, interval); +} + // vim:ts=4:sw=4:noexpandtab diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/egl/ws.h libhybris-0.1.0+git20151016+6d424c9/hybris/egl/ws.h --- libhybris-0.1.0+git20131207+e452e83/hybris/egl/ws.h 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/egl/ws.h 2015-07-30 07:51:13.000000000 +0000 @@ -1,21 +1,53 @@ #ifndef __LIBHYBRIS_WS_H #define __LIBHYBRIS_WS_H #include +#include + +struct ws_egl_interface { + void * (*android_egl_dlsym)(const char *symbol); + + int (*has_mapping)(EGLSurface surface); + EGLNativeWindowType (*get_mapping)(EGLSurface surface); +}; + +struct egl_image +{ + EGLImageKHR egl_image; + EGLClientBuffer egl_buffer; + EGLenum target; +}; + +/* Defined in egl.c */ +extern struct ws_egl_interface hybris_egl_interface; + +struct _EGLDisplay { + EGLDisplay dpy; +}; struct ws_module { - int (*IsValidDisplay)(EGLNativeDisplayType display_id); - EGLNativeWindowType (*CreateWindow)(EGLNativeWindowType win, EGLNativeDisplayType display); + void (*init_module)(struct ws_egl_interface *egl_interface); + + struct _EGLDisplay *(*GetDisplay)(EGLNativeDisplayType native); + void (*Terminate)(struct _EGLDisplay *display); + EGLNativeWindowType (*CreateWindow)(EGLNativeWindowType win, struct _EGLDisplay *display); void (*DestroyWindow)(EGLNativeWindowType win); __eglMustCastToProperFunctionPointerType (*eglGetProcAddress)(const char *procname); void (*passthroughImageKHR)(EGLContext *ctx, EGLenum *target, EGLClientBuffer *buffer, const EGLint **attrib_list); const char *(*eglQueryString)(EGLDisplay dpy, EGLint name, const char *(*real_eglQueryString)(EGLDisplay dpy, EGLint name)); + void (*prepareSwap)(EGLDisplay dpy, EGLNativeWindowType win, EGLint *damage_rects, EGLint damage_n_rects); + void (*finishSwap)(EGLDisplay dpy, EGLNativeWindowType win); + void (*setSwapInterval)(EGLDisplay dpy, EGLNativeWindowType win, EGLint interval); }; -int ws_IsValidDisplay(EGLNativeDisplayType display); -EGLNativeWindowType ws_CreateWindow(EGLNativeWindowType win, EGLNativeDisplayType display); +struct _EGLDisplay *ws_GetDisplay(EGLNativeDisplayType native); +void ws_Terminate(struct _EGLDisplay *dpy); +EGLNativeWindowType ws_CreateWindow(EGLNativeWindowType win, struct _EGLDisplay *display); void ws_DestroyWindow(EGLNativeWindowType win); __eglMustCastToProperFunctionPointerType ws_eglGetProcAddress(const char *procname); void ws_passthroughImageKHR(EGLContext *ctx, EGLenum *target, EGLClientBuffer *buffer, const EGLint **attrib_list); const char *ws_eglQueryString(EGLDisplay dpy, EGLint name, const char *(*real_eglQueryString)(EGLDisplay dpy, EGLint name)); +void ws_prepareSwap(EGLDisplay dpy, EGLNativeWindowType win, EGLint *damage_rects, EGLint damage_n_rects); +void ws_finishSwap(EGLDisplay dpy, EGLNativeWindowType win); +void ws_setSwapInterval(EGLDisplay dpy, EGLNativeWindowType win, EGLint interval); #endif diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/glesv1/glesv1_cm.c libhybris-0.1.0+git20151016+6d424c9/hybris/glesv1/glesv1_cm.c --- libhybris-0.1.0+git20131207+e452e83/hybris/glesv1/glesv1_cm.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/glesv1/glesv1_cm.c 2015-07-30 07:51:13.000000000 +0000 @@ -24,7 +24,7 @@ #include #include -#include +#include #define GLESV1_CM_LIBRARY_PATH "/system/lib/libGLESv1_CM.so" diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/glesv1/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/glesv1/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/glesv1/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/glesv1/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -2,7 +2,7 @@ libGLESv1_CM.la libGLESv1_CM_la_SOURCES = glesv1_cm.c -libGLESv1_CM_la_CFLAGS = -I$(top_srcdir)/include +libGLESv1_CM_la_CFLAGS = -I$(top_srcdir)/include $(ANDROID_HEADERS_CFLAGS) pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = glesv1_cm.pc diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/glesv2/glesv2.c libhybris-0.1.0+git20151016+6d424c9/hybris/glesv2/glesv2.c --- libhybris-0.1.0+git20131207+e452e83/hybris/glesv2/glesv2.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/glesv2/glesv2.c 2015-07-30 07:51:13.000000000 +0000 @@ -22,1021 +22,404 @@ #include #include -#include -#include +#include +#include +#include static void *_libglesv2 = NULL; -static void (*_glActiveTexture)(GLenum texture) = NULL; -static void (*_glAttachShader)(GLuint program, GLuint shader) = NULL; -static void (*_glBindAttribLocation)(GLuint program, GLuint index, const GLchar* name) = NULL; -static void (*_glBindBuffer)(GLenum target, GLuint buffer) = NULL; -static void (*_glBindFramebuffer)(GLenum target, GLuint framebuffer) = NULL; -static void (*_glBindRenderbuffer)(GLenum target, GLuint renderbuffer) = NULL; -static void (*_glBindTexture)(GLenum target, GLuint texture) = NULL; +/* Only functions with floating point argument need a wrapper to change the call convention correctly */ + static void (*_glBlendColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) FP_ATTRIB = NULL; -static void (*_glBlendEquation)(GLenum mode ) = NULL; -static void (*_glBlendEquationSeparate)(GLenum modeRGB, GLenum modeAlpha) = NULL; -static void (*_glBlendFunc)(GLenum sfactor, GLenum dfactor) = NULL; -static void (*_glBlendFuncSeparate)(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) = NULL; -static void (*_glBufferData)(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) = NULL; -static void (*_glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) = NULL; -static GLenum (*_glCheckFramebufferStatus)(GLenum target) = NULL; -static void (*_glClear)(GLbitfield mask) = NULL; static void (*_glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) FP_ATTRIB = NULL; static void (*_glClearDepthf)(GLclampf depth) FP_ATTRIB = NULL; -static void (*_glClearStencil)(GLint s) = NULL; -static void (*_glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) = NULL; -static void (*_glCompileShader)(GLuint shader) = NULL; -static void (*_glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) = NULL; -static void (*_glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) = NULL; -static void (*_glCopyTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) = NULL; -static void (*_glCopyTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) = NULL; -static GLuint (*_glCreateProgram)(void) = NULL; -static GLuint (*_glCreateShader)(GLenum type) = NULL; -static void (*_glCullFace)(GLenum mode) = NULL; -static void (*_glDeleteBuffers)(GLsizei n, const GLuint* buffers) = NULL; -static void (*_glDeleteFramebuffers)(GLsizei n, const GLuint* framebuffers) = NULL; -static void (*_glDeleteProgram)(GLuint program) = NULL; -static void (*_glDeleteRenderbuffers)(GLsizei n, const GLuint* renderbuffers) = NULL; -static void (*_glDeleteShader)(GLuint shader) = NULL; -static void (*_glDeleteTextures)(GLsizei n, const GLuint* textures) = NULL; -static void (*_glDepthFunc)(GLenum func) = NULL; -static void (*_glDepthMask)(GLboolean flag) = NULL; static void (*_glDepthRangef)(GLclampf zNear, GLclampf zFar) FP_ATTRIB = NULL; -static void (*_glDetachShader)(GLuint program, GLuint shader) = NULL; -static void (*_glDisable)(GLenum cap) = NULL; -static void (*_glDisableVertexAttribArray)(GLuint index) = NULL; -static void (*_glDrawArrays)(GLenum mode, GLint first, GLsizei count) = NULL; -static void (*_glDrawElements)(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) = NULL; -static void (*_glEnable)(GLenum cap) = NULL; -static void (*_glEnableVertexAttribArray)(GLuint index) = NULL; -static void (*_glFinish)(void) = NULL; -static void (*_glFlush)(void) = NULL; -static void (*_glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) = NULL; -static void (*_glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) = NULL; -static void (*_glFrontFace)(GLenum mode) = NULL; -static void (*_glGenBuffers)(GLsizei n, GLuint* buffers) = NULL; -static void (*_glGenerateMipmap)(GLenum target) = NULL; -static void (*_glGenFramebuffers)(GLsizei n, GLuint* framebuffers) = NULL; -static void (*_glGenRenderbuffers)(GLsizei n, GLuint* renderbuffers) = NULL; -static void (*_glGenTextures)(GLsizei n, GLuint* textures) = NULL; -static void (*_glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) = NULL; -static void (*_glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) = NULL; -static void (*_glGetAttachedShaders)(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) = NULL; -static int (*_glGetAttribLocation)(GLuint program, const GLchar* name) = NULL; -static void (*_glGetBooleanv)(GLenum pname, GLboolean* params) = NULL; -static void (*_glGetBufferParameteriv)(GLenum target, GLenum pname, GLint* params) = NULL; -static GLenum (*_glGetError)(void) = NULL; -static void (*_glGetFloatv)(GLenum pname, GLfloat* params) = NULL; -static void (*_glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint* params) = NULL; -static void (*_glGetIntegerv)(GLenum pname, GLint* params) = NULL; -static void (*_glGetProgramiv)(GLuint program, GLenum pname, GLint* params) = NULL; -static void (*_glGetProgramInfoLog)(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog) = NULL; -static void (*_glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint* params) = NULL; -static void (*_glGetShaderiv)(GLuint shader, GLenum pname, GLint* params) = NULL; -static void (*_glGetShaderInfoLog)(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog) = NULL; -static void (*_glGetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) = NULL; -static void (*_glGetShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) = NULL; -static const GLubyte* (*_glGetString)(GLenum name) = NULL; -static void (*_glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat* params) = NULL; -static void (*_glGetTexParameteriv)(GLenum target, GLenum pname, GLint* params) = NULL; -static void (*_glGetUniformfv)(GLuint program, GLint location, GLfloat* params) = NULL; -static void (*_glGetUniformiv)(GLuint program, GLint location, GLint* params) = NULL; -static int (*_glGetUniformLocation)(GLuint program, const GLchar* name) = NULL; -static void (*_glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat* params) = NULL; -static void (*_glGetVertexAttribiv)(GLuint index, GLenum pname, GLint* params) = NULL; -static void (*_glGetVertexAttribPointerv)(GLuint index, GLenum pname, GLvoid** pointer) = NULL; -static void (*_glHint)(GLenum target, GLenum mode) = NULL; -static GLboolean (*_glIsBuffer)(GLuint buffer) = NULL; -static GLboolean (*_glIsEnabled)(GLenum cap) = NULL; -static GLboolean (*_glIsFramebuffer)(GLuint framebuffer) = NULL; -static GLboolean (*_glIsProgram)(GLuint program) = NULL; -static GLboolean (*_glIsRenderbuffer)(GLuint renderbuffer) = NULL; -static GLboolean (*_glIsShader)(GLuint shader) = NULL; -static GLboolean (*_glIsTexture)(GLuint texture) = NULL; static void (*_glLineWidth)(GLfloat width) FP_ATTRIB = NULL; -static void (*_glLinkProgram)(GLuint program) = NULL; -static void (*_glPixelStorei)(GLenum pname, GLint param) = NULL; static void (*_glPolygonOffset)(GLfloat factor, GLfloat units) FP_ATTRIB = NULL; -static void (*_glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) = NULL; -static void (*_glReleaseShaderCompiler)(void) = NULL; -static void (*_glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) = NULL; static void (*_glSampleCoverage)(GLclampf value, GLboolean invert) FP_ATTRIB = NULL; -static void (*_glScissor)(GLint x, GLint y, GLsizei width, GLsizei height) = NULL; -static void (*_glShaderBinary)(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length) = NULL; -static void (*_glShaderSource)(GLuint shader, GLsizei count, const GLchar** string, const GLint* length) = NULL; -static void (*_glStencilFunc)(GLenum func, GLint ref, GLuint mask) = NULL; -static void (*_glStencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask) = NULL; -static void (*_glStencilMask)(GLuint mask) = NULL; -static void (*_glStencilMaskSeparate)(GLenum face, GLuint mask) = NULL; -static void (*_glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass) = NULL; -static void (*_glStencilOpSeparate)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) = NULL; -static void (*_glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels) = NULL; static void (*_glTexParameterf)(GLenum target, GLenum pname, GLfloat param) FP_ATTRIB = NULL; -static void (*_glTexParameterfv)(GLenum target, GLenum pname, const GLfloat* params) = NULL; -static void (*_glTexParameteri)(GLenum target, GLenum pname, GLint param) = NULL; -static void (*_glTexParameteriv)(GLenum target, GLenum pname, const GLint* params) = NULL; -static void (*_glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) = NULL; static void (*_glUniform1f)(GLint location, GLfloat x) FP_ATTRIB = NULL; -static void (*_glUniform1fv)(GLint location, GLsizei count, const GLfloat* v) = NULL; -static void (*_glUniform1i)(GLint location, GLint x) = NULL; -static void (*_glUniform1iv)(GLint location, GLsizei count, const GLint* v) = NULL; static void (*_glUniform2f)(GLint location, GLfloat x, GLfloat y) FP_ATTRIB = NULL; -static void (*_glUniform2fv)(GLint location, GLsizei count, const GLfloat* v) = NULL; -static void (*_glUniform2i)(GLint location, GLint x, GLint y) = NULL; -static void (*_glUniform2iv)(GLint location, GLsizei count, const GLint* v) = NULL; static void (*_glUniform3f)(GLint location, GLfloat x, GLfloat y, GLfloat z) FP_ATTRIB = NULL; -static void (*_glUniform3fv)(GLint location, GLsizei count, const GLfloat* v) = NULL; -static void (*_glUniform3i)(GLint location, GLint x, GLint y, GLint z) = NULL; -static void (*_glUniform3iv)(GLint location, GLsizei count, const GLint* v) = NULL; static void (*_glUniform4f)(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) FP_ATTRIB = NULL; -static void (*_glUniform4fv)(GLint location, GLsizei count, const GLfloat* v) = NULL; -static void (*_glUniform4i)(GLint location, GLint x, GLint y, GLint z, GLint w) = NULL; -static void (*_glUniform4iv)(GLint location, GLsizei count, const GLint* v) = NULL; -static void (*_glUniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = NULL; -static void (*_glUniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = NULL; -static void (*_glUniformMatrix4fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = NULL; -static void (*_glUseProgram)(GLuint program) = NULL; -static void (*_glValidateProgram)(GLuint program) = NULL; static void (*_glVertexAttrib1f)(GLuint indx, GLfloat x) FP_ATTRIB = NULL; -static void (*_glVertexAttrib1fv)(GLuint indx, const GLfloat* values) = NULL; static void (*_glVertexAttrib2f)(GLuint indx, GLfloat x, GLfloat y) FP_ATTRIB = NULL; -static void (*_glVertexAttrib2fv)(GLuint indx, const GLfloat* values) = NULL; static void (*_glVertexAttrib3f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z) FP_ATTRIB = NULL; -static void (*_glVertexAttrib3fv)(GLuint indx, const GLfloat* values) = NULL; static void (*_glVertexAttrib4f)(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) FP_ATTRIB = NULL; -static void (*_glVertexAttrib4fv)(GLuint indx, const GLfloat* values) = NULL; -static void (*_glVertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) = NULL; -static void (*_glViewport)(GLint x, GLint y, GLsizei width, GLsizei height) = NULL; -static void (*_glEGLImageTargetTexture2DOES) (GLenum target, GLeglImageOES image) = NULL; +static void (*_glEGLImageTargetTexture2DOES)(GLenum target, GLeglImageOES image) = NULL; #define GLES2_LOAD(sym) { *(&_ ## sym) = (void *) android_dlsym(_libglesv2, #sym); } +/* +This generates a function that when first called overwrites it's plt entry with new address. Subsequent calls jump directly at the target function in the android library. This means effectively 0 call overhead after the first call. +*/ + +#define GLES2_IDLOAD(sym) \ + __asm__ (".type " #sym ", %gnu_indirect_function"); \ +typeof(sym) * sym ## _dispatch (void) __asm__ (#sym);\ +typeof(sym) * sym ## _dispatch (void) \ +{ \ + return (void *) android_dlsym(_libglesv2, #sym); \ +} + static void __attribute__((constructor)) _init_androidglesv2() { _libglesv2 = (void *) android_dlopen(getenv("LIBGLESV2") ? getenv("LIBGLESV2") : "libGLESv2.so", RTLD_NOW); - GLES2_LOAD(glActiveTexture); - GLES2_LOAD(glAttachShader); - GLES2_LOAD(glBindAttribLocation); - GLES2_LOAD(glBindBuffer); - GLES2_LOAD(glBindFramebuffer); - GLES2_LOAD(glBindRenderbuffer); - GLES2_LOAD(glBindTexture); GLES2_LOAD(glBlendColor); - GLES2_LOAD(glBlendEquation); - GLES2_LOAD(glBlendEquationSeparate); - GLES2_LOAD(glBlendFunc); - GLES2_LOAD(glBlendFuncSeparate); - GLES2_LOAD(glBufferData); - GLES2_LOAD(glBufferSubData); - GLES2_LOAD(glCheckFramebufferStatus); - GLES2_LOAD(glClear); GLES2_LOAD(glClearColor); GLES2_LOAD(glClearDepthf); - GLES2_LOAD(glClearStencil); - GLES2_LOAD(glColorMask); - GLES2_LOAD(glCompileShader); - GLES2_LOAD(glCompressedTexImage2D); - GLES2_LOAD(glCompressedTexSubImage2D); - GLES2_LOAD(glCopyTexImage2D); - GLES2_LOAD(glCopyTexSubImage2D); - GLES2_LOAD(glCreateProgram); - GLES2_LOAD(glCreateShader); - GLES2_LOAD(glCullFace); - GLES2_LOAD(glDeleteBuffers); - GLES2_LOAD(glDeleteFramebuffers); - GLES2_LOAD(glDeleteProgram); - GLES2_LOAD(glDeleteRenderbuffers); - GLES2_LOAD(glDeleteShader); - GLES2_LOAD(glDeleteTextures); - GLES2_LOAD(glDepthFunc); - GLES2_LOAD(glDepthMask); GLES2_LOAD(glDepthRangef); - GLES2_LOAD(glDetachShader); - GLES2_LOAD(glDisable); - GLES2_LOAD(glDisableVertexAttribArray); - GLES2_LOAD(glDrawArrays); - GLES2_LOAD(glDrawElements); - GLES2_LOAD(glEnable); - GLES2_LOAD(glEnableVertexAttribArray); - GLES2_LOAD(glFinish); - GLES2_LOAD(glFlush); - GLES2_LOAD(glFramebufferRenderbuffer); - GLES2_LOAD(glFramebufferTexture2D); - GLES2_LOAD(glFrontFace); - GLES2_LOAD(glGenBuffers); - GLES2_LOAD(glGenerateMipmap); - GLES2_LOAD(glGenFramebuffers); - GLES2_LOAD(glGenRenderbuffers); - GLES2_LOAD(glGenTextures); - GLES2_LOAD(glGetActiveAttrib); - GLES2_LOAD(glGetActiveUniform); - GLES2_LOAD(glGetAttachedShaders); - GLES2_LOAD(glGetAttribLocation); - GLES2_LOAD(glGetBooleanv); - GLES2_LOAD(glGetBufferParameteriv); - GLES2_LOAD(glGetError); - GLES2_LOAD(glGetFloatv); - GLES2_LOAD(glGetFramebufferAttachmentParameteriv); - GLES2_LOAD(glGetIntegerv); - GLES2_LOAD(glGetProgramiv); - GLES2_LOAD(glGetProgramInfoLog); - GLES2_LOAD(glGetRenderbufferParameteriv); - GLES2_LOAD(glGetShaderiv); - GLES2_LOAD(glGetShaderInfoLog); - GLES2_LOAD(glGetShaderPrecisionFormat); - GLES2_LOAD(glGetShaderSource); - GLES2_LOAD(glGetString); - GLES2_LOAD(glGetTexParameterfv); - GLES2_LOAD(glGetTexParameteriv); - GLES2_LOAD(glGetUniformfv); - GLES2_LOAD(glGetUniformiv); - GLES2_LOAD(glGetUniformLocation); - GLES2_LOAD(glGetVertexAttribfv); - GLES2_LOAD(glGetVertexAttribiv); - GLES2_LOAD(glGetVertexAttribPointerv); - GLES2_LOAD(glHint); - GLES2_LOAD(glIsBuffer); - GLES2_LOAD(glIsEnabled); - GLES2_LOAD(glIsFramebuffer); - GLES2_LOAD(glIsProgram); - GLES2_LOAD(glIsRenderbuffer); - GLES2_LOAD(glIsShader); - GLES2_LOAD(glIsTexture); GLES2_LOAD(glLineWidth); - GLES2_LOAD(glLinkProgram); - GLES2_LOAD(glPixelStorei); GLES2_LOAD(glPolygonOffset); - GLES2_LOAD(glReadPixels); - GLES2_LOAD(glReleaseShaderCompiler); - GLES2_LOAD(glRenderbufferStorage); GLES2_LOAD(glSampleCoverage); - GLES2_LOAD(glScissor); - GLES2_LOAD(glShaderBinary); - GLES2_LOAD(glShaderSource); - GLES2_LOAD(glStencilFunc); - GLES2_LOAD(glStencilFuncSeparate); - GLES2_LOAD(glStencilMask); - GLES2_LOAD(glStencilMaskSeparate); - GLES2_LOAD(glStencilOp); - GLES2_LOAD(glStencilOpSeparate); - GLES2_LOAD(glTexImage2D); GLES2_LOAD(glTexParameterf); - GLES2_LOAD(glTexParameterfv); - GLES2_LOAD(glTexParameteri); - GLES2_LOAD(glTexParameteriv); - GLES2_LOAD(glTexSubImage2D); GLES2_LOAD(glUniform1f); - GLES2_LOAD(glUniform1fv); - GLES2_LOAD(glUniform1i); - GLES2_LOAD(glUniform1iv); GLES2_LOAD(glUniform2f); - GLES2_LOAD(glUniform2fv); - GLES2_LOAD(glUniform2i); - GLES2_LOAD(glUniform2iv); GLES2_LOAD(glUniform3f); - GLES2_LOAD(glUniform3fv); - GLES2_LOAD(glUniform3i); - GLES2_LOAD(glUniform3iv); GLES2_LOAD(glUniform4f); - GLES2_LOAD(glUniform4fv); - GLES2_LOAD(glUniform4i); - GLES2_LOAD(glUniform4iv); - GLES2_LOAD(glUniformMatrix2fv); - GLES2_LOAD(glUniformMatrix3fv); - GLES2_LOAD(glUniformMatrix4fv); - GLES2_LOAD(glUseProgram); - GLES2_LOAD(glValidateProgram); GLES2_LOAD(glVertexAttrib1f); - GLES2_LOAD(glVertexAttrib1fv); GLES2_LOAD(glVertexAttrib2f); - GLES2_LOAD(glVertexAttrib2fv); GLES2_LOAD(glVertexAttrib3f); - GLES2_LOAD(glVertexAttrib3fv); GLES2_LOAD(glVertexAttrib4f); - GLES2_LOAD(glVertexAttrib4fv); - GLES2_LOAD(glVertexAttribPointer); - GLES2_LOAD(glViewport); GLES2_LOAD(glEGLImageTargetTexture2DOES); - } -void glActiveTexture (GLenum texture) -{ - return (*_glActiveTexture)(texture); -} +GLES2_IDLOAD(glActiveTexture); -void glAttachShader (GLuint program, GLuint shader) -{ - return (*_glAttachShader)(program, shader); -} +GLES2_IDLOAD(glAttachShader); -void glBindAttribLocation (GLuint program, GLuint index, const GLchar* name) -{ - return (*_glBindAttribLocation)(program, index, name); -} +GLES2_IDLOAD(glBindAttribLocation); -void glBindBuffer (GLenum target, GLuint buffer) -{ - return (*_glBindBuffer)(target, buffer); -} +GLES2_IDLOAD(glBindBuffer); -void glBindFramebuffer (GLenum target, GLuint framebuffer) -{ - return (*_glBindFramebuffer)(target, framebuffer); -} +GLES2_IDLOAD(glBindFramebuffer); -void glBindRenderbuffer (GLenum target, GLuint renderbuffer) -{ - return (*_glBindRenderbuffer)(target, renderbuffer); -} +GLES2_IDLOAD(glBindRenderbuffer); -void glBindTexture (GLenum target, GLuint texture) -{ - return (*_glBindTexture)(target, texture); -} +GLES2_IDLOAD(glBindTexture); -void glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) -{ - return (*_glBlendColor)(red, green, blue, alpha); -} +GLES2_IDLOAD(glBlendEquation); -void glBlendEquation ( GLenum mode ) -{ - return (*_glBlendEquation)(mode); -} +GLES2_IDLOAD(glBlendEquationSeparate); -void glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha) -{ - return (*_glBlendEquationSeparate)(modeRGB, modeAlpha); -} +GLES2_IDLOAD(glBlendFunc); -void glBlendFunc (GLenum sfactor, GLenum dfactor) -{ - return (*_glBlendFunc)(sfactor, dfactor); -} +GLES2_IDLOAD(glBlendFuncSeparate); -void glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) -{ - return (*_glBlendFuncSeparate)(srcRGB, dstRGB, srcAlpha, dstAlpha); -} +GLES2_IDLOAD(glBufferData); -void glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) -{ - return (*_glBufferData)(target, size, data, usage); -} +GLES2_IDLOAD(glBufferSubData); -void glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) -{ - return (*_glBufferSubData)(target, offset, size, data); -} +GLES2_IDLOAD(glCheckFramebufferStatus); -GLenum glCheckFramebufferStatus (GLenum target) -{ - return (*_glCheckFramebufferStatus)(target); -} +GLES2_IDLOAD(glClear); -void glClear (GLbitfield mask) -{ - return (*_glClear)(mask); -} +GLES2_IDLOAD(glClearStencil); -void glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) -{ - return (*_glClearColor)(red, green, blue, alpha); -} +GLES2_IDLOAD(glColorMask); -void glClearDepthf (GLclampf depth) -{ - return (*_glClearDepthf)(depth); -} +GLES2_IDLOAD(glCompileShader); -void glClearStencil (GLint s) -{ - return (*_glClearStencil)(s); -} +GLES2_IDLOAD(glCompressedTexImage2D); -void glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) -{ - return (*_glColorMask)(red, green, blue, alpha); -} +GLES2_IDLOAD(glCompressedTexSubImage2D); -void glCompileShader (GLuint shader) -{ - return (*_glCompileShader)(shader); -} +GLES2_IDLOAD(glCopyTexImage2D); -void glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) -{ - return (*_glCompressedTexImage2D)(target, level, internalformat, width, height, border, imageSize, data); -} +GLES2_IDLOAD(glCopyTexSubImage2D); -void glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data) -{ - return (*_glCompressedTexSubImage2D)(target, level, xoffset, yoffset, width, height, format, imageSize, data); -} +GLES2_IDLOAD(glCreateProgram); -void glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) -{ - return (*_glCopyTexImage2D)(target, level, internalformat, x, y, width, height, border); -} +GLES2_IDLOAD(glCreateShader); -void glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) -{ - return (*_glCopyTexSubImage2D)(target, level, xoffset, yoffset, x, y, width, height); -} +GLES2_IDLOAD(glCullFace); -GLuint glCreateProgram (void) -{ - return (*_glCreateProgram)(); -} +GLES2_IDLOAD(glDeleteBuffers); -GLuint glCreateShader (GLenum type) -{ - return (*_glCreateShader)(type); -} +GLES2_IDLOAD(glDeleteFramebuffers); -void glCullFace (GLenum mode) -{ - return (*_glCullFace)(mode); -} +GLES2_IDLOAD(glDeleteProgram); -void glDeleteBuffers (GLsizei n, const GLuint* buffers) -{ - return (*_glDeleteBuffers)(n, buffers); -} +GLES2_IDLOAD(glDeleteRenderbuffers); -void glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers) -{ - return (*_glDeleteFramebuffers)(n, framebuffers); -} +GLES2_IDLOAD(glDeleteShader); -void glDeleteProgram (GLuint program) -{ - return (*_glDeleteProgram)(program); -} +GLES2_IDLOAD(glDeleteTextures); -void glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers) -{ - return (*_glDeleteRenderbuffers)(n, renderbuffers); -} +GLES2_IDLOAD(glDepthFunc); -void glDeleteShader (GLuint shader) -{ - return (*_glDeleteShader)(shader); -} +GLES2_IDLOAD(glDepthMask); -void glDeleteTextures (GLsizei n, const GLuint* textures) -{ - return (*_glDeleteTextures)(n, textures); -} +GLES2_IDLOAD(glDetachShader); -void glDepthFunc (GLenum func) -{ - return (*_glDepthFunc)(func); -} +GLES2_IDLOAD(glDisable); -void glDepthMask (GLboolean flag) -{ - return (*_glDepthMask)(flag); -} +GLES2_IDLOAD(glDisableVertexAttribArray); -void glDepthRangef (GLclampf zNear, GLclampf zFar) -{ - return (*_glDepthRangef)(zNear, zFar); -} - -void glDetachShader (GLuint program, GLuint shader) -{ - return (*_glDetachShader)(program, shader); -} +GLES2_IDLOAD(glDrawArrays); -void glDisable (GLenum cap) -{ - return (*_glDisable)(cap); -} +GLES2_IDLOAD(glDrawElements); -void glDisableVertexAttribArray (GLuint index) -{ - return (*_glDisableVertexAttribArray)(index); -} +GLES2_IDLOAD(glEnable); -void glDrawArrays (GLenum mode, GLint first, GLsizei count) -{ - return (*_glDrawArrays)(mode, first, count); -} +GLES2_IDLOAD(glEnableVertexAttribArray); -void glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) -{ - return (*_glDrawElements)(mode, count, type, indices); -} +GLES2_IDLOAD(glFinish); -void glEnable (GLenum cap) -{ - return (*_glEnable)(cap); -} +GLES2_IDLOAD(glFlush); -void glEnableVertexAttribArray (GLuint index) -{ - return (*_glEnableVertexAttribArray)(index); -} +GLES2_IDLOAD(glFramebufferRenderbuffer); -void glFinish (void) -{ - return (*_glFinish)(); -} +GLES2_IDLOAD(glFramebufferTexture2D); -void glFlush (void) -{ - return (*_glFlush)(); -} +GLES2_IDLOAD(glFrontFace); -void glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) -{ - return (*_glFramebufferRenderbuffer)(target, attachment, renderbuffertarget, renderbuffer); -} +GLES2_IDLOAD(glGenBuffers); -void glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) -{ - return (*_glFramebufferTexture2D)(target, attachment, textarget, texture, level); -} +GLES2_IDLOAD(glGenerateMipmap); -void glFrontFace (GLenum mode) -{ - return (*_glFrontFace)(mode); -} +GLES2_IDLOAD(glGenFramebuffers); -void glGenBuffers (GLsizei n, GLuint* buffers) -{ - return (*_glGenBuffers)(n, buffers); -} +GLES2_IDLOAD(glGenRenderbuffers); -void glGenerateMipmap (GLenum target) -{ - return (*_glGenerateMipmap)(target); -} +GLES2_IDLOAD(glGenTextures); -void glGenFramebuffers (GLsizei n, GLuint* framebuffers) -{ - return (*_glGenFramebuffers)(n, framebuffers); -} +GLES2_IDLOAD(glGetActiveAttrib); -void glGenRenderbuffers (GLsizei n, GLuint* renderbuffers) -{ - return (*_glGenRenderbuffers)(n, renderbuffers); -} +GLES2_IDLOAD(glGetActiveUniform); -void glGenTextures (GLsizei n, GLuint* textures) -{ - return (*_glGenTextures)(n, textures); -} +GLES2_IDLOAD(glGetAttachedShaders); -void glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) -{ - return (*_glGetActiveAttrib)(program, index, bufsize, length, size, type, name); -} +GLES2_IDLOAD(glGetAttribLocation); -void glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name) -{ - return (*_glGetActiveUniform)(program, index, bufsize, length, size, type, name); -} +GLES2_IDLOAD(glGetBooleanv); -void glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) -{ - return (*_glGetAttachedShaders)(program, maxcount, count, shaders); -} +GLES2_IDLOAD(glGetBufferParameteriv); -int glGetAttribLocation (GLuint program, const GLchar* name) -{ - return (*_glGetAttribLocation)(program, name); -} +GLES2_IDLOAD(glGetError); -void glGetBooleanv (GLenum pname, GLboolean* params) -{ - return (*_glGetBooleanv)(pname, params); -} +GLES2_IDLOAD(glGetFloatv); -void glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params) -{ - return (*_glGetBufferParameteriv)(target, pname, params); -} +GLES2_IDLOAD(glGetFramebufferAttachmentParameteriv); -GLenum glGetError (void) -{ - return (*_glGetError)(); -} +GLES2_IDLOAD(glGetIntegerv); -void glGetFloatv (GLenum pname, GLfloat* params) -{ - return (*_glGetFloatv)(pname, params); -} +GLES2_IDLOAD(glGetProgramiv); -void glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params) -{ - return (*_glGetFramebufferAttachmentParameteriv)(target, attachment, pname, params); -} +GLES2_IDLOAD(glGetProgramInfoLog); -void glGetIntegerv (GLenum pname, GLint* params) -{ - return (*_glGetIntegerv)(pname, params); -} +GLES2_IDLOAD(glGetRenderbufferParameteriv); -void glGetProgramiv (GLuint program, GLenum pname, GLint* params) -{ - return (*_glGetProgramiv)(program, pname, params); -} +GLES2_IDLOAD(glGetShaderiv); -void glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog) -{ - return (*_glGetProgramInfoLog)(program, bufsize, length, infolog); -} +GLES2_IDLOAD(glGetShaderInfoLog); -void glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params) -{ - return (*_glGetRenderbufferParameteriv)(target, pname, params); -} +GLES2_IDLOAD(glGetShaderPrecisionFormat); -void glGetShaderiv (GLuint shader, GLenum pname, GLint* params) -{ - return (*_glGetShaderiv)(shader, pname, params); -} +GLES2_IDLOAD(glGetShaderSource); -void glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog) -{ - return (*_glGetShaderInfoLog)(shader, bufsize, length, infolog); -} +GLES2_IDLOAD(glGetString); -void glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) -{ - return (*_glGetShaderPrecisionFormat)(shadertype, precisiontype, range, precision); -} +GLES2_IDLOAD(glGetTexParameterfv); -void glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source) -{ - return (*_glGetShaderSource)(shader, bufsize, length, source); -} +GLES2_IDLOAD(glGetTexParameteriv); -const GLubyte* glGetString (GLenum name) -{ - return (*_glGetString)(name); -} +GLES2_IDLOAD(glGetUniformfv); -void glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params) -{ - return (*_glGetTexParameterfv)(target, pname, params); -} +GLES2_IDLOAD(glGetUniformiv); -void glGetTexParameteriv (GLenum target, GLenum pname, GLint* params) -{ - return (*_glGetTexParameteriv)(target, pname, params); -} +GLES2_IDLOAD(glGetUniformLocation); -void glGetUniformfv (GLuint program, GLint location, GLfloat* params) -{ - return (*_glGetUniformfv)(program, location, params); -} +GLES2_IDLOAD(glGetVertexAttribfv); -void glGetUniformiv (GLuint program, GLint location, GLint* params) -{ - return (*_glGetUniformiv)(program, location, params); -} +GLES2_IDLOAD(glGetVertexAttribiv); -int glGetUniformLocation (GLuint program, const GLchar* name) -{ - return (*_glGetUniformLocation)(program, name); -} +GLES2_IDLOAD(glGetVertexAttribPointerv); -void glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params) -{ - return (*_glGetVertexAttribfv)(index, pname, params); -} +GLES2_IDLOAD(glHint); -void glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params) -{ - return (*_glGetVertexAttribiv)(index, pname, params); -} +GLES2_IDLOAD(glIsBuffer); -void glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer) -{ - return (*_glGetVertexAttribPointerv)(index, pname, pointer); -} +GLES2_IDLOAD(glIsEnabled); -void glHint (GLenum target, GLenum mode) -{ - return (*_glHint)(target, mode); -} +GLES2_IDLOAD(glIsFramebuffer); -GLboolean glIsBuffer (GLuint buffer) -{ - return (*_glIsBuffer)(buffer); -} +GLES2_IDLOAD(glIsProgram); -GLboolean glIsEnabled (GLenum cap) -{ - return (*_glIsEnabled)(cap); -} +GLES2_IDLOAD(glIsRenderbuffer); -GLboolean glIsFramebuffer (GLuint framebuffer) -{ - return (*_glIsFramebuffer)(framebuffer); -} +GLES2_IDLOAD(glIsShader); -GLboolean glIsProgram (GLuint program) -{ - return (*_glIsProgram)(program); -} +GLES2_IDLOAD(glIsTexture); -GLboolean glIsRenderbuffer (GLuint renderbuffer) -{ - return (*_glIsRenderbuffer)(renderbuffer); -} +GLES2_IDLOAD(glLinkProgram); -GLboolean glIsShader (GLuint shader) -{ - return (*_glIsShader)(shader); -} +GLES2_IDLOAD(glPixelStorei); -GLboolean glIsTexture (GLuint texture) -{ - return (*_glIsTexture)(texture); -} +GLES2_IDLOAD(glReadPixels); -void glLineWidth (GLfloat width) -{ - return (*_glLineWidth)(width); -} +GLES2_IDLOAD(glReleaseShaderCompiler); -void glLinkProgram (GLuint program) -{ - return (*_glLinkProgram)(program); -} +GLES2_IDLOAD(glRenderbufferStorage); -void glPixelStorei (GLenum pname, GLint param) -{ - return (*_glPixelStorei)(pname, param); -} +GLES2_IDLOAD(glScissor); -void glPolygonOffset (GLfloat factor, GLfloat units) -{ - return (*_glPolygonOffset)(factor, units); -} +GLES2_IDLOAD(glShaderBinary); -void glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels) -{ - return (*_glReadPixels)(x, y, width, height, format, type, pixels); +GLES2_IDLOAD(glShaderSource); -} +GLES2_IDLOAD(glStencilFunc); -void glReleaseShaderCompiler (void) -{ - return (*_glReleaseShaderCompiler)(); -} +GLES2_IDLOAD(glStencilFuncSeparate); -void glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height) -{ - return (*_glRenderbufferStorage)(target, internalformat, width, height); -} +GLES2_IDLOAD(glStencilMask); -void glSampleCoverage (GLclampf value, GLboolean invert) -{ - return (*_glSampleCoverage)(value, invert); -} +GLES2_IDLOAD(glStencilMaskSeparate); -void glScissor (GLint x, GLint y, GLsizei width, GLsizei height) -{ - return (*_glScissor)(x, y, width, height); -} +GLES2_IDLOAD(glStencilOp); -void glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length) -{ - return (*_glShaderBinary)(n, shaders, binaryformat, binary, length); -} +GLES2_IDLOAD(glStencilOpSeparate); -void glShaderSource (GLuint shader, GLsizei count, const GLchar** string, const GLint* length) -{ - return (*_glShaderSource)(shader, count, string, length); -} +GLES2_IDLOAD(glTexImage2D); -void glStencilFunc (GLenum func, GLint ref, GLuint mask) -{ - return (*_glStencilFunc)(func, ref, mask); -} +GLES2_IDLOAD(glTexParameterfv); -void glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask) -{ - return (*_glStencilFuncSeparate)(face, func, ref, mask); -} +GLES2_IDLOAD(glTexParameteri); -void glStencilMask (GLuint mask) -{ - return (*_glStencilMask)(mask); -} +GLES2_IDLOAD(glTexParameteriv); -void glStencilMaskSeparate (GLenum face, GLuint mask) -{ - return (*_glStencilMaskSeparate)(face, mask); -} +GLES2_IDLOAD(glTexSubImage2D); -void glStencilOp (GLenum fail, GLenum zfail, GLenum zpass) -{ - return (*_glStencilOp)(fail, zfail, zpass); -} +GLES2_IDLOAD(glUniform1fv); -void glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass) -{ - return (*_glStencilOpSeparate)(face, fail, zfail, zpass); -} +GLES2_IDLOAD(glUniform1i); -void glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels) -{ - return (*_glTexImage2D)(target, level, internalformat, width, height, border, format, type, pixels); -} +GLES2_IDLOAD(glUniform1iv); -void glTexParameterf (GLenum target, GLenum pname, GLfloat param) -{ - return (*_glTexParameterf)(target, pname, param); -} +GLES2_IDLOAD(glUniform2fv); -void glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params) -{ - return (*_glTexParameterfv)(target, pname, params); -} +GLES2_IDLOAD(glUniform2i); -void glTexParameteri (GLenum target, GLenum pname, GLint param) -{ - return (*_glTexParameteri)(target, pname, param); -} +GLES2_IDLOAD(glUniform2iv); -void glTexParameteriv (GLenum target, GLenum pname, const GLint* params) -{ - return (*_glTexParameteriv)(target, pname, params); -} +GLES2_IDLOAD(glUniform3fv); -void glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels) -{ - return (*_glTexSubImage2D)(target, level, xoffset, yoffset, width, height, format, type, pixels); -} +GLES2_IDLOAD(glUniform3i); -void glUniform1f (GLint location, GLfloat x) -{ - return (*_glUniform1f)(location, x); -} +GLES2_IDLOAD(glUniform3iv); -void glUniform1fv (GLint location, GLsizei count, const GLfloat* v) -{ - return (*_glUniform1fv)(location, count, v); -} +GLES2_IDLOAD(glUniform4fv); -void glUniform1i (GLint location, GLint x) -{ - return (*_glUniform1i)(location, x); -} +GLES2_IDLOAD(glUniform4i); -void glUniform1iv (GLint location, GLsizei count, const GLint* v) -{ - return (*_glUniform1iv)(location, count, v); -} +GLES2_IDLOAD(glUniform4iv); -void glUniform2f (GLint location, GLfloat x, GLfloat y) -{ - return (*_glUniform2f)(location, x, y); -} +GLES2_IDLOAD(glUniformMatrix2fv); -void glUniform2fv (GLint location, GLsizei count, const GLfloat* v) -{ - return (*_glUniform2fv)(location, count, v); -} +GLES2_IDLOAD(glUniformMatrix3fv); -void glUniform2i (GLint location, GLint x, GLint y) -{ - return (*_glUniform2i)(location, x, y); -} +GLES2_IDLOAD(glUniformMatrix4fv); -void glUniform2iv (GLint location, GLsizei count, const GLint* v) -{ - return (*_glUniform2iv)(location, count, v); -} +GLES2_IDLOAD(glUseProgram); -void glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z) -{ - return (*_glUniform3f)(location, x, y, z); -} +GLES2_IDLOAD(glValidateProgram); -void glUniform3fv (GLint location, GLsizei count, const GLfloat* v) -{ - return (*_glUniform3fv)(location, count, v); -} +GLES2_IDLOAD(glVertexAttrib1fv); -void glUniform3i (GLint location, GLint x, GLint y, GLint z) -{ - return (*_glUniform3i)(location, x, y, z); -} +GLES2_IDLOAD(glVertexAttrib2fv); -void glUniform3iv (GLint location, GLsizei count, const GLint* v) -{ - return (*_glUniform3iv)(location, count, v); -} +GLES2_IDLOAD(glVertexAttrib3fv); -void glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) -{ - return (*_glUniform4f)(location, x, y, z, w); -} +GLES2_IDLOAD(glVertexAttrib4fv); -void glUniform4fv (GLint location, GLsizei count, const GLfloat* v) -{ - return (*_glUniform4fv)(location, count, v); -} +GLES2_IDLOAD(glVertexAttribPointer); -void glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w) -{ - return (*_glUniform4i)(location, x, y, z, w); -} +GLES2_IDLOAD(glViewport); -void glUniform4iv (GLint location, GLsizei count, const GLint* v) +void glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) { - return (*_glUniform4iv)(location, count, v); + struct egl_image *img = image; + return (*_glEGLImageTargetTexture2DOES)(target, img ? img->egl_image : NULL); } -void glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +void glBlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { - return (*_glUniformMatrix2fv)(location, count, transpose, value); + return (*_glBlendColor)(red, green, blue, alpha); } -void glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +void glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { - return (*_glUniformMatrix3fv)(location, count, transpose, value); + return (*_glVertexAttrib4f)(indx, x, y, z, w); } -void glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +void glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y) { - return (*_glUniformMatrix4fv)(location, count, transpose, value); + return (*_glVertexAttrib2f)(indx, x, y); } -void glUseProgram (GLuint program) +void glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z) { - return (*_glUseProgram)(program); + return (*_glVertexAttrib3f)(indx, x, y, z); } -void glValidateProgram (GLuint program) -{ - return (*_glValidateProgram)(program); -} void glVertexAttrib1f (GLuint indx, GLfloat x) { return (*_glVertexAttrib1f)(indx, x); } -void glVertexAttrib1fv (GLuint indx, const GLfloat* values) +void glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { - return (*_glVertexAttrib1fv)(indx, values); + return (*_glUniform4f)(location, x, y, z, w); } -void glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y) +void glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z) { - return (*_glVertexAttrib2f)(indx, x, y); + return (*_glUniform3f)(location, x, y, z); } -void glVertexAttrib2fv (GLuint indx, const GLfloat* values) +void glUniform2f (GLint location, GLfloat x, GLfloat y) { - return (*_glVertexAttrib2fv)(indx, values); + return (*_glUniform2f)(location, x, y); } -void glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z) +void glUniform1f (GLint location, GLfloat x) { - return (*_glVertexAttrib3f)(indx, x, y, z); + return (*_glUniform1f)(location, x); } -void glVertexAttrib3fv (GLuint indx, const GLfloat* values) +void glTexParameterf (GLenum target, GLenum pname, GLfloat param) { - return (*_glVertexAttrib3fv)(indx, values); + return (*_glTexParameterf)(target, pname, param); } -void glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +void glSampleCoverage (GLclampf value, GLboolean invert) { - return (*_glVertexAttrib4f)(indx, x, y, z, w); + return (*_glSampleCoverage)(value, invert); } - -void glVertexAttrib4fv (GLuint indx, const GLfloat* values) +void glPolygonOffset (GLfloat factor, GLfloat units) { - return (*_glVertexAttrib4fv)(indx, values); + return (*_glPolygonOffset)(factor, units); } - -void glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) +void glDepthRangef (GLclampf zNear, GLclampf zFar) { - return (*_glVertexAttribPointer)(indx, size, type, normalized, stride, ptr); + return (*_glDepthRangef)(zNear, zFar); } -void glViewport (GLint x, GLint y, GLsizei width, GLsizei height) + +void glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { - return (*_glViewport)(x, y, width, height); + return (*_glClearColor)(red, green, blue, alpha); } -void glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image) +void glClearDepthf (GLclampf depth) { - (*_glEGLImageTargetTexture2DOES)(target, image); + return (*_glClearDepthf)(depth); +} +void glLineWidth (GLfloat width) +{ + return (*_glLineWidth)(width); } diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/glesv2/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/glesv2/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/glesv2/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/glesv2/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -2,7 +2,7 @@ libGLESv2.la libGLESv2_la_SOURCES = glesv2.c -libGLESv2_la_CFLAGS = -I$(top_srcdir)/include +libGLESv2_la_CFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include $(ANDROID_HEADERS_CFLAGS) pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = glesv2.pc diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/hardware/hardware.c libhybris-0.1.0+git20151016+6d424c9/hybris/hardware/hardware.c --- libhybris-0.1.0+git20131207+e452e83/hybris/hardware/hardware.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/hardware/hardware.c 2015-07-30 07:51:13.000000000 +0000 @@ -15,10 +15,11 @@ * */ +#include #include #include -#include -#include +#include +#include static void *_libhardware = NULL; @@ -30,7 +31,7 @@ static void _init_lib_hardware() { - _libhardware = (void *) android_dlopen("/system/lib/libhardware.so", RTLD_LAZY); + _libhardware = (void *) android_dlopen("libhardware.so", RTLD_LAZY); } int hw_get_module(const char *id, const struct hw_module_t **module) diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/hardware/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/hardware/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/hardware/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/hardware/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -5,7 +5,7 @@ pkgconfig_DATA = libhardware.pc libhardware_la_SOURCES = hardware.c -libhardware_la_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/android +libhardware_la_CFLAGS = -I$(top_srcdir)/include $(ANDROID_HEADERS_CFLAGS) if WANT_TRACE libhardware_la_CFLAGS += -DDEBUG endif diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/include/EGL/eglext.h libhybris-0.1.0+git20151016+6d424c9/hybris/include/EGL/eglext.h --- libhybris-0.1.0+git20131207+e452e83/hybris/include/EGL/eglext.h 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/EGL/eglext.h 2015-07-30 07:51:13.000000000 +0000 @@ -456,6 +456,22 @@ #endif #endif + +#ifndef EGL_EXT_swap_buffers_with_damage +#define EGL_EXT_swap_buffers_with_damage 1 +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageEXT( EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects); +#endif /* EGL_EGLEXT_PROTOTYPES */ +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC)(EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects); +#endif + + +#ifndef EGL_EXT_buffer_age +#define EGL_EXT_buffer_age 1 +#define EGL_BUFFER_AGE_EXT 0x313D +#endif + + #include #ifdef __cplusplus diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/common/binding.h libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/common/binding.h --- libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/common/binding.h 1970-01-01 00:00:00.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/common/binding.h 2015-07-30 07:51:13.000000000 +0000 @@ -0,0 +1,448 @@ + +/** + * Copyright (C) 2013 Simon Busch + * 2012 Canonical Ltd + * 2013 Jolla Ltd. + * + * Auto-generated via "generate_wrapper_macros.py" + * + * 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 HYBRIS_BINDING_H_ +#define HYBRIS_BINDING_H_ + +/* floating_point_abi.h defines FP_ATTRIB */ +#include + +void *android_dlopen(const char *filename, int flag); +void *android_dlsym(void *name, const char *symbol); +int android_dlclose(void *handle); +const char *android_dlerror(void); +int android_dladdr(const void *addr, void *info); + + + +/** + * XXX AUTO-GENERATED FILE XXX + * + * Do not edit this file directly, but update the templates in + * utils/generate_wrapper_macros.py and run it again to build + * an updated version of this header file: + * + * python utils/generate_wrapper_macros.py > \ + * hybris/include/hybris/common/binding.h + * + * If you need macros with more arguments, just customize the + * MAX_ARGS variable in generate_wrapper_macros.py. + * + * XXX AUTO-GENERATED FILE XXX + **/ + + +#define HYBRIS_DLSYSM(name, fptr, sym) \ + if (!name##_handle) \ + hybris_##name##_initialize(); \ + if (*(fptr) == NULL) \ + { \ + *(fptr) = (void *) android_dlsym(name##_handle, sym); \ + } + +#define HYBRIS_LIBRARY_INITIALIZE(name, path) \ + void *name##_handle; \ + void hybris_##name##_initialize() \ + { \ + name##_handle = android_dlopen(path, RTLD_LAZY); \ + } + + + +#define HYBRIS_IMPLEMENT_FUNCTION0(name, return_type, symbol) \ + return_type symbol() \ + { \ + static return_type (*f)() FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + return f(); \ + } + + +#define HYBRIS_IMPLEMENT_FUNCTION1(name, return_type, symbol, a1) \ + return_type symbol(a1 n1) \ + { \ + static return_type (*f)(a1) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + return f(n1); \ + } + + +#define HYBRIS_IMPLEMENT_FUNCTION2(name, return_type, symbol, a1, a2) \ + return_type symbol(a1 n1, a2 n2) \ + { \ + static return_type (*f)(a1, a2) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + return f(n1, n2); \ + } + + +#define HYBRIS_IMPLEMENT_FUNCTION3(name, return_type, symbol, a1, a2, a3) \ + return_type symbol(a1 n1, a2 n2, a3 n3) \ + { \ + static return_type (*f)(a1, a2, a3) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + return f(n1, n2, n3); \ + } + + +#define HYBRIS_IMPLEMENT_FUNCTION4(name, return_type, symbol, a1, a2, a3, a4) \ + return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4) \ + { \ + static return_type (*f)(a1, a2, a3, a4) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + return f(n1, n2, n3, n4); \ + } + + +#define HYBRIS_IMPLEMENT_FUNCTION5(name, return_type, symbol, a1, a2, a3, a4, a5) \ + return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5) \ + { \ + static return_type (*f)(a1, a2, a3, a4, a5) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + return f(n1, n2, n3, n4, n5); \ + } + + +#define HYBRIS_IMPLEMENT_FUNCTION6(name, return_type, symbol, a1, a2, a3, a4, a5, a6) \ + return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6) \ + { \ + static return_type (*f)(a1, a2, a3, a4, a5, a6) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + return f(n1, n2, n3, n4, n5, n6); \ + } + + +#define HYBRIS_IMPLEMENT_FUNCTION7(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7) \ + return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7) \ + { \ + static return_type (*f)(a1, a2, a3, a4, a5, a6, a7) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + return f(n1, n2, n3, n4, n5, n6, n7); \ + } + + +#define HYBRIS_IMPLEMENT_FUNCTION8(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8) \ + return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8) \ + { \ + static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + return f(n1, n2, n3, n4, n5, n6, n7, n8); \ + } + + +#define HYBRIS_IMPLEMENT_FUNCTION9(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9) \ + return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9) \ + { \ + static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + return f(n1, n2, n3, n4, n5, n6, n7, n8, n9); \ + } + + +#define HYBRIS_IMPLEMENT_FUNCTION10(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \ + return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10) \ + { \ + static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + return f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10); \ + } + + +#define HYBRIS_IMPLEMENT_FUNCTION11(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) \ + return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11) \ + { \ + static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + return f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11); \ + } + + +#define HYBRIS_IMPLEMENT_FUNCTION12(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) \ + return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12) \ + { \ + static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + return f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12); \ + } + + +#define HYBRIS_IMPLEMENT_FUNCTION13(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) \ + return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13) \ + { \ + static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + return f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13); \ + } + + +#define HYBRIS_IMPLEMENT_FUNCTION14(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) \ + return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14) \ + { \ + static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + return f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14); \ + } + + +#define HYBRIS_IMPLEMENT_FUNCTION15(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) \ + return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14, a15 n15) \ + { \ + static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + return f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15); \ + } + + +#define HYBRIS_IMPLEMENT_FUNCTION16(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) \ + return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14, a15 n15, a16 n16) \ + { \ + static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + return f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16); \ + } + + +#define HYBRIS_IMPLEMENT_FUNCTION17(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) \ + return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14, a15 n15, a16 n16, a17 n17) \ + { \ + static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + return f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17); \ + } + + +#define HYBRIS_IMPLEMENT_FUNCTION18(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) \ + return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14, a15 n15, a16 n16, a17 n17, a18 n18) \ + { \ + static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + return f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18); \ + } + + +#define HYBRIS_IMPLEMENT_FUNCTION19(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) \ + return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14, a15 n15, a16 n16, a17 n17, a18 n18, a19 n19) \ + { \ + static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + return f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18, n19); \ + } + + +#define HYBRIS_IMPLEMENT_VOID_FUNCTION0(name, symbol) \ + void symbol() \ + { \ + static void (*f)() FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + f(); \ + } + + +#define HYBRIS_IMPLEMENT_VOID_FUNCTION1(name, symbol, a1) \ + void symbol(a1 n1) \ + { \ + static void (*f)(a1) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + f(n1); \ + } + + +#define HYBRIS_IMPLEMENT_VOID_FUNCTION2(name, symbol, a1, a2) \ + void symbol(a1 n1, a2 n2) \ + { \ + static void (*f)(a1, a2) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + f(n1, n2); \ + } + + +#define HYBRIS_IMPLEMENT_VOID_FUNCTION3(name, symbol, a1, a2, a3) \ + void symbol(a1 n1, a2 n2, a3 n3) \ + { \ + static void (*f)(a1, a2, a3) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + f(n1, n2, n3); \ + } + + +#define HYBRIS_IMPLEMENT_VOID_FUNCTION4(name, symbol, a1, a2, a3, a4) \ + void symbol(a1 n1, a2 n2, a3 n3, a4 n4) \ + { \ + static void (*f)(a1, a2, a3, a4) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + f(n1, n2, n3, n4); \ + } + + +#define HYBRIS_IMPLEMENT_VOID_FUNCTION5(name, symbol, a1, a2, a3, a4, a5) \ + void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5) \ + { \ + static void (*f)(a1, a2, a3, a4, a5) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + f(n1, n2, n3, n4, n5); \ + } + + +#define HYBRIS_IMPLEMENT_VOID_FUNCTION6(name, symbol, a1, a2, a3, a4, a5, a6) \ + void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6) \ + { \ + static void (*f)(a1, a2, a3, a4, a5, a6) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + f(n1, n2, n3, n4, n5, n6); \ + } + + +#define HYBRIS_IMPLEMENT_VOID_FUNCTION7(name, symbol, a1, a2, a3, a4, a5, a6, a7) \ + void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7) \ + { \ + static void (*f)(a1, a2, a3, a4, a5, a6, a7) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + f(n1, n2, n3, n4, n5, n6, n7); \ + } + + +#define HYBRIS_IMPLEMENT_VOID_FUNCTION8(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8) \ + void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8) \ + { \ + static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + f(n1, n2, n3, n4, n5, n6, n7, n8); \ + } + + +#define HYBRIS_IMPLEMENT_VOID_FUNCTION9(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9) \ + void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9) \ + { \ + static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + f(n1, n2, n3, n4, n5, n6, n7, n8, n9); \ + } + + +#define HYBRIS_IMPLEMENT_VOID_FUNCTION10(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \ + void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10) \ + { \ + static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10); \ + } + + +#define HYBRIS_IMPLEMENT_VOID_FUNCTION11(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) \ + void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11) \ + { \ + static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11); \ + } + + +#define HYBRIS_IMPLEMENT_VOID_FUNCTION12(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) \ + void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12) \ + { \ + static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12); \ + } + + +#define HYBRIS_IMPLEMENT_VOID_FUNCTION13(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) \ + void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13) \ + { \ + static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13); \ + } + + +#define HYBRIS_IMPLEMENT_VOID_FUNCTION14(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) \ + void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14) \ + { \ + static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14); \ + } + + +#define HYBRIS_IMPLEMENT_VOID_FUNCTION15(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) \ + void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14, a15 n15) \ + { \ + static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15); \ + } + + +#define HYBRIS_IMPLEMENT_VOID_FUNCTION16(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) \ + void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14, a15 n15, a16 n16) \ + { \ + static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16); \ + } + + +#define HYBRIS_IMPLEMENT_VOID_FUNCTION17(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) \ + void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14, a15 n15, a16 n16, a17 n17) \ + { \ + static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17); \ + } + + +#define HYBRIS_IMPLEMENT_VOID_FUNCTION18(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) \ + void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14, a15 n15, a16 n16, a17 n17, a18 n18) \ + { \ + static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18); \ + } + + +#define HYBRIS_IMPLEMENT_VOID_FUNCTION19(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) \ + void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14, a15 n15, a16 n16, a17 n17, a18 n18, a19 n19) \ + { \ + static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) FP_ATTRIB = NULL; \ + HYBRIS_DLSYSM(name, &f, #symbol); \ + f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18, n19); \ + } + + +/** + * XXX AUTO-GENERATED FILE XXX + * + * Do not edit this file directly, but update the templates in + * utils/generate_wrapper_macros.py and run it again to build + * an updated version of this header file: + * + * python utils/generate_wrapper_macros.py > \ + * hybris/include/hybris/common/binding.h + * + * If you need macros with more arguments, just customize the + * MAX_ARGS variable in generate_wrapper_macros.py. + * + * XXX AUTO-GENERATED FILE XXX + **/ + + +#endif /* HYBRIS_BINDING_H_ */ + diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/common/dlfcn.h libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/common/dlfcn.h --- libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/common/dlfcn.h 1970-01-01 00:00:00.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/common/dlfcn.h 2015-07-30 07:51:13.000000000 +0000 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2013 Intel Corporation + * + * 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 _HYBRIS_DLFCN_H_ +#define _HYBRIS_DLFCN_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void *hybris_dlopen(const char *filename, int flag); +void *hybris_dlsym(void *handle, const char *symbol); +int hybris_dlclose(void *handle); +char *hybris_dlerror(void); + +#ifdef __cplusplus +} +#endif + +#endif // _HYBRIS_DLFCN_H_ + +// vim: noai:ts=4:sw=4:ss=4:expandtab diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/common/floating_point_abi.h libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/common/floating_point_abi.h --- libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/common/floating_point_abi.h 1970-01-01 00:00:00.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/common/floating_point_abi.h 2015-07-30 07:51:13.000000000 +0000 @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2013 Jolla Ltd. + * Contact: Thomas Perl + * + * 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 HYBRIS_FLOATING_POINT_ABI_H_ +#define HYBRIS_FLOATING_POINT_ABI_H_ + +/** + * Make sure to use FP_ATTRIB on all functions that are loaded from + * Android (bionic libc) libraries to make sure floating point arguments + * are passed the right way. + * + * See: http://wiki.debian.org/ArmHardFloatPort/VfpComparison + * http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html + * + * It doesn't hurt to have it added for non-floating point arguments and + * return types, even though it does not really have any effect. + * + * If you use the convenience macros in hybris/common/binding.h, your + * wrapper functions will automatically make use of this attribute. + **/ + +#ifdef __ARM_PCS_VFP +# define FP_ATTRIB __attribute__((pcs("aapcs"))) +#else +# define FP_ATTRIB +#endif + +#endif /* HYBRIS_FLOATING_POINT_ABI_H_ */ diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/dlfcn/dlfcn.h libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/dlfcn/dlfcn.h --- libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/dlfcn/dlfcn.h 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/dlfcn/dlfcn.h 2015-07-30 07:51:13.000000000 +0000 @@ -15,22 +15,7 @@ * */ -#ifndef _HYBRIS_DLFCN_H_ -#define _HYBRIS_DLFCN_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -void *hybris_dlopen(const char *filename, int flag); -void *hybris_dlsym(void *handle, const char *symbol); -int hybris_dlclose(void *handle); -char *hybris_dlerror(void); - -#ifdef __cplusplus -} -#endif - -#endif // _HYBRIS_DLFCN_H_ +/* File was moved. Just providing it here for compatibility */ +#include // vim: noai:ts=4:sw=4:ss=4:expandtab diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/internal/binding.h libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/internal/binding.h --- libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/internal/binding.h 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/internal/binding.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,448 +0,0 @@ - -/** - * Copyright (C) 2013 Simon Busch - * 2012 Canonical Ltd - * 2013 Jolla Ltd. - * - * Auto-generated via "generate_wrapper_macros.py" - * - * 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 HYBRIS_BINDING_H_ -#define HYBRIS_BINDING_H_ - -/* floating_point_abi.h defines FP_ATTRIB */ -#include - -void *android_dlopen(const char *filename, int flag); -void *android_dlsym(void *name, const char *symbol); -int android_dlclose(void *handle); -const char *android_dlerror(void); -int android_dladdr(const void *addr, void *info); - - - -/** - * XXX AUTO-GENERATED FILE XXX - * - * Do not edit this file directly, but update the templates in - * utils/generate_wrapper_macros.py and run it again to build - * an updated version of this header file: - * - * python utils/generate_wrapper_macros.py > \ - * hybris/include/hybris/internal/binding.h - * - * If you need macros with more arguments, just customize the - * MAX_ARGS variable in generate_wrapper_macros.py. - * - * XXX AUTO-GENERATED FILE XXX - **/ - - -#define HYBRIS_DLSYSM(name, fptr, sym) \ - if (!name##_handle) \ - hybris_##name##_initialize(); \ - if (*(fptr) == NULL) \ - { \ - *(fptr) = (void *) android_dlsym(name##_handle, sym); \ - } - -#define HYBRIS_LIBRARY_INITIALIZE(name, path) \ - void *name##_handle; \ - void hybris_##name##_initialize() \ - { \ - name##_handle = android_dlopen(path, RTLD_LAZY); \ - } - - - -#define HYBRIS_IMPLEMENT_FUNCTION0(name, return_type, symbol) \ - return_type symbol() \ - { \ - static return_type (*f)() FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - return f(); \ - } - - -#define HYBRIS_IMPLEMENT_FUNCTION1(name, return_type, symbol, a1) \ - return_type symbol(a1 n1) \ - { \ - static return_type (*f)(a1) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - return f(n1); \ - } - - -#define HYBRIS_IMPLEMENT_FUNCTION2(name, return_type, symbol, a1, a2) \ - return_type symbol(a1 n1, a2 n2) \ - { \ - static return_type (*f)(a1, a2) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - return f(n1, n2); \ - } - - -#define HYBRIS_IMPLEMENT_FUNCTION3(name, return_type, symbol, a1, a2, a3) \ - return_type symbol(a1 n1, a2 n2, a3 n3) \ - { \ - static return_type (*f)(a1, a2, a3) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - return f(n1, n2, n3); \ - } - - -#define HYBRIS_IMPLEMENT_FUNCTION4(name, return_type, symbol, a1, a2, a3, a4) \ - return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4) \ - { \ - static return_type (*f)(a1, a2, a3, a4) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - return f(n1, n2, n3, n4); \ - } - - -#define HYBRIS_IMPLEMENT_FUNCTION5(name, return_type, symbol, a1, a2, a3, a4, a5) \ - return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5) \ - { \ - static return_type (*f)(a1, a2, a3, a4, a5) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - return f(n1, n2, n3, n4, n5); \ - } - - -#define HYBRIS_IMPLEMENT_FUNCTION6(name, return_type, symbol, a1, a2, a3, a4, a5, a6) \ - return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6) \ - { \ - static return_type (*f)(a1, a2, a3, a4, a5, a6) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - return f(n1, n2, n3, n4, n5, n6); \ - } - - -#define HYBRIS_IMPLEMENT_FUNCTION7(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7) \ - return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7) \ - { \ - static return_type (*f)(a1, a2, a3, a4, a5, a6, a7) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - return f(n1, n2, n3, n4, n5, n6, n7); \ - } - - -#define HYBRIS_IMPLEMENT_FUNCTION8(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8) \ - return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8) \ - { \ - static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - return f(n1, n2, n3, n4, n5, n6, n7, n8); \ - } - - -#define HYBRIS_IMPLEMENT_FUNCTION9(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9) \ - return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9) \ - { \ - static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - return f(n1, n2, n3, n4, n5, n6, n7, n8, n9); \ - } - - -#define HYBRIS_IMPLEMENT_FUNCTION10(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \ - return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10) \ - { \ - static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - return f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10); \ - } - - -#define HYBRIS_IMPLEMENT_FUNCTION11(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) \ - return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11) \ - { \ - static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - return f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11); \ - } - - -#define HYBRIS_IMPLEMENT_FUNCTION12(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) \ - return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12) \ - { \ - static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - return f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12); \ - } - - -#define HYBRIS_IMPLEMENT_FUNCTION13(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) \ - return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13) \ - { \ - static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - return f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13); \ - } - - -#define HYBRIS_IMPLEMENT_FUNCTION14(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) \ - return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14) \ - { \ - static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - return f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14); \ - } - - -#define HYBRIS_IMPLEMENT_FUNCTION15(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) \ - return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14, a15 n15) \ - { \ - static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - return f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15); \ - } - - -#define HYBRIS_IMPLEMENT_FUNCTION16(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) \ - return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14, a15 n15, a16 n16) \ - { \ - static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - return f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16); \ - } - - -#define HYBRIS_IMPLEMENT_FUNCTION17(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) \ - return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14, a15 n15, a16 n16, a17 n17) \ - { \ - static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - return f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17); \ - } - - -#define HYBRIS_IMPLEMENT_FUNCTION18(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) \ - return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14, a15 n15, a16 n16, a17 n17, a18 n18) \ - { \ - static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - return f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18); \ - } - - -#define HYBRIS_IMPLEMENT_FUNCTION19(name, return_type, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) \ - return_type symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14, a15 n15, a16 n16, a17 n17, a18 n18, a19 n19) \ - { \ - static return_type (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - return f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18, n19); \ - } - - -#define HYBRIS_IMPLEMENT_VOID_FUNCTION0(name, symbol) \ - void symbol() \ - { \ - static void (*f)() FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - f(); \ - } - - -#define HYBRIS_IMPLEMENT_VOID_FUNCTION1(name, symbol, a1) \ - void symbol(a1 n1) \ - { \ - static void (*f)(a1) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - f(n1); \ - } - - -#define HYBRIS_IMPLEMENT_VOID_FUNCTION2(name, symbol, a1, a2) \ - void symbol(a1 n1, a2 n2) \ - { \ - static void (*f)(a1, a2) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - f(n1, n2); \ - } - - -#define HYBRIS_IMPLEMENT_VOID_FUNCTION3(name, symbol, a1, a2, a3) \ - void symbol(a1 n1, a2 n2, a3 n3) \ - { \ - static void (*f)(a1, a2, a3) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - f(n1, n2, n3); \ - } - - -#define HYBRIS_IMPLEMENT_VOID_FUNCTION4(name, symbol, a1, a2, a3, a4) \ - void symbol(a1 n1, a2 n2, a3 n3, a4 n4) \ - { \ - static void (*f)(a1, a2, a3, a4) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - f(n1, n2, n3, n4); \ - } - - -#define HYBRIS_IMPLEMENT_VOID_FUNCTION5(name, symbol, a1, a2, a3, a4, a5) \ - void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5) \ - { \ - static void (*f)(a1, a2, a3, a4, a5) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - f(n1, n2, n3, n4, n5); \ - } - - -#define HYBRIS_IMPLEMENT_VOID_FUNCTION6(name, symbol, a1, a2, a3, a4, a5, a6) \ - void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6) \ - { \ - static void (*f)(a1, a2, a3, a4, a5, a6) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - f(n1, n2, n3, n4, n5, n6); \ - } - - -#define HYBRIS_IMPLEMENT_VOID_FUNCTION7(name, symbol, a1, a2, a3, a4, a5, a6, a7) \ - void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7) \ - { \ - static void (*f)(a1, a2, a3, a4, a5, a6, a7) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - f(n1, n2, n3, n4, n5, n6, n7); \ - } - - -#define HYBRIS_IMPLEMENT_VOID_FUNCTION8(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8) \ - void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8) \ - { \ - static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - f(n1, n2, n3, n4, n5, n6, n7, n8); \ - } - - -#define HYBRIS_IMPLEMENT_VOID_FUNCTION9(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9) \ - void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9) \ - { \ - static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - f(n1, n2, n3, n4, n5, n6, n7, n8, n9); \ - } - - -#define HYBRIS_IMPLEMENT_VOID_FUNCTION10(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) \ - void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10) \ - { \ - static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10); \ - } - - -#define HYBRIS_IMPLEMENT_VOID_FUNCTION11(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) \ - void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11) \ - { \ - static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11); \ - } - - -#define HYBRIS_IMPLEMENT_VOID_FUNCTION12(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) \ - void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12) \ - { \ - static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12); \ - } - - -#define HYBRIS_IMPLEMENT_VOID_FUNCTION13(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) \ - void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13) \ - { \ - static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13); \ - } - - -#define HYBRIS_IMPLEMENT_VOID_FUNCTION14(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) \ - void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14) \ - { \ - static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14); \ - } - - -#define HYBRIS_IMPLEMENT_VOID_FUNCTION15(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) \ - void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14, a15 n15) \ - { \ - static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15); \ - } - - -#define HYBRIS_IMPLEMENT_VOID_FUNCTION16(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) \ - void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14, a15 n15, a16 n16) \ - { \ - static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16); \ - } - - -#define HYBRIS_IMPLEMENT_VOID_FUNCTION17(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) \ - void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14, a15 n15, a16 n16, a17 n17) \ - { \ - static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17); \ - } - - -#define HYBRIS_IMPLEMENT_VOID_FUNCTION18(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) \ - void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14, a15 n15, a16 n16, a17 n17, a18 n18) \ - { \ - static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18); \ - } - - -#define HYBRIS_IMPLEMENT_VOID_FUNCTION19(name, symbol, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) \ - void symbol(a1 n1, a2 n2, a3 n3, a4 n4, a5 n5, a6 n6, a7 n7, a8 n8, a9 n9, a10 n10, a11 n11, a12 n12, a13 n13, a14 n14, a15 n15, a16 n16, a17 n17, a18 n18, a19 n19) \ - { \ - static void (*f)(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19) FP_ATTRIB = NULL; \ - HYBRIS_DLSYSM(name, &f, #symbol); \ - f(n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13, n14, n15, n16, n17, n18, n19); \ - } - - -/** - * XXX AUTO-GENERATED FILE XXX - * - * Do not edit this file directly, but update the templates in - * utils/generate_wrapper_macros.py and run it again to build - * an updated version of this header file: - * - * python utils/generate_wrapper_macros.py > \ - * hybris/include/hybris/internal/binding.h - * - * If you need macros with more arguments, just customize the - * MAX_ARGS variable in generate_wrapper_macros.py. - * - * XXX AUTO-GENERATED FILE XXX - **/ - - -#endif /* HYBRIS_BINDING_H_ */ - diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/internal/floating_point_abi.h libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/internal/floating_point_abi.h --- libhybris-0.1.0+git20131207+e452e83/hybris/include/hybris/internal/floating_point_abi.h 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/hybris/internal/floating_point_abi.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2013 Jolla Ltd. - * Contact: Thomas Perl - * - * 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 HYBRIS_FLOATING_POINT_ABI_H_ -#define HYBRIS_FLOATING_POINT_ABI_H_ - -/** - * Make sure to use FP_ATTRIB on all functions that are loaded from - * Android (bionic libc) libraries to make sure floating point arguments - * are passed the right way. - * - * See: http://wiki.debian.org/ArmHardFloatPort/VfpComparison - * http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html - * - * It doesn't hurt to have it added for non-floating point arguments and - * return types, even though it does not really have any effect. - * - * If you use the convenience macros in hybris/internal/binding.h, your - * wrapper functions will automatically make use of this attribute. - **/ - -#ifdef __ARM_PCS_VFP -# define FP_ATTRIB __attribute__((pcs("aapcs"))) -#else -# define FP_ATTRIB -#endif - -#endif /* HYBRIS_FLOATING_POINT_ABI_H_ */ diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/include/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/include/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/include/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/include/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -68,3 +68,9 @@ dlfcnincludedir = $(includedir)/hybris/dlfcn dlfcninclude_HEADERS = \ hybris/dlfcn/dlfcn.h + +commonincludedir = $(includedir)/hybris/common +commoninclude_HEADERS = \ + hybris/common/binding.h \ + hybris/common/floating_point_abi.h \ + hybris/common/dlfcn.h diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/input/is.c libhybris-0.1.0+git20151016+6d424c9/hybris/input/is.c --- libhybris-0.1.0+git20131207+e452e83/hybris/input/is.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/input/is.c 2015-07-30 07:51:13.000000000 +0000 @@ -21,7 +21,7 @@ #include #include -#include +#include #include #define COMPAT_LIBRARY_PATH "/system/lib/libis_compat_layer.so" diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/input/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/input/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/input/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/input/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -2,7 +2,7 @@ libis.la libis_la_SOURCES = is.c -libis_la_CFLAGS = -I$(top_srcdir)/include +libis_la_CFLAGS = -I$(top_srcdir)/include $(ANDROID_HEADERS_CFLAGS) if WANT_TRACE libis_la_CFLAGS += -DDEBUG endif diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/libnfc_ndef_nxp/libnfc_ndef_nxp.c libhybris-0.1.0+git20151016+6d424c9/hybris/libnfc_ndef_nxp/libnfc_ndef_nxp.c --- libhybris-0.1.0+git20131207+e452e83/hybris/libnfc_ndef_nxp/libnfc_ndef_nxp.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/libnfc_ndef_nxp/libnfc_ndef_nxp.c 2015-07-30 07:51:13.000000000 +0000 @@ -32,7 +32,7 @@ #include #include -#include +#include HYBRIS_LIBRARY_INITIALIZE(libnfc_ndef_so, "/system/lib/libnfc_ndef.so"); diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/libnfc_ndef_nxp/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/libnfc_ndef_nxp/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/libnfc_ndef_nxp/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/libnfc_ndef_nxp/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -2,7 +2,7 @@ libnfc_ndef_nxp.la libnfc_ndef_nxp_la_SOURCES = libnfc_ndef_nxp.c -libnfc_ndef_nxp_la_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/android -I$(top_srcdir)/include/android/libnfc-nxp +libnfc_ndef_nxp_la_CFLAGS = -I$(top_srcdir)/include $(ANDROID_HEADERS_CFLAGS) pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libnfc_ndef_nxp.pc diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/libnfc_nxp/libnfc_nxp.c libhybris-0.1.0+git20151016+6d424c9/hybris/libnfc_nxp/libnfc_nxp.c --- libhybris-0.1.0+git20131207+e452e83/hybris/libnfc_nxp/libnfc_nxp.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/libnfc_nxp/libnfc_nxp.c 2015-07-30 07:51:13.000000000 +0000 @@ -21,7 +21,7 @@ * https://github.com/thp/libhybris-nfc-wrapper-generator **/ -#include +#include #include #include @@ -54,7 +54,7 @@ #include #include -#include +#include HYBRIS_LIBRARY_INITIALIZE(libnfc_so, "/system/lib/libnfc.so"); @@ -459,7 +459,7 @@ HYBRIS_IMPLEMENT_FUNCTION3(libnfc_so, uint32_t, phFriNfc_Llcp_Buffer2Sequence, uint8_t *, uint32_t, phFriNfc_Llcp_sPacketSequence_t *); HYBRIS_IMPLEMENT_VOID_FUNCTION5(libnfc_so, Handle_ConnectionOriented_IncommingFrame, phFriNfc_LlcpTransport_t *, phNfc_sData_t *, uint8_t, uint8_t, uint8_t); HYBRIS_IMPLEMENT_VOID_FUNCTION4(libnfc_so, Handle_Connectionless_IncommingFrame, phFriNfc_LlcpTransport_t *, phNfc_sData_t *, uint8_t, uint8_t); -#if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=3 +#if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=3 || ANDROID_VERSION_MAJOR >= 5 /* see libnfc-nxp commit 7c4b4fad -- since Android 4.3 */ HYBRIS_IMPLEMENT_FUNCTION7(libnfc_so, NFCSTATUS, phFriNfc_LlcpTransport_LinkSend, phFriNfc_LlcpTransport_t *, phFriNfc_Llcp_sPacketHeader_t *, phFriNfc_Llcp_sPacketSequence_t *, phNfc_sData_t *, phFriNfc_Llcp_LinkSend_CB_t, uint8_t, void *); #else diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/libnfc_nxp/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/libnfc_nxp/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/libnfc_nxp/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/libnfc_nxp/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -2,7 +2,7 @@ libnfc_nxp.la libnfc_nxp_la_SOURCES = libnfc_nxp.c -libnfc_nxp_la_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/android -I$(top_srcdir)/include/android/libnfc-nxp +libnfc_nxp_la_CFLAGS = -I$(top_srcdir)/include $(ANDROID_HEADERS_CFLAGS) pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libnfc_nxp.pc diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/libsync/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/libsync/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/libsync/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/libsync/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -5,7 +5,7 @@ pkgconfig_DATA = libsync.pc libsync_la_SOURCES = sync.c -libsync_la_CFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/include/android +libsync_la_CFLAGS = -I$(top_srcdir)/include $(ANDROID_HEADERS_CFLAGS) if WANT_TRACE libsync_la_CFLAGS += -DDEBUG endif diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -3,8 +3,11 @@ if HAS_ANDROID_4_2_0 SUBDIRS += libsync endif +if HAS_ANDROID_5_0_0 +SUBDIRS += libsync +endif +SUBDIRS += egl glesv1 glesv2 ui sf input camera vibrator -SUBDIRS += egl glesv1 glesv2 ui sf input camera if HAS_LIBNFC_NXP_HEADERS SUBDIRS += libnfc_nxp libnfc_ndef_nxp endif diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/properties/cache.c libhybris-0.1.0+git20151016+6d424c9/hybris/properties/cache.c --- libhybris-0.1.0+git20131207+e452e83/hybris/properties/cache.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/properties/cache.c 2015-07-30 07:51:13.000000000 +0000 @@ -44,6 +44,7 @@ static int max_prop; /* helpers */ +static void cache_update(); static int prop_qcmp(const void *a, const void *b); static struct hybris_prop_value *cache_find_internal(const char *key); static void cache_add_internal(const char *key, const char *value); @@ -65,6 +66,37 @@ */ char *hybris_propcache_find(const char *key) { + char *ret = NULL; + + cache_update(); + + /* then look up the key and do a copy if we get a result */ + struct hybris_prop_value *prop = cache_find_internal(key); + if (prop) + return prop->value; + +out: + return ret; +} + +void hybris_propcache_list(hybris_propcache_list_cb cb, void *cookie) +{ + int n; + struct hybris_prop_value *current; + + if (!cb) + return; + + cache_update(); + + for (n = 0; n < max_prop; n++) { + current = &prop_array[n]; + cb(current->key, current->value, cookie); + } +} + +static void cache_update() +{ struct stat st; FILE *f = fopen("/system/build.prop", "r"); char *ret = NULL; @@ -98,14 +130,8 @@ qsort(prop_array, max_prop, sizeof(struct hybris_prop_value), prop_qcmp); } - /* then look up the key and do a copy if we get a result */ - struct hybris_prop_value *prop = cache_find_internal(key); - if (prop) - ret = strdup(prop->value); - out: fclose(f); - return ret; } /* private: diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/properties/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/properties/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/properties/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/properties/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -2,7 +2,7 @@ libandroid-properties.la libandroid_properties_la_SOURCES = properties.c cache.c -libandroid_properties_la_CFLAGS = -I$(top_srcdir)/include +libandroid_properties_la_CFLAGS = -I$(top_srcdir)/include $(ANDROID_HEADERS_CFLAGS) if WANT_DEBUG libandroid_properties_la_CFLAGS += -ggdb -O0 endif diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/properties/properties.c libhybris-0.1.0+git20151016+6d424c9/hybris/properties/properties.c --- libhybris-0.1.0+git20131207+e452e83/hybris/properties/properties.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/properties/properties.c 2015-07-30 07:51:13.000000000 +0000 @@ -118,8 +118,7 @@ return result; } -int property_list(void (*propfn)(const char *key, const char *value, void *cookie), - void *cookie) +int property_list(void (*propfn)(const char *key, const char *value, void *cookie), void *cookie) { int err; prop_msg_t msg; @@ -128,9 +127,9 @@ msg.cmd = PROP_MSG_LISTPROP; err = send_prop_msg(&msg, propfn, cookie); - if (err < 0) { - return err; - } + if (err < 0) + /* fallback to property cache */ + hybris_propcache_list((hybris_propcache_list_cb) propfn, cookie); return 0; } @@ -176,7 +175,6 @@ if (ret) { strcpy(value, ret); - free(ret); return strlen(value); } else if (default_value != NULL) { strcpy(value, default_value); diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/properties/properties_p.h libhybris-0.1.0+git20151016+6d424c9/hybris/properties/properties_p.h --- libhybris-0.1.0+git20131207+e452e83/hybris/properties/properties_p.h 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/properties/properties_p.h 2015-07-30 07:51:13.000000000 +0000 @@ -18,6 +18,9 @@ #ifndef HYBRIS_PROPERTIES #define HYBRIS_PROPERTIES +typedef void (*hybris_propcache_list_cb)(const char *key, const char *value, void *cookie); + +void hybris_propcache_list(hybris_propcache_list_cb cb, void *cookie); char *hybris_propcache_find(const char *key); #endif diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/sf/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/sf/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/sf/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/sf/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -2,7 +2,7 @@ libsf.la libsf_la_SOURCES = sf.c -libsf_la_CFLAGS = -I$(top_srcdir)/include +libsf_la_CFLAGS = -I$(top_srcdir)/include $(ANDROID_HEADERS_CFLAGS) if WANT_TRACE libsf_la_CFLAGS += -DDEBUG endif diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/sf/sf.c libhybris-0.1.0+git20151016+6d424c9/hybris/sf/sf.c --- libhybris-0.1.0+git20131207+e452e83/hybris/sf/sf.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/sf/sf.c 2015-07-30 07:51:13.000000000 +0000 @@ -21,7 +21,7 @@ #include #include -#include +#include #include #define COMPAT_LIBRARY_PATH "/system/lib/libsf_compat_layer.so" diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/tests/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/tests/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/tests/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/tests/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -7,12 +7,18 @@ test_sensors \ test_input \ test_camera \ + test_vibrator \ test_gps if HAS_ANDROID_4_2_0 bin_PROGRAMS += test_hwcomposer endif +if HAS_ANDROID_5_0_0 +bin_PROGRAMS += test_hwcomposer +endif + + if HAS_LIBNFC_NXP_HEADERS bin_PROGRAMS += test_nfc endif @@ -32,7 +38,7 @@ test_egl_SOURCES = test_egl.c test_egl_CFLAGS = \ -I$(top_srcdir)/include \ - -I$(top_srcdir)/include/android \ + $(ANDROID_HEADERS_CFLAGS) \ -I$(top_srcdir)/egl/platforms/common if WANT_MESA @@ -45,7 +51,7 @@ test_egl_configs_SOURCES = test_egl_configs.c test_egl_configs_CFLAGS = \ -I$(top_srcdir)/include \ - -I$(top_srcdir)/include/android + $(ANDROID_HEADERS_CFLAGS) test_egl_configs_LDADD = \ $(top_builddir)/common/libhybris-common.la \ $(top_builddir)/egl/libEGL.la @@ -53,7 +59,7 @@ test_glesv2_SOURCES = test_glesv2.c test_glesv2_CFLAGS = \ -I$(top_srcdir)/include \ - -I$(top_srcdir)/include/android + $(ANDROID_HEADERS_CFLAGS) if WANT_MESA test_glesv2_CFLAGS += -DLIBHYBRIS_WANTS_MESA_X11_HEADERS endif @@ -66,7 +72,7 @@ test_hwcomposer_SOURCES = test_hwcomposer.cpp test_hwcomposer_CXXFLAGS = \ -I$(top_srcdir)/include \ - -I$(top_srcdir)/include/android \ + $(ANDROID_HEADERS_CFLAGS) \ -I$(top_srcdir)/common \ -I$(top_srcdir)/egl/platforms/common \ -I$(top_srcdir)/egl/platforms/hwcomposer \ @@ -88,7 +94,7 @@ test_sensors_SOURCES = test_sensors.c test_sensors_CFLAGS = \ -I$(top_srcdir)/include \ - -I$(top_srcdir)/include/android + $(ANDROID_HEADERS_CFLAGS) test_sensors_LDADD = \ $(top_builddir)/common/libhybris-common.la \ $(top_builddir)/hardware/libhardware.la @@ -96,7 +102,7 @@ test_lights_SOURCES = test_lights.c test_lights_CFLAGS = \ -I$(top_srcdir)/include \ - -I$(top_srcdir)/include/android + $(ANDROID_HEADERS_CFLAGS) test_lights_LDADD = \ $(top_builddir)/common/libhybris-common.la \ @@ -105,7 +111,7 @@ test_ui_SOURCES = test_ui.c test_ui_CFLAGS = \ -I$(top_srcdir)/include \ - -I$(top_srcdir)/include/android + $(ANDROID_HEADERS_CFLAGS) test_ui_LDADD = \ $(top_builddir)/common/libhybris-common.la \ $(top_builddir)/ui/libui.la @@ -113,7 +119,7 @@ test_sf_SOURCES = test_sf.c test_sf_CFLAGS = \ -I$(top_srcdir)/include \ - -I$(top_srcdir)/include/android + $(ANDROID_HEADERS_CFLAGS) test_sf_LDADD = \ $(top_builddir)/common/libhybris-common.la \ $(top_builddir)/egl/libEGL.la \ @@ -123,15 +129,15 @@ test_input_SOURCES = test_input.c test_input_CFLAGS = \ -I$(top_srcdir)/include \ - -I$(top_srcdir)/include/android + $(ANDROID_HEADERS_CFLAGS) test_input_LDADD = \ $(top_builddir)/common/libhybris-common.la \ $(top_builddir)/input/libis.la test_camera_SOURCES = test_camera.c test_camera_CFLAGS = \ - -I$(top_srcdir)/include - -I$(top_srcdir)/include/android + -I$(top_srcdir)/include \ + $(ANDROID_HEADERS_CFLAGS) test_camera_LDADD = \ $(top_builddir)/common/libhybris-common.la \ @@ -143,12 +149,14 @@ test_gps_SOURCES = test_gps.c test_gps_CFLAGS = -pthread \ -I$(top_srcdir)/include \ - -I$(top_srcdir)/include/android + $(ANDROID_HEADERS_CFLAGS) if HAS_ANDROID_4_2_0 test_gps_CFLAGS += -DHAS_ANDROID_4_2_0 endif - +if HAS_ANDROID_5_0_0 +test_gps_CFLAGS += -DHAS_ANDROID_5_0_0 +endif test_gps_LDFLAGS = -pthread test_gps_LDADD = \ $(top_builddir)/common/libhybris-common.la \ @@ -157,10 +165,18 @@ test_nfc_SOURCES = test_nfc.c test_nfc_CFLAGS = \ -I$(top_srcdir)/include \ - -I$(top_srcdir)/include/android \ - -I$(top_srcdir)/include/android/libnfc-nxp + $(ANDROID_HEADERS_CFLAGS) test_nfc_LDFLAGS = test_nfc_LDADD = \ $(top_builddir)/libnfc_nxp/libnfc_nxp.la \ $(top_builddir)/hardware/libhardware.la + +test_vibrator_SOURCES = test_vibrator.c +test_vibrator_CFLAGS = \ + -I$(top_srcdir)/include \ + $(ANDROID_HEADERS_CFLAGS) +test_vibrator_LDADD = \ + $(top_builddir)/common/libhybris-common.la \ + $(top_builddir)/vibrator/libvibrator.la + diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_audio.c libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_audio.c --- libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_audio.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_audio.c 2015-07-30 07:51:13.000000000 +0000 @@ -15,14 +15,15 @@ * */ +#include #include #include #include #include #include -#include -#include +#include +#include int main(int argc, char **argv) { diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_camera.c libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_camera.c --- libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_camera.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_camera.c 2015-07-30 07:51:13.000000000 +0000 @@ -120,6 +120,8 @@ char fn[256]; sprintf(fn, "/tmp/shot_%d.jpeg", shot_counter); int fd = open(fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if(fd < 0) + return; ssize_t ret = write(fd, data, data_size); close(fd); shot_counter++; diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_egl.c libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_egl.c --- libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_egl.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_egl.c 2015-07-30 07:51:13.000000000 +0000 @@ -15,6 +15,7 @@ * */ +#include #include #include #include diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_glesv2.c libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_glesv2.c --- libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_glesv2.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_glesv2.c 2015-07-30 07:51:13.000000000 +0000 @@ -148,8 +148,17 @@ //glViewport ( 0 , 0 , 800, 600); // commented out so it uses the initial window dimensions glClearColor ( 1. , 1. , 1. , 1.); // background color float phase = 0; + int frames = -1; + if(argc == 2) { + frames = atoi(argv[1]); + } + if(frames < 0) { + frames = 30 * 60; + } + int i; - for (i=0; i<3*60; ++i) { + for (i = 0; i < frames; ++i) { + if(i % 60 == 0) printf("frame:%i\n", i); glClear(GL_COLOR_BUFFER_BIT); glUniform1f ( phase_loc , phase ); // write the value of phase to the shaders phase phase = fmodf ( phase + 0.5f , 2.f * 3.141f ); // and update the local variable diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_gps.c libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_gps.c --- libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_gps.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_gps.c 2015-07-30 07:51:13.000000000 +0000 @@ -16,6 +16,7 @@ * */ +#include #include #include #include @@ -25,7 +26,7 @@ #include #include -#include +#include const GpsInterface* Gps = NULL; const AGpsInterface* AGps = NULL; @@ -37,6 +38,7 @@ const UlpPhoneContextInterface *UlpPhoneContext = NULL; #endif /* HAVE_ULP */ char *apn = 0; +char *agps_server = 0; static const GpsInterface* get_gps_interface() { @@ -286,7 +288,7 @@ { case GPS_REQUEST_AGPS_DATA_CONN: fprintf(stdout, "*** data_conn_open\n"); -#ifndef HAS_ANDROID_4_2_0 +#if ! defined(HAS_ANDROID_4_2_0) && ! defined(HAS_ANDROID_5_0_0) AGps->data_conn_open(AGPS_TYPE_SUPL, apn, AGPS_APN_BEARER_IPV4); #else AGps->data_conn_open(apn); @@ -294,7 +296,7 @@ break; case GPS_RELEASE_AGPS_DATA_CONN: fprintf(stdout, "*** data_conn_closed\n"); -#ifndef HAS_ANDROID_4_2_0 +#if ! defined(HAS_ANDROID_4_2_0) && ! defined(HAS_ANDROID_5_0_0) AGps->data_conn_closed(AGPS_TYPE_SUPL); #else AGps->data_conn_closed(); @@ -412,7 +414,7 @@ fprintf(stdout, "*** cleanup\n"); if(AGps) { -#ifndef HAS_ANDROID_4_2_0 +#if ! defined(HAS_ANDROID_4_2_0) && ! defined(HAS_ANDROID_5_0_0) AGps->data_conn_closed(AGPS_TYPE_SUPL); #else AGps->data_conn_closed(); @@ -435,7 +437,7 @@ char *location = 0, *longitude, *latitude; float accuracy = 100; /* Use 100m as location accuracy by default */ - while ((opt = getopt(argc, argv, "acl:p:rtux")) != -1) + while ((opt = getopt(argc, argv, "acl:p:s:rtux")) != -1) { switch (opt) { case 'a': @@ -462,6 +464,9 @@ case 'p': apn = optarg; break; + case 's': + agps_server = optarg; + break; case 'u': ulp = 1; break; @@ -474,6 +479,7 @@ \t-a for agps,\n \ \t-c for coldstarting the gps,\n \ \t-p to specify an apn name,\n \ + \t-s to specify a different supls server.\n \ \t-r for agpsril,\n \ \t-t to inject time,\n \ \t-u to use ULP (if available,\n \ @@ -513,7 +519,19 @@ fprintf(stdout, "*** set up agps interface\n"); AGps->init(&callbacks2); fprintf(stdout, "*** set up agps server\n"); - AGps->set_server(AGPS_TYPE_SUPL, "supl.google.com", 7276); + if(agps_server) + { + char *server,*port = 0; + + server = strdup(agps_server); + strtok_r (server, ":", &port); + + fprintf(stdout, "SUPL server: %s at port number: %s\n", server, port); + AGps->set_server(AGPS_TYPE_SUPL, server, atoi(port)); + free(server); + } + else + AGps->set_server(AGPS_TYPE_SUPL, "supl.google.com", 7276); } if(agpsril) diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_hwcomposer.cpp libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_hwcomposer.cpp --- libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_hwcomposer.cpp 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_hwcomposer.cpp 2015-07-30 07:51:13.000000000 +0000 @@ -15,6 +15,7 @@ * */ +#include #include #include #include @@ -85,6 +86,49 @@ }; +class HWComposer : public HWComposerNativeWindow +{ + private: + hwc_layer_1_t *fblayer; + hwc_composer_device_1_t *hwcdevice; + hwc_display_contents_1_t **mlist; + protected: + void present(HWComposerNativeWindowBuffer *buffer); + + public: + + HWComposer(unsigned int width, unsigned int height, unsigned int format, hwc_composer_device_1_t *device, hwc_display_contents_1_t **mList, hwc_layer_1_t *layer); + void set(); +}; + +HWComposer::HWComposer(unsigned int width, unsigned int height, unsigned int format, hwc_composer_device_1_t *device, hwc_display_contents_1_t **mList, hwc_layer_1_t *layer) : HWComposerNativeWindow(width, height, format) +{ + fblayer = layer; + hwcdevice = device; + mlist = mList; +} + +void HWComposer::present(HWComposerNativeWindowBuffer *buffer) +{ + int oldretire = mlist[0]->retireFenceFd; + mlist[0]->retireFenceFd = -1; + fblayer->handle = buffer->handle; + fblayer->acquireFenceFd = getFenceBufferFd(buffer); + fblayer->releaseFenceFd = -1; + int err = hwcdevice->prepare(hwcdevice, HWC_NUM_DISPLAY_TYPES, mlist); + assert(err == 0); + + err = hwcdevice->set(hwcdevice, HWC_NUM_DISPLAY_TYPES, mlist); + assert(err == 0); + setFenceBufferFd(buffer, fblayer->releaseFenceFd); + + if (oldretire != -1) + { + sync_wait(oldretire, -1); + close(oldretire); + } +} + int main(int argc, char **argv) { EGLDisplay display; @@ -131,35 +175,6 @@ printf("width: %i height: %i\n", attr_values[0], attr_values[1]); - HWComposerNativeWindow *win = new HWComposerNativeWindow(attr_values[0], attr_values[1], HAL_PIXEL_FORMAT_RGBA_8888); - - - display = eglGetDisplay(NULL); - assert(eglGetError() == EGL_SUCCESS); - assert(display != EGL_NO_DISPLAY); - - rv = eglInitialize(display, 0, 0); - assert(eglGetError() == EGL_SUCCESS); - assert(rv == EGL_TRUE); - - eglChooseConfig((EGLDisplay) display, attr, &ecfg, 1, &num_config); - assert(eglGetError() == EGL_SUCCESS); - assert(rv == EGL_TRUE); - - surface = eglCreateWindowSurface((EGLDisplay) display, ecfg, (EGLNativeWindowType) static_cast (win), NULL); - assert(eglGetError() == EGL_SUCCESS); - assert(surface != EGL_NO_SURFACE); - - context = eglCreateContext((EGLDisplay) display, ecfg, EGL_NO_CONTEXT, ctxattr); - assert(eglGetError() == EGL_SUCCESS); - assert(context != EGL_NO_CONTEXT); - - assert(eglMakeCurrent((EGLDisplay) display, surface, surface, context) == EGL_TRUE); - - const char *version = (const char *)glGetString(GL_VERSION); - assert(version); - printf("%s\n",version); - size_t size = sizeof(hwc_display_contents_1_t) + 2 * sizeof(hwc_layer_1_t); hwc_display_contents_1_t *list = (hwc_display_contents_1_t *) malloc(size); hwc_display_contents_1_t **mList = (hwc_display_contents_1_t **) malloc(HWC_NUM_DISPLAY_TYPES * sizeof(hwc_display_contents_1_t *)); @@ -202,6 +217,37 @@ list->flags = HWC_GEOMETRY_CHANGED; list->numHwLayers = 2; + + HWComposer *win = new HWComposer(attr_values[0], attr_values[1], HAL_PIXEL_FORMAT_RGBA_8888, hwcDevicePtr, mList, &list->hwLayers[1]); + + display = eglGetDisplay(NULL); + assert(eglGetError() == EGL_SUCCESS); + assert(display != EGL_NO_DISPLAY); + + rv = eglInitialize(display, 0, 0); + assert(eglGetError() == EGL_SUCCESS); + assert(rv == EGL_TRUE); + + eglChooseConfig((EGLDisplay) display, attr, &ecfg, 1, &num_config); + assert(eglGetError() == EGL_SUCCESS); + assert(rv == EGL_TRUE); + + + + surface = eglCreateWindowSurface((EGLDisplay) display, ecfg, (EGLNativeWindowType) static_cast (win), NULL); + assert(eglGetError() == EGL_SUCCESS); + assert(surface != EGL_NO_SURFACE); + + context = eglCreateContext((EGLDisplay) display, ecfg, EGL_NO_CONTEXT, ctxattr); + assert(eglGetError() == EGL_SUCCESS); + assert(context != EGL_NO_CONTEXT); + + assert(eglMakeCurrent((EGLDisplay) display, surface, surface, context) == EGL_TRUE); + + const char *version = (const char *)glGetString(GL_VERSION); + assert(version); + printf("%s\n",version); + GLuint vertexShader = load_shader ( vertex_src , GL_VERTEX_SHADER ); // load vertex shader GLuint fragmentShader = load_shader ( fragment_src , GL_FRAGMENT_SHADER ); // load fragment shader @@ -236,43 +282,6 @@ glDrawArrays ( GL_TRIANGLE_STRIP, 0, 5 ); eglSwapBuffers ( (EGLDisplay) display, surface ); // get the rendered buffer to the screen - - HWComposerNativeWindowBuffer *front; - win->lockFrontBuffer(&front); - - mList[0]->hwLayers[1].handle = front->handle; - mList[0]->hwLayers[0].handle = NULL; - mList[0]->hwLayers[0].flags = HWC_SKIP_LAYER; - - oldretire = mList[0]->retireFenceFd; - oldrelease = mList[0]->hwLayers[1].releaseFenceFd; - oldrelease2 = mList[0]->hwLayers[0].releaseFenceFd; - - int err = hwcDevicePtr->prepare(hwcDevicePtr, HWC_NUM_DISPLAY_TYPES, mList); - assert(err == 0); - - err = hwcDevicePtr->set(hwcDevicePtr, HWC_NUM_DISPLAY_TYPES, mList); - assert(err == 0); - - assert(mList[0]->hwLayers[0].releaseFenceFd == -1); - - win->unlockFrontBuffer(front); - - if (oldrelease != -1) - { - sync_wait(oldrelease, -1); - close(oldrelease); - } - if (oldrelease2 != -1) - { - sync_wait(oldrelease2, -1); - close(oldrelease2); - } - if (oldretire != -1) - { - sync_wait(oldretire, -1); - close(oldretire); - } } printf("stop\n"); diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_input.c libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_input.c --- libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_input.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_input.c 2015-07-30 07:51:13.000000000 +0000 @@ -17,6 +17,7 @@ * Ricardo Salveti de Araujo */ +#include #include #include #include diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_lights.c libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_lights.c --- libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_lights.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_lights.c 2015-07-30 07:51:13.000000000 +0000 @@ -15,10 +15,11 @@ * */ +#include #include #include #include -#include +#include int main(int argc, char **argv) { diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_nfc.c libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_nfc.c --- libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_nfc.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_nfc.c 2015-07-30 07:51:13.000000000 +0000 @@ -16,6 +16,7 @@ * */ +#include #include #include #include diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_sensors.c libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_sensors.c --- libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_sensors.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_sensors.c 2015-07-30 07:51:13.000000000 +0000 @@ -15,10 +15,54 @@ * */ +#include #include #include #include -#include +#include + +static void process_event(sensors_event_t *data) +{ + switch (data->type) { + case SENSOR_TYPE_ACCELEROMETER: + printf("Accelerometer: %+08.2f, %+08.2f, %+08.2f", data->acceleration.x, + data->acceleration.y, data->acceleration.z); + break; + case SENSOR_TYPE_ORIENTATION: + printf("Orientation: %+08.2f, %+08.2f, %+08.2f", data->orientation.x, + data->orientation.y, data->orientation.z); + break; + case SENSOR_TYPE_GYROSCOPE: + printf("Gyroscope: %+08.2f, %+08.2f, %+08.2f", data->gyro.x, + data->gyro.y, data->gyro.z); + break; + case SENSOR_TYPE_LIGHT: + printf("Light: %+08.2f", data->light); + break; + case SENSOR_TYPE_PROXIMITY: + printf("Proximity: %+08.2f", data->distance); + break; + default: + printf("Other sensor data (not parsed yet, type=%d)", data->type); + } +} + +static void print_sensor_info(int i, struct sensor_t const *s) +{ + printf("=== Sensor %d ==\n", i); + printf("Name: %s\n", s->name); + printf("Vendor: %s\n", s->vendor); + printf("Version: 0x%x\n", s->version); + printf("Handle: 0x%x\n", s->handle); + printf("Type: %d\n", s->type); + printf("maxRange: %.f\n", s->maxRange); + printf("resolution: %.f\n", s->resolution); + printf("power: %.f mA\n", s->power); + printf("minDelay: %d\n", s->minDelay); + //printf("fifoReservedEventCount: %d\n", s->fifoReservedEventCount); + //printf("fifoMaxEventCount: %d\n", s->fifoMaxEventCount); + printf("\n\n\n"); +} int main(int argc, char **argv) { @@ -33,6 +77,71 @@ exit(1); } + printf("Hardware module ID: %s\n", hwmod->id); + printf("Hardware module Name: %s\n", hwmod->name); + printf("Hardware module Author: %s\n", hwmod->author); + printf("Hardware module API version: 0x%x\n", hwmod->module_api_version); + printf("Hardware HAL API version: 0x%x\n", hwmod->hal_api_version); + printf("Poll device version: 0x%x\n", dev->common.version); + + printf("API VERSION 0.1 (legacy): 0x%x\n", HARDWARE_MODULE_API_VERSION(0, 1)); +#ifdef SENSORS_DEVICE_API_VERSION_0_1 + printf("API VERSION 0.1: 0x%d\n", SENSORS_DEVICE_API_VERSION_0_1); +#endif +#ifdef SENSORS_DEVICE_API_VERSION_1_0 + printf("API VERSION 1.0: 0x%d\n", SENSORS_DEVICE_API_VERSION_1_0); +#endif +#ifdef SENSORS_DEVICE_API_VERSION_1_1 + printf("API VERSION 1.1: 0x%d\n", SENSORS_DEVICE_API_VERSION_1_1); +#endif + + struct sensors_module_t *smod = (struct sensors_module_t *)(hwmod); + + struct sensor_t const *sensors_list = NULL; + int sensors = smod->get_sensors_list(smod, &sensors_list); + printf("Got %d sensors\n", sensors); + + int res; + int poll_sensor = ((argc == 2) ? atoi(argv[1]) : -1); + + if (poll_sensor != -1 && poll_sensor < sensors) { + struct sensor_t const *s = sensors_list + poll_sensor; + print_sensor_info(poll_sensor, s); + + res = dev->setDelay(dev, s->handle, s->minDelay); + if (res != 0) { + printf("Could not set delay: %s\n", strerror(-res)); + } + res = dev->activate(dev, s->handle, 1); + if (res != 0) { + printf("Could not activate sensor: %s\n", strerror(-res)); + } else { + printf("Reading events\n"); + while (1) { + sensors_event_t data; + data.sensor = -1; + printf("\rPolling... "); + fflush(stdout); + while (dev->poll(dev, &data, 1) != 1); + printf(" "); + if (data.sensor == poll_sensor) { + process_event(&data); + } + printf("\33[K"); + fflush(stdout); + } + res = dev->activate(dev, s->handle, 0); + if (res != 0) { + printf("Could not deactivate sensor: %s\n", strerror(-res)); + } + } + } else { + int i; + for (i=0; i */ +#include #include #include #include diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_ui.c libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_ui.c --- libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_ui.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_ui.c 2015-07-30 07:51:13.000000000 +0000 @@ -14,11 +14,12 @@ * limitations under the License. */ +#include #include #include -#include -#include +#include +#include int main(int argc, char **argv) { diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_vibrator.c libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_vibrator.c --- libhybris-0.1.0+git20131207+e452e83/hybris/tests/test_vibrator.c 1970-01-01 00:00:00.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/tests/test_vibrator.c 2015-07-30 07:51:13.000000000 +0000 @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2014 Jolla Ltd. + * Contact: Simonas Leleiva + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + // Android mistakenly reports that vibrator does not exist: + //assert(vibrator_exists() != 0); + + if (vibrator_on(1000) < 0) { + printf("ERROR: vibrator failed to vibrate\n"); + exit(1); + } + + return 0; +} + +// vim:ts=4:sw=4:noexpandtab diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/ui/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/ui/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/ui/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/ui/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -2,7 +2,7 @@ libui.la libui_la_SOURCES = ui.c -libui_la_CFLAGS = -I$(top_srcdir)/include +libui_la_CFLAGS = -I$(top_srcdir)/include $(ANDROID_HEADERS_CFLAGS) if WANT_TRACE libui_la_CFLAGS += -DDEBUG endif diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/ui/ui.c libhybris-0.1.0+git20151016+6d424c9/hybris/ui/ui.c --- libhybris-0.1.0+git20131207+e452e83/hybris/ui/ui.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/ui/ui.c 2015-07-30 07:51:13.000000000 +0000 @@ -17,7 +17,7 @@ #include #include -#include +#include #include #define COMPAT_LIBRARY_PATH "/system/lib/libui_compat_layer.so" diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/utils/getprop.c libhybris-0.1.0+git20151016+6d424c9/hybris/utils/getprop.c --- libhybris-0.1.0+git20131207+e452e83/hybris/utils/getprop.c 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/utils/getprop.c 2015-07-30 07:51:13.000000000 +0000 @@ -33,7 +33,7 @@ char temp[PROP_VALUE_MAX + PROP_NAME_MAX + 16]; snprintf(temp, sizeof(temp), "[%s]: [%s]", key, name); - list->items = realloc(list->items, (list->count + 1) * sizeof(char **)); + list->items = realloc(list->items, (list->count + 1) * sizeof(char *)); list->items[list->count++] = strdup(temp); } diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/utils/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/utils/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/utils/Makefile.am 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/utils/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -4,7 +4,7 @@ getprop_SOURCES = getprop.c getprop_CFLAGS = \ - -I$(top_srcdir)/include + -I$(top_srcdir)/include $(ANDROID_HEADERS_CFLAGS) getprop_LDADD = \ $(top_builddir)/properties/libandroid-properties.la diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/vibrator/libvibrator.pc.in libhybris-0.1.0+git20151016+6d424c9/hybris/vibrator/libvibrator.pc.in --- libhybris-0.1.0+git20131207+e452e83/hybris/vibrator/libvibrator.pc.in 1970-01-01 00:00:00.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/vibrator/libvibrator.pc.in 2015-07-30 07:51:13.000000000 +0000 @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=${prefix} +libdir=@libdir@ +includedir=@includedir@ + +Name: hybris-vibrator +Description: libhybris vibrator library +Version: @VERSION@ +Libs: -L${libdir} -lhybris-common -lvibrator +Cflags: -I${includedir} diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/vibrator/Makefile.am libhybris-0.1.0+git20151016+6d424c9/hybris/vibrator/Makefile.am --- libhybris-0.1.0+git20131207+e452e83/hybris/vibrator/Makefile.am 1970-01-01 00:00:00.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/vibrator/Makefile.am 2015-07-30 07:51:13.000000000 +0000 @@ -0,0 +1,17 @@ +lib_LTLIBRARIES = \ + libvibrator.la + +libvibrator_la_SOURCES = vibrator.c +libvibrator_la_CFLAGS = -I$(top_srcdir)/include $(ANDROID_HEADERS_CFLAGS) +if WANT_TRACE +libvibrator_la_CFLAGS += -DDEBUG +endif +if WANT_DEBUG +libvibrator_la_CFLAGS += -ggdb -O0 +endif +libvibrator_la_LDFLAGS = \ + $(top_builddir)/common/libhybris-common.la \ + -version-info "1":"0":"0" + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libvibrator.pc diff -Nru libhybris-0.1.0+git20131207+e452e83/hybris/vibrator/vibrator.c libhybris-0.1.0+git20151016+6d424c9/hybris/vibrator/vibrator.c --- libhybris-0.1.0+git20131207+e452e83/hybris/vibrator/vibrator.c 1970-01-01 00:00:00.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/hybris/vibrator/vibrator.c 2015-07-30 07:51:13.000000000 +0000 @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2014 Jolla Ltd. + * Contact: Simonas Leleiva + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include +#include +#include + +#include + +HYBRIS_LIBRARY_INITIALIZE(vibrator, "/system/lib/libhardware_legacy.so"); + +HYBRIS_IMPLEMENT_FUNCTION0(vibrator, int, vibrator_exists); +HYBRIS_IMPLEMENT_FUNCTION1(vibrator, int, vibrator_on, int); +HYBRIS_IMPLEMENT_FUNCTION1(vibrator, int, vibrator_off, int); diff -Nru libhybris-0.1.0+git20131207+e452e83/utils/extract-headers.sh libhybris-0.1.0+git20151016+6d424c9/utils/extract-headers.sh --- libhybris-0.1.0+git20131207+e452e83/utils/extract-headers.sh 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/utils/extract-headers.sh 2015-07-30 07:51:13.000000000 +0000 @@ -9,8 +9,22 @@ PATCH2=$6 PATCH3=$7 +usage() { + echo "Usage: extract-headers.sh [Android Platform Version]" + echo + echo " ANDROID_ROOT: Directory containing the Android source tree." + echo " HEADER_PATH: Where the headers will be extracted to." + echo + echo "Android Platform Version:" + echo " This field is optional. If not specified, automatic extraction is attempted." + echo + echo "Ex:" + echo " ./extract-headers.sh android-aosp/ /tmp/android-headers/ 4 2 2" + +} + if [ x$ANDROID_ROOT = x -o "x$HEADERPATH" = x ]; then - echo "Syntax: extract-headers.sh ANDROID_ROOT HEADERPATH [MAJOR] [MINOR] [PATCH] [PATCH2] [PATCH3]" + usage exit 1 fi @@ -28,29 +42,15 @@ parse_defaults_failed fi - PLATFORM_VERSION=$(egrep -o "PLATFORM_VERSION := [0-9.]+" $VERSION_DEFAULTS | awk '{ print $3 }') - if [ x$PLATFORM_VERSION = x ]; then - parse_defaults_failed - fi - - MAJOR=$(echo $PLATFORM_VERSION | cut -d. -f1) - MINOR=$(echo $PLATFORM_VERSION | cut -d. -f2) - PATCH=$(echo $PLATFORM_VERSION | cut -d. -f3) - PATCH2=$(echo $PLATFORM_VERSION | cut -d. -f4) - PATCH3=$(echo $PLATFORM_VERSION | cut -d. -f5) + IFS="." read MAJOR MINOR PATCH PATCH2 PATCH3 < - HEADER_FILE=$ANDROID_ROOT/$1 - if [ ! -e "$HEADER_FILE" ]; then - return 1 - fi - - return 0 -} - # Make sure that the dir given contains at least some of the assumed structures. require_sources \ @@ -110,13 +101,9 @@ mkdir -p $HEADERPATH -if [ x$PATCH2 = x ]; then - PATCH2=0 -fi - -if [ x$PATCH3 = x ]; then - PATCH3=0 -fi +# Default PATCH2,3 to 0 +PATCH2=${PATCH2:-0} +PATCH3=${PATCH3:-0} cat > $HEADERPATH/android-version.h << EOF #ifndef ANDROID_VERSION_H_ @@ -131,38 +118,82 @@ #endif EOF +cat > $HEADERPATH/android-config.h << EOF +#ifndef HYBRIS_CONFIG_H_ +#define HYBRIS_CONFIG_H_ + +/* When android is built for a specific device the build is + modified by BoardConfig.mk and possibly other mechanisms. + eg + device/samsung/i9305/BoardConfig.mk: + COMMON_GLOBAL_CFLAGS += -DCAMERA_WITH_CITYID_PARAM + device/samsung/smdk4412-common/BoardCommonConfig.mk: + COMMON_GLOBAL_CFLAGS += -DEXYNOS4_ENHANCEMENTS + + This file allows those global configurations, which are not + otherwise defined in the build headers, to be available in + hybris builds. + + Typically it is generated at hardware adaptation time. + + The CONFIG GOES HERE line can be used by automation to modify + this file. +*/ + +#include + +/* CONFIG GOES HERE */ + +#endif +EOF + +cat <<< 'Name: Android header files +Description: Header files needed to write applications for the Android platform +Version: androidversion + +prefix=/usr +exec_prefix=${prefix} +includedir=${prefix}/include + +Cflags: -I${includedir}/android' > $HEADERPATH/android-headers.pc +sed -i -e s:androidversion:$MAJOR.$MINOR.$PATCH:g $HEADERPATH/android-headers.pc + extract_headers_to hardware \ hardware/libhardware/include/hardware extract_headers_to hardware_legacy \ + hardware/libhardware_legacy/include/hardware_legacy/vibrator.h \ hardware/libhardware_legacy/include/hardware_legacy/audio_policy_conf.h extract_headers_to cutils \ system/core/include/cutils +extract_headers_to log \ + system/core/include/log + extract_headers_to system \ system/core/include/system extract_headers_to android \ system/core/include/android -check_header_exists external/kernel-headers/original/linux/sync.h && \ - extract_headers_to linux \ - external/kernel-headers/original/linux/sync.h \ - external/kernel-headers/original/linux/sw_sync.h - -check_header_exists system/core/include/sync/sync.h && \ - extract_headers_to sync \ - system/core/include/sync - -check_header_exists external/libnfc-nxp/inc/phNfcConfig.h && \ - extract_headers_to libnfc-nxp \ - external/libnfc-nxp/inc \ - external/libnfc-nxp/src +extract_headers_to linux \ + bionic/libc/kernel/common/linux/sync.h \ + bionic/libc/kernel/common/linux/sw_sync.h + +extract_headers_to sync \ + system/core/include/sync + +extract_headers_to libnfc-nxp \ + external/libnfc-nxp/inc \ + external/libnfc-nxp/src extract_headers_to private \ system/core/include/private/android_filesystem_config.h +extract_headers_to linux \ + external/kernel-headers/original/linux/android_alarm.h \ + external/kernel-headers/original/linux/binder.h # In order to make it easier to trace back the origins of headers, fetch # some repository information from the Git source tree (if available). @@ -174,8 +205,8 @@ hardware/libhardware hardware/libhardware_legacy system/core - external/kernel-headers external/libnfc-nxp + external/linux-headers " echo "Extracting Git revision information" @@ -206,4 +237,29 @@ cp $ANDROID_ROOT/.repo/manifest.xml $HEADERPATH/ fi +# Add a makefile to make packaging easier +cat > ${HEADERPATH}/Makefile << EOF +PREFIX?=/usr/local +INCLUDEDIR?=\$(PREFIX)/include/android +all: + @echo "Use '\$(MAKE) install' to install" + +install: + mkdir -p \$(DESTDIR)/\$(INCLUDEDIR) + cp android-config.h android-version.h android-headers.pc \$(DESTDIR)/\$(INCLUDEDIR) + sed -i -e s:prefix=/usr:prefix=\$(PREFIX):g \$(DESTDIR)/\$(INCLUDEDIR)/android-headers.pc + cp -r hardware \$(DESTDIR)/\$(INCLUDEDIR) + cp -r hardware_legacy \$(DESTDIR)/\$(INCLUDEDIR) + cp -r cutils \$(DESTDIR)/\$(INCLUDEDIR) + cp -r system \$(DESTDIR)/\$(INCLUDEDIR) + cp -r android \$(DESTDIR)/\$(INCLUDEDIR) + cp -r linux \$(DESTDIR)/\$(INCLUDEDIR) + cp -r sync \$(DESTDIR)/\$(INCLUDEDIR) + cp -r libnfc-nxp \$(DESTDIR)/\$(INCLUDEDIR) + cp -r private \$(DESTDIR)/\$(INCLUDEDIR) +EOF + +find "$HEADERPATH" -type f -exec chmod 0644 {} \; + exit 0 +# vim: noai:ts=4:sw=4:ss=4:expandtab diff -Nru libhybris-0.1.0+git20131207+e452e83/utils/generate_wrapper_macros.py libhybris-0.1.0+git20151016+6d424c9/utils/generate_wrapper_macros.py --- libhybris-0.1.0+git20131207+e452e83/utils/generate_wrapper_macros.py 2013-12-07 15:35:26.000000000 +0000 +++ libhybris-0.1.0+git20151016+6d424c9/utils/generate_wrapper_macros.py 2015-07-30 07:51:13.000000000 +0000 @@ -77,7 +77,7 @@ #define HYBRIS_BINDING_H_ /* floating_point_abi.h defines FP_ATTRIB */ -#include +#include void *android_dlopen(const char *filename, int flag); void *android_dlsym(void *name, const char *symbol);