Showing posts with label NDK. Show all posts
Showing posts with label NDK. Show all posts

Wednesday, October 19, 2016

Improving Stability with Private C/C++ Symbol Restrictions in Android N


Posted by Dimitry Ivanov & Elliott Hughes, Software Engineers



As documented in the href="https://developer.android.com/preview/behavior-changes.html#ndk">Android N
behavioral changes
, to protect Android users and apps from unforeseen
crashes, Android N will restrict which libraries your C/C++ code can link
against at runtime
. As a result, if your app uses any private symbols from
platform libraries, you will need to update it to either use the public NDK APIs
or to include its own copy of those libraries. Some libraries are public: the
NDK exposes libandroid, libc, libcamera2ndk, libdl,
libGLES, libjnigraphics, liblog, libm, libmediandk, libOpenMAXAL, libOpenSLES,
libstdc++, libvulkan, and libz as part of the NDK API. Other libraries are
private, and Android N only allows access to them for platform HALs, system
daemons, and the like. If you aren’t sure whether your app uses private
libraries, you can immediately check it for warnings on the N Developer Preview.


We’re making this change because it’s painful for users when their apps stop
working after a platform update. Whether they blame the app developer or the
platform, everybody loses. Users should have a consistent app experience across
updates, and developers shouldn’t have to make emergency app updates to handle
platform changes. For that reason, we recommend against using private C/C++
symbols. Private symbols aren’t tested as part of the Compatibility Test Suite
(CTS) that all Android devices must pass. They may not exist, or they may behave
differently. This makes apps that use them more likely to fail on specific
devices, or on future releases — as many developers found when Android 6.0
Marshmallow switched from OpenSSL to BoringSSL.


You may be surprised that there’s no STL in the list of NDK libraries. The three
STL implementations included in the NDK — the LLVM libc++, the GNU STL, and
libstlport — are intended to be bundled with your app, either by statically
linking into your library, or by inclusion as a separate shared library. In the
past, some developers have assumed that they didn’t need to package the library
because the OS itself had a copy. This assumption is incorrect: a particular STL
implementation may disappear (as was the case with stlport, which was removed in
Marshmallow), may never have been available (as is the case with the GNU STL),
or it may change in ABI incompatible ways (as is the case with the LLVM libc++).


In order to reduce the user impact of this transition, we’ve identified a set of
libraries that see significant use from Google Play’s most-installed apps, and
that are feasible for us to support in the short term (including
libandroid_runtime.so, libcutils.so, libcrypto.so, and libssl.so). For legacy
code in N, we will temporarily support these libraries in order to give you more
time to transition. Note that we don't intend to continue this support in any
future Android platform release, so if you see a warning that means your code
will not work in a future release — please fix it now!



Table 1. What to expect if your app is linking against private native libraries.

LibrariesApp's targetSdkVersionRuntime access via dynamic linkerImpact, N Developer PreviewImpact, Final N ReleaseImpact, future platform version
NDK PublicAnyAccessible
Private (graylist)<=23Temporarily accessibleWarning / ToastWarningError
>=24RestrictedErrorErrorError
Private (all other)>AnyRestrictedErrorErrorError



What behavior will I see?



Please test your app during the N Previews.


N Preview behavior



  • All public NDK libraries (libandroid, libc, libcamera2ndk, libdl, libGLES,
    libjnigraphics, liblog, libm, libmediandk, libOpenMAXAL, libOpenSLES, libstdc++,
    libvulkan, and libz), plus libraries that are part of your app are accessible.
  • For all other libraries you’ll see a warning in logcat and a toast on the
    display. This will happen only if your app’s targetSdkVersion is less than N. If
    you change your manifest to target N, loading will fail: Java’s
    System.loadLibrary will throw, and C/C++’s dlopen(3) will return NULL.




Test your apps on the Developer Preview — if you see a toast like this one, your app is accessing private native APIs. Please fix your code soon!



N Final Release behavior



  • All NDK libraries (libandroid, libc, libcamera2ndk, libdl, libGLES,
    libjnigraphics, liblog, libm, libmediandk, libOpenMAXAL, libOpenSLES, libstdc++,
    libvulkan, and libz), plus libraries that are part of your app are accessible.
  • For the temporarily accessible libraries (such as libandroid_runtime.so,
    libcutils.so, libcrypto.so, and libssl.so), you’ll see a warning in logcat for
    all API levels before N, but loading will fail if you update your app so that
    its targetSdkVersion is N or later.
  • Attempts to load any other libraries will fail in the final release of
    Android N, even if your app is targeting a pre-N platform version.



Future platform behavior



  • In O, all access to the temporarily accessible libraries will be removed.
    As a result, you should plan to update your app regardless of your
    targetSdkVersion prior to O. If you believe there is missing functionality from
    the NDK API that will make it impossible for you to transition off a temporarily
    accessible library, please file a bug here.



What do the errors look like?



Here’s some example logcat output from an app that hasn’t bumped its target SDK
version (and so the restriction isn’t fully enforced because this is only the
developer preview):




03-21 17:07:51.502 31234 31234 W linker  : library "libandroid_runtime.so"
("/system/lib/libandroid_runtime.so") needed or dlopened by
"/data/app/com.popular-app.android-2/lib/arm/libapplib.so" is not accessible
for the namespace "classloader-namespace" - the access is temporarily granted
as a workaround for http://b/26394120


This is telling you that your library “libapplib.so” refers to the library
“libandroid_runtime.so”, which is a private library.


When Android N ships, or if you set your target SDK version to N now, you’ll see
something like this if you try to use System.loadLibrary from Java:

java.lang.UnsatisfiedLinkError: dlopen failed: library "libcutils.so"
("/system/lib/libcutils.so") needed or dlopened by "/system/lib/libnativeloader.so"
is not accessible for the namespace "classloader-namespace"
  at java.lang.Runtime.loadLibrary0(Runtime.java:977)
  at java.lang.System.loadLibrary(System.java:1602)


If you’re using href="http://man7.org/linux/man-pages/man3/dlopen.3.html">dlopen(3) from
C/C++ you’ll get a NULL return and href="http://man7.org/linux/man-pages/man3/dlerror.3.html">dlerror(3) will
return the same “dlopen failed...” string as shown above.


For more information about how to check if your app is using private symbols,
see the FAQ on developer.android.com.

Tuesday, June 28, 2016

Android changes for NDK developers

Android changes for NDK developers

Posted by Dmitry Malykhanov, Developer Advocate




Related to other improvements to the Android platform, the dynamic linker in
Android M and N has stricter requirements for writing clean, cross-platform
compatible native code in order to load. It is necessary that an application’s
native code follows the rules and recommendations in order to ensure a smooth
transition to recent Android releases.



Below we outline in detail each individual change related to native code
loading, the consequences and steps you can take to avoid issues.



Required tools: there is an <arch>-linux-android-readelf binary (e.g.
arm-linux-androideabi-readelf or i686-linux-android-readelf) for each
architecture in the NDK (under toolchains/), but you can use readelf for any
architecture, as we will be doing basic inspection only. On Linux you need to
have the “binutils” package installed for readelf, and “pax-utils” for scanelf.


Private API (Enforced since API 24)



Native libraries must use only href="http://developer.android.com/ndk/guides/stable_apis.html?utm_campaign=android_discussion_ndkchanges_062716&utm_source=anddev&utm_medium=blog">public API,
and must not link against non-NDK platform libraries. Starting with API 24 this
rule is enforced and applications are no longer able to load non-NDK platform
libraries. The rule is enforced by the dynamic linker, so non-public libraries
are not accessible regardless of the way code tries to load them:
System.loadLibrary(...), DT_NEEDED entries, and direct calls to dlopen(...) will
fail in exactly the same way.



Users should have a consistent app experience across updates, and developers
shouldn’t have to make emergency app updates to handle platform changes. For
that reason, we recommend against using private C/C++ symbols. Private symbols
aren’t tested as part of the Compatibility Test Suite (CTS) that all Android
devices must pass. They may not exist, or they may behave differently. This
makes apps that use them more likely to fail on specific devices, or on future
releases --- as many developers found when Android 6.0 Marshmallow switched from
OpenSSL to BoringSSL.



In order to reduce the user impact of this transition, we’ve identified a set of
libraries that see significant use from Google Play’s most-installed apps, and
that are feasible for us to support in the short term (including
libandroid_runtime.so, libcutils.so, libcrypto.so, and libssl.so). In order to
give you more time to transition, we will temporarily support these libraries;
so if you see a warning that means your code will not work in a future release
-- please fix it now!



$ readelf --dynamic libBroken.so | grep NEEDED
0x00000001 (NEEDED) Shared library: [libnativehelper.so]
0x00000001 (NEEDED) Shared library: [libutils.so]
0x00000001 (NEEDED) Shared library: [libstagefright_foundation.so]
0x00000001 (NEEDED) Shared library: [libmedia_jni.so]
0x00000001 (NEEDED) Shared library: [liblog.so]
0x00000001 (NEEDED) Shared library: [libdl.so]
0x00000001 (NEEDED) Shared library: [libz.so]
0x00000001 (NEEDED) Shared library: [libstdc++.so]
0x00000001 (NEEDED) Shared library: [libm.so]
0x00000001 (NEEDED) Shared library: [libc.so]


Potential problems: starting from API 24 the dynamic linker will not load
private libraries, preventing the application from loading.



Resolution: rewrite your native code to rely only on public API. As a short term
workaround, platform libraries without complex dependencies (libcutils.so) can
be copied to the project. As a long term solution the relevant code must be
copied to the project tree. SSL/Media/JNI internal/binder APIs should not be
accessed from the native code. When necessary, native code should call
appropriate public Java API methods.



A complete list of public libraries is available within the NDK, under
platforms/android-API/usr/lib.


Note: SSL/crypto is a special case, applications must NOT use platform libcrypto
and libssl libraries directly, even on older platforms. All applications should
use href="http://developer.android.com/training/articles/security-gms-provider.html?utm_campaign=android_discussion_ndkchanges_062716&utm_source=anddev&utm_medium=blog">GMS
Security Provider to ensure they are protected from known vulnerabilities.


Missing Section Headers (Enforced since API 24)



Each ELF file has additional information contained in the section headers. These
headers must be present now, because the dynamic linker uses them for sanity
checking. Some developers try to strip them in an attempt to obfuscate the
binary and prevent reverse engineering. (This doesn’t really help because it is
possible to reconstruct the stripped information using widely-available tools.)



$ readelf --header libBroken.so | grep 'section headers'
Start of section headers: 0 (bytes into file)
Size of section headers: 0 (bytes)
Number of section headers: 0
$


Resolution: remove the extra steps from your build that strip section headers.


Text Relocations (Enforced since API 23)



Starting with API 23, shared objects must not contain text relocations. That is,
the code must be loaded as is and must not be modified. Such an approach reduces
load time and improves security.



The usual reason for text relocations is non-position independent hand-written
assembler. This is not common. Use the href="https://wiki.gentoo.org/wiki/Hardened/Textrels_Guide#Finding_broken_object_code">scanelf
tool as described in href="http://developer.android.com/about/versions/marshmallow/android-6.0-changes.html?utm_campaign=android_discussion_ndkchanges_062716&utm_source=anddev&utm_medium=blog#behavior-runtime">our
documentation for further diagnostics:



$ scanelf -qT libTextRel.so
libTextRel.so: (memory/data?) [0x15E0E2] in (optimized out: previous simd_broken_op1) [0x15E0E0]
libTextRel.so: (memory/data?) [0x15E3B2] in (optimized out: previous simd_broken_op2) [0x15E3B0]
[skipped the rest]


If you have no scanelf tool available, it is possible to do a basic check with
readelf instead, look for either a TEXTREL entry or the TEXTREL flag. Either
alone is sufficient. (The value corresponding to the TEXTREL entry is irrelevant
and typically 0 --- simply the presence of the TEXTREL entry declares that the
.so contains text relocations). This example has both indicators present:



$ readelf --dynamic libTextRel.so | grep TEXTREL
0x00000016 (TEXTREL) 0x0
0x0000001e (FLAGS) SYMBOLIC TEXTREL BIND_NOW
$


Note: it is technically possible to have a shared object with the TEXTREL
entry/flag but without any actual text relocations. This doesn’t happen with the
NDK, but if you’re generating ELF files yourself make sure you’re not generating
ELF files that claim to have text relocations, because the Android dynamic
linker trusts the entry/flag.



Potential problems: Relocations enforce code pages being writable, and
wastefully increase the number of dirty pages in memory. The dynamic linker has
issued warnings about text relocations since Android K (API 19), but on API 23
and above it refuses to load code with text relocations.



Resolution: rewrite assembler to be position independent to ensure no text
relocations are necessary. Check the href="https://wiki.gentoo.org/wiki/Hardened/Textrels_Guide">Gentoo
documentation for cookbook recipes.


Invalid DT_NEEDED Entries (Enforced since API 23)



While library dependencies (DT_NEEDED entries in the ELF headers) can be
absolute paths, that doesn’t make sense on Android because you have no control
over where your library will be installed by the system. A DT_NEEDED entry
should be the same as the needed library’s SONAME, leaving the business of
finding the library at runtime to the dynamic linker.



Before API 23, Android’s dynamic linker ignored the full path, and used only the
basename (the part after the last ‘/’) when looking up the required libraries.
Since API 23 the runtime linker will honor the DT_NEEDED exactly and so it won’t
be able to load the library if it is not present in that exact location on the
device.



Even worse, some build systems have bugs that cause them to insert DT_NEEDED
entries that point to a file on the build host, something that
cannot be found on the device.



$ readelf --dynamic libSample.so | grep NEEDED
0x00000001 (NEEDED) Shared library: [libm.so]
0x00000001 (NEEDED) Shared library: [libc.so]
0x00000001 (NEEDED) Shared library: [libdl.so]
0x00000001 (NEEDED) Shared library:
[C:\Users\build\Android\ci\jni\libBroken.so]
$


Potential problems: before API 23 the DT_NEEDED entry’s basename was used, but
starting from API 23 the Android runtime will try to load the library using the path
specified, and that path won’t exist on the device. There are broken third-party
toolchains/build systems that use a path on a build host instead of the SONAME.



Resolution: make sure all required libraries are referenced by SONAME only. It
is better to let the runtime linker to find and load those libraries as the
location may change from device to device.


Missing SONAME (Used since API 23)



Each ELF shared object (“native library”) must have a SONAME (Shared Object
Name) attribute. The NDK toolchain adds this attribute by default, so its
absence indicates either a misconfigured alternative toolchain or a
misconfiguration in your build system. A missing SONAME may lead to runtime
issues such as the wrong library being loaded: the filename is used instead when
this attribute is missing.



$ readelf --dynamic libWithSoName.so | grep SONAME
0x0000000e (SONAME) Library soname: [libWithSoName.so]
$


Potential problems: namespace conflicts may lead to the wrong library being
loaded at runtime, which leads to crashes when required symbols are not found,
or you try to use an ABI-incompatible library that isn’t the library you were
expecting.



Resolution: the current NDK generates the correct SONAME by default. Ensure
you’re using the current NDK and that you haven’t configured your build system
to generate incorrect SONAME entries (using the -soname linker
option).



Please remember, clean, cross-platform code built with a current NDK should have
no issues on Android N. We encourage you to revise your native code build so
that it produces correct binaries.

Thursday, April 14, 2016

Optimize, Develop, and Debug with Vulkan Developer Tools

Posted by Shannon Woods, Technical Program Manager



Today we're pleased to bring you a preview of Android development tools for Vulkan™. Vulkan is a new 3D rendering API which we’ve helped to develop as a member of Khronos, geared at providing explicit, low-overhead GPU (Graphics Processor Unit) control to developers. Vulkan’s reduction of CPU overhead allows some synthetic benchmarks to see as much as 10 times the draw call throughput on a single core as compared to OpenGL ES. Combined with a threading-friendly API design which allows multiple cores to be used in parallel with high efficiency, this offers a significant boost in performance for draw-call heavy applications.



Vulkan support is available now via the Android N Preview on devices which support it, including Nexus 5X and Nexus 6P. (Of course, you will still be able to use OpenGL ES as well!)




To help developers start coding quickly, we’ve put together a set of samples and guides that illustrate how to use Vulkan effectively.



You can see Vulkan in action running on an Android device with Robert Hodgin’s Fish Tornado demo, ported by Google’s Art, Copy, and Code team:






Optimization: The Vulkan API



There are many similarities between OpenGL ES and Vulkan, but Vulkan offers new features for developers who need to make every millisecond count.




  • Application control of memory allocation. Vulkan provides mechanisms for fine-grained control of how and when memory is allocated on the GPU. This allows developers to use their own allocation and recycling policies to fit their application, ultimately reducing execution and memory overhead and allowing applications to control when expensive allocations occur.

  • Asynchronous command generation. In OpenGL ES, draw calls are issued to the GPU as soon as the application calls them. In Vulkan, the application instead submits draw calls to command buffers, which allows the work of forming and recording the draw call to be separated from the act of issuing it to the GPU. By spreading command generation across several threads, applications can more effectively make use of multiple CPU cores. These command buffers can also be reused, reducing the overhead involved in command creation and issuance.

  • No hidden work. One OpenGL ES pitfall is that some commands may trigger work at points which are not explicitly spelled out in the API specification or made obvious to the developer. Vulkan makes performance more predictable and consistent by specifying which commands will explicitly trigger work and which will not.

  • Multithreaded design, from the ground up. All OpenGL ES applications must issue commands for a context only from a single thread in order to render predictably and correctly. By contrast, Vulkan doesn’t have this requirement, allowing applications to do work like command buffer generation in parallel— but at the same time, it doesn’t make implicit guarantees about the safety of modifying and reading data from multiple threads at the same time. The power and responsibility of managing thread synchronization is in the hands of the application.

  • Mobile-friendly features. Vulkan includes features particularly helpful for achieving high performance on tiling GPUs, used by many mobile devices. Applications can provide information about the interaction between separate rendering passes, allowing tiling GPUs to make effective use of limited memory bandwidth, and avoid performing off-chip reads.

  • Offline shader compilation. Vulkan mandates support for SPIR-V, an intermediate language for shaders. This allows developers to compile shaders ahead of time, and ship SPIR-V binaries with their applications. These binaries are simpler to parse than high-level languages like GLSL, which means less variance in how drivers perform this parsing. SPIR-V also opens the door for third parties to provide compilers for specialized or cross-platform shading languages.

  • Optional validation. OpenGL ES validates every command you call, checking that arguments are within expected ranges, and objects are in the correct state to be operated upon. Vulkan doesn’t perform any of this validation itself. Instead, developers can use optional debug tools to ensure their calls are correct, incurring no run-time overhead in the final product.




Debugging: Validation Layers


As noted above, Vulkan’s lack of implicit validation requires developers to make use of tools outside the API in order to validate their code. Vulkan’s layer mechanism allows validation code and other developer tools to inspect every API call during development, without incurring any overhead in the shipping version. Our guides show you how to build the validation layers for use with the Android NDK, giving you the tools necessary to build bug-free Vulkan code from start to finish.




Develop: Shader toolchain



The Shaderc collection of tools provides developers with build-time and run-time tools for compiling GLSL into SPIR-V. Shaders can be compiled at build time using glslc, a command-line compiler, for easy integration into existing build systems. Or, for shaders which are generated or edited during execution, developers can use the Shaderc library to compile GLSL shaders to SPIR-V via a C interface. Both tools are built on top of Khronos’s reference compiler.




Additional Resources


The Vulkan ecosystem is a broad one, and the resources to get you started don’t end here. There is a wealth of material to explore, including:


























Friday, October 16, 2015

Game Performance: Vertex Array Objects

Game Performance: Vertex Array Objects

Posted by Shanee Nishry



Previously, we showed how you can use vertex layout qualifiers to increase the performance and determinism of your OpenGL application. In this post, we’ll show another useful technique that will help you produce increased performance and cleaner code when drawing objects.



Binding the vertex buffer



Before drawing onto the screen, you need to bind your vertex data (e.g. positions, normals, UVs) to the corresponding vertex shader attributes. To do that, you need to bind the vertex buffer, enable the generic vertex attribute, and use glVertexAttribPointer to describe the layout of the buffer.



Therefore, a draw call might look like this:



const GLuint ATTRIBUTE_LOCATION_POSITIONS   = 0;
const GLuint ATTRIBUTE_LOCATION_TEXTUREUV = 1;
const GLuint ATTRIBUTE_LOCATION_NORMALS = 2;

// Bind shader program, uniforms and textures
// ...

// Bind the vertex buffer
glBindBuffer( GL_ARRAY_BUFFER, vertex_buffer_object );

// Set the vertex attributes
glEnableVertexAttribArray( ATTRIBUTE_LOCATION_POSITIONS );
glVertexAttribPointer( ATTRIBUTE_LOCATION_POSITIONS, 3, GL_FLOAT, GL_FALSE, 32, 0 );

glEnableVertexAttribArray( ATTRIBUTE_LOCATION_TEXTUREUV );
glVertexAttribPointer( ATTRIBUTE_LOCATION_TEXTUREUV, 2, GL_FLOAT, GL_FALSE, 32, 12 );

glEnableVertexAttribArray( ATTRIBUTE_LOCATION_NORMALS );
glVertexAttribPointer( ATTRIBUTE_LOCATION_NORMALS, 3, GL_FLOAT, GL_FALSE, 32, 20 );

// Draw elements
glDrawElements( GL_TRIANGLES, count, GL_UNSIGNED_SHORT, 0 );


There are several reasons why we might not like this code very much. The first is that we need to cache the layout of the vertex buffer to enable and disable the right attributes before drawing. This means we are either hard-coding or saving some amount of data for a nearly meaningless task.



The second reason is performance. Having to tell the drivers which attributes to individually activate is suboptimal. It would be best if we could precompile this information and deliver it all at once.



Lastly, and purely for aesthetics, our draw call is cluttered by long boilerplate code. It would be nice to get rid of it.








Did you know there is another reason why someone might frown on this code? The code is making use of layout qualifiers which is great! But, since it’s already using OpenGL ES 3+, it would be even better if the code also used Geometry Instancing. By batching many instances of a mesh into a single draw call, you can really boost performance.




So how can we improve on the above code?



Vertex Array Objects (VAOs)



If you are using OpenGL ES 3 or higher, you should use Vertex Array Objects (or "VAOs") to store your vertex attribute state.



Using a VAO allows the drivers to compile the vertex description format for repeated use. In addition, this frees you from having to cache the vertex format needed for glVertexAttribPointer, and it also results in less per-draw boilerplate code.



Creating Vertex Array Objects



The first thing you need to do is create your VAO. This is created once per mesh, alongside the vertex buffer object and is done like this:



const GLuint ATTRIBUTE_LOCATION_POSITIONS   = 0;
const GLuint ATTRIBUTE_LOCATION_TEXTUREUV = 1;
const GLuint ATTRIBUTE_LOCATION_NORMALS = 2;

// Bind the vertex buffer object
glBindBuffer( GL_ARRAY_BUFFER, vertex_buffer_object );

// Create a VAO
GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );

// Set the vertex attributes as usual
glEnableVertexAttribArray( ATTRIBUTE_LOCATION_POSITIONS );
glVertexAttribPointer( ATTRIBUTE_LOCATION_POSITIONS, 3, GL_FLOAT, GL_FALSE, 32, 0 );

glEnableVertexAttribArray( ATTRIBUTE_LOCATION_TEXTUREUV );
glVertexAttribPointer( ATTRIBUTE_LOCATION_TEXTUREUV, 2, GL_FLOAT, GL_FALSE, 32, 12 );

glEnableVertexAttribArray( ATTRIBUTE_LOCATION_NORMALS );
glVertexAttribPointer( ATTRIBUTE_LOCATION_NORMALS, 3, GL_FLOAT, GL_FALSE, 32, 20 );

// Unbind the VAO to avoid accidentally overwriting the state
// Skip this if you are confident your code will not do so
glBindVertexArray( 0 );


You have probably noticed that this is very similar to our previous code section except that we now have the addition of:



// Create a vertex array object
GLuint vao;
glGenVertexArrays( 1, &vao );
glBindVertexArray( vao );


These lines create and bind the VAO. All glEnableVertexAttribArray and glVertexAttribPointer calls after that are recorded in the currently bound VAO, and that greatly simplifies our per-draw procedure as all you need to do is use the newly created VAO.



Using the Vertex Array Object



The next time you want to draw using this mesh all you need to do is bind the VAO using glBindVertexArray.



// Bind shader program, uniforms and textures
// ...

// Bind Vertex Array Object
glBindVertexArray( vao );

// Draw elements
glDrawElements( GL_TRIANGLES, count, GL_UNSIGNED_SHORT, 0 );


You no longer need to go through all the vertex attributes. This makes your code cleaner, makes per-frame calls shorter and more efficient, and allows the drivers to optimize the binding stage to increase performance.








Did you notice we are no longer calling glBindBuffer? This is because calling glVertexAttribPointer while recording the VAO references the currently bound buffer even though the VAO does not record glBindBuffer calls on itself.



Want to learn more how to improve your game performance? Check out our Game Performance article series. If you are building on Android you might also be interested in the Android Performance Patterns.



Android Support Library 23.1

Posted by Ian Lake, Developer Advocate



The Android Support Library is a collection of libraries available on a wide array of API levels that help you focus on the unique parts of your app, providing pre-built components, new functionality, and compatibility shims.



With the latest release of the Android Support Library (23.1), you will see improvements across the Support V4, Media Router, RecyclerView, AppCompat, Design, Percent, Custom Tabs, Leanback, and Palette libraries. Let’s take a closer look.



Support V4



The Support V4 library focuses on making supporting a wide variety of API levels straightforward with compatibility shims and backporting specific functionality.



NestedScrollView is a ScrollView that supports nested scrolling back to API 4. You’ll now be able to set a OnScrollChangeListener to receive callbacks when the scroll X or Y positions change.



There are a lot of pieces that make up a fully functioning media playback app, with much of it centered around MediaSessionCompat. A media button receiver, a key part to handling playback controls from hardware or bluetooth controls, is now formalized in the new MediaButtonReceiver class. This class makes it possible to forward received playback controls to a Service which is managing your MediaSessionCompat, reusing the Callback methods already required for API 21+, centralizing support on all API levels and all media control events in one place. A simplified constructor for MediaSessionCompat is also available, automatically finding a media button receiver in your manifest for use with MediaSessionCompat.



Media Router



The Media Router Support Library is the key component for connecting and sending your media playback to remote devices, such as video and audio devices with Google Cast support. It also provides the mechanism, via MediaRouteProvider, to enable any application to create and manage a remote media playback device connection.



In this release, MediaRouteChooserDialog (the dialog that controls selecting a valid remote device) and MediaRouteControllerDialog (the dialog to control ongoing remote playback) have both received a brand new design and additional functionality as well. You’ll find the chooser dialog sorts devices by frequency of use and includes a device type icon for easy identification of different devices while the controller dialog now shows current playback information (including album art).





To feel like a natural part of your app, the content color for both dialogs is now based on the colorPrimary of your alert dialog theme:



<!-- Your app theme set on your Activity -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<item name="colorPrimary">@color/primary</item>
<item name="colorPrimaryDark">@color/primaryDark</item>
<item name="alertDialogTheme">@style/AppTheme.Dialog</item>
</style>


<!-- Theme for the dialog itself -->
<style name="AppTheme.Dialog" parent="Theme.AppCompat.Light.Dialog.Alert">
<item name="colorPrimary">@color/primary</item>
<item name="colorPrimaryDark">@color/primaryDark</item>
</style>



RecyclerView



RecyclerView is an extremely powerful and flexible way to show a list, grid, or any view of a large set of data. One advantage over ListView or GridView is the built in support for animations as items are added, removed, or repositioned.



This release significantly changes the animation system for the better. By using the new ItemAnimator’s canReuseUpdatedViewHolder() method, you’ll be able to choose to reuse the existing ViewHolder, enabling item content animation support. The new ItemHolderInfo and associated APIs give the ItemAnimator the flexibility to collect any data it wants at the correct point in the layout lifecycle, passing that information into the animate callbacks.



Note that this new API is not backward compatible. If you previously implemented an ItemAnimator, you can instead extend SimpleItemAnimator, which provides the old API by wrapping the new API. You’ll also notice that some methods have been entirely removed from ItemAnimator. For example, if you were calling recyclerView.getItemAnimator().setSupportsChangeAnimations(false), this code won’t compile anymore. You can replace it with:



ItemAnimator animator = recyclerView.getItemAnimator();
if (animator instanceof SimpleItemAnimator) {
((SimpleItemAnimator) animator).setSupportsChangeAnimations(false);
}


AppCompat



One component of the AppCompat Support Library has been in providing a consistent set of widgets across all API levels, including the ability to tint those widgets to match your branding and accent colors.



This release adds tint aware versions of SeekBar (for tinting the thumb) as well as ImageButton and ImageView (providing backgroundTint support) which will automatically be used when you use the platform versions in your layouts. You’ll also find that SwitchCompat has been updated to match the styling found in Android 6.0 Marshmallow.



Design



The Design Support Library includes a number of components to help implement the latest in the Google design specifications.



TextInputLayout expands its existing functionality of floating hint text and error indicators with new support for character counting.



AppBarLayout supports a number of scroll flags which affect how children views react to scrolling (e.g. scrolling off the screen). New to this release is SCROLL_FLAG_SNAP, ensuring that when scrolling ends, the view is not left partially visible. Instead, it will be scrolled to its nearest edge, making fully visible or scrolled completely off the screen. You’ll also find that AppBarLayout now allows users to start scrolling from within the AppBarLayout rather than only from within your scrollable view - this behavior can be controlled by adding a DragCallback.



NavigationView provides a convenient way to build a navigation drawer, including the ability to creating menu items using a menu XML file. We’ve expanded the functionality possible with the ability to set custom views for items via app:actionLayout or using MenuItemCompat.setActionView().



Percent



The Percent Support Library provides percentage based dimensions and margins and, new to this release, the ability to set a custom aspect ratio via app:aspectRatio. By setting only a single width or height and using aspectRatio, the PercentFrameLayout or PercentRelativeLayout will automatically adjust the other dimension so that the layout uses a set aspect ratio.



Custom Tabs



The Custom Tabs Support Library allows your app to utilize the full features of compatible browsers including using pre-existing cookies while still maintaining a fast load time (via prefetching) and a custom look and actions.



In this release, we’re adding a few additional customizations such as hiding the url bar when the page is scrolled down with the new enableUrlBarHiding() method. You’ll also be able to update the action button in an already launched custom tab via your CustomTabsSession with setActionButton() - perfect for providing a visual indication of a state change.



Navigation events via CustomTabsCallback#onNavigationEvent() have also been expanded to include the new TAB_SHOWN and TAB_HIDDEN events, giving your app more information on how the user interacts with your web content.



Leanback



The Leanback library makes it easy to build user interfaces on TV devices. This release adds GuidedStepSupportFragment for a support version of GuidedStepFragment as well as improving animations and transitions and allowing GuidedStepFragment to be placed on top of existing content.



You’ll also be able to annotate different types of search completions in SearchFragment and staggered slide transition support for VerticalGridFragment.



Palette



Palette, used to extract colors from images, now supports extracting from a specific region of a Bitmap with the new setRegion() method.



SDK available now!



There’s no better time to get started with the Android Support Library. You can get started developing today by updating the Android Support Repository from the Android SDK Manager.



For an in depth look at every API change in this release, check out the full API diff.



To learn more about the Android Support Library and the APIs available to you through it, visit the Support Library section on the Android Developer site.


Thursday, September 10, 2015

Play Games Loot Drop for Developers

Posted by Ben Frenkel, Product Manager Google Play Games



Launched last March, Player Analytics is already becoming an important tool for many game developers, helping them to manage their games businesses and optimize in-game player behavior. Today we’re expanding Player Analytics with two new analytics reports that give you better visibility into time-based player activity and custom game events. We’re also introducing a new Player Stats API to let you tune your game experience for specific segments of players across the game lifecycle. Along with those, we’re rolling out a new version of our C++/iOS SDKs and Unity plug-in and giving you better tools to manage repeating Quests.



New useful reports for developers



We are launching two new reports later this week in the Play Games developer console: the Player Time Series Explorer and the Events Viewer. We’ve also made improvements to our player retention report.



Player Time Series Explorer



Ever wondered what your players are doing in the first few minutes of gameplay? What happens just before players spend or churn? The time-series explorer lets you understand what happens in these critical moments for your players.



For example, you carefully built out the first set of experiences in your game, but are surprised by how many players never get through even the first set of challenges. With the Player Time Series Explorer, you can now see which challenges are impeding player progress most, and make targeted improvements to decrease the rate of churn. Learn more.



Customize settings to explore player time series





Select from a list of preset questions





Find out what happens before your players spend for the first time



Select “What happens before first spend” to see what happens just before your players spend for the first time. Time series are aligned by first spend event so you can easily explore what happened just before and after first purchase.





Find out what happens before your players churn



Select “What happens before churn” to see what happens before your players stop playing. In the example below, all the churn events are right aligned to make it easier to compare player time series.





Hovering over events shows you additional details

You can see more details for all event types by holding your cursor over the event’s shape. In this example, you can see that “Player 03” spent $4.99 after earning six achievements. Hovering over the achievement shapes will show you which specific achievements were earned.





Events Viewer



Now you can create your own reports based on your custom Play Games’ events. You can select multiple events to display and bookmark the report for easy access. Learn more.



Here’s an example showing how a developer can compare the rates at which Players are entering contests, winning, and almost winning. This report would identify opportunities to improve the balance of its contest modes. You can then bookmark the settings so you can easily track improvements.





28x28 day retention grid



We added a 28-day-by-28-day retention grid to help you compare retention rates across a larger number of new user cohorts.





Tailor player experiences with the Player Stats API



Stats and reports give you insights into your what your players are doing, but wouldn’t it be nice to take action on those insights in your game? That’s what the Player Stats API is all about. The Player Stats API lets you tailor player experiences to specific segments of players across the game lifecycle. Player segments are based on player progression, spend, and engagement.



Here are some examples of what you can do with Player Stats API:



  • For highly engaged players that just aren’t spending, you can show them special bonuses that are aimed at recruiting others to play instead of spending

  • For your most prolific spenders, you can provide occasional free gifts and upgrades

  • For users that haven’t found their stride in your game, you can show them a video that directs them to community features, like clan attacks or alliances, that drive deeper engagement

  • For players that have been away from the game for a while, you can give them a welcome back message that acknowledges impressive accomplishments, and award a badge designed to encourage return play


The Player Stats API is launching in the next few weeks.



C++/iOS SDK and Unity Plug-in updates



iOS support for Play game services just got a lot better. This update includes improved CocoaPods support, which will make it easier to configure Play game services in Xcode. This also means you’ll have a much easier time building for iOS using the Unity plug-in as well.



The latest build of the C++/iOS SDKs is now built on the new Google Sign-In framework, which adds support for authentication via multiple Google apps, including Gmail and YouTube. More importantly, if a player does not have any applicable Google apps installed, the Sign-In framework will bring up a webview within the app for authentication. Opening up a webview inside the app, instead of switching to a separate browser instance, makes for a much better user experience, and addresses a top developer request. For more on the new Google Sign-in library on iOS, check out this video. Learn more.



Improved Quests



Quests are a great way of engaging your players with new goals, and with this update we have made managing Quests easier with the introduction of repeating Quests. You can create Quests that run weekly or monthly by checking the repeating quest box. This will make it easier for you to engage your players with regularly occurring challenges. Repeating Quests will be launching in the next few weeks.



If you have previously integrated Quests, you can easily convert them into repeating quests by following two easy steps.



1. Go to Quests section of developer console, and open up an existing Quest. Click the copy Quest button at the top of the page





2. Scroll down to the Schedule section of the Quest form, check the “Repeating quest” box, select between monthly and weekly quests under “Repeats”, and leave the “Ends:” field set to “Never”. After hitting save, you are done! From then on, the quest will run weekly or monthly until you decide to end it.





Google Play game services (GPGS) docs and SDK downloads