Slide 1

Slide 1 text

Developers

Slide 2

Slide 2 text

For Butter or Worse Smoothing Out Performance in Android UIs Chet Haase Romain Guy Android UI Toolkit Engineers

Slide 3

Slide 3 text

Developers

Slide 4

Slide 4 text

jank, noun 1. Choppy performance “Swiping the home screen feels janky” 2. Discontinuous, surprising experience “What's with the jank launching that app?”

Slide 5

Slide 5 text

butter, tasty noun 1. Smooth performance “Home screen swiping is very buttery” 2. Fattening spread and cooking ingredient “America’s obesity problem is directly proportional to the deliciousness of butter”

Slide 6

Slide 6 text

2. Discontinuous, surprising experience “What's with the jank launching that app?” jank, noun 1. Choppy performance “Swiping the home screen feels janky” This session will focus on the first kind of jank.

Slide 7

Slide 7 text

Recipe • Butter for eating is made from cream • Butter for Android is made from - low latency - fast, consistent framerate Latency Event Display

Slide 8

Slide 8 text

Recipe • Butter for eating is made from cream • Butter for Android is made from - low latency - fast, consistent framerate Latency Event Display

Slide 9

Slide 9 text

Recipe • Butter for eating is made from cream • Butter for Android is made from - low latency - fast, consistent framerate Latency Event Display Event Display Event Display Event Display Event Display Event Display Event Display Event Display Event Display Event Display Event Display

Slide 10

Slide 10 text

Input Latency Event Event Queue Event Event Event Event Process Events Draw

Slide 11

Slide 11 text

Input Lag (What a drag) `

Slide 12

Slide 12 text

Input Lag (What a drag) `

Slide 13

Slide 13 text

Input Lag (What a drag) `

Slide 14

Slide 14 text

Input Latency a a..c b User Input Time c d e f g h i j k l m n o p q r s t u v w x Dispatcher Activity Proc a..c Draw d...j Proc d..j Draw k..s

Slide 15

Slide 15 text

Input Latency a a..c b User Input Time c d e f g h i j k l m n o p q r s t u v w x Dispatcher Activity Proc a..c Draw d...j Proc d..j Draw k..s Latency a d c j

Slide 16

Slide 16 text

Event Streaming a b User Input Time c d e f g h i j k l m n o p q r s t u v w x Activity Proc a..f Draw Proc g..o Draw VSync VSync

Slide 17

Slide 17 text

Event Streaming a b User Input Time c d e f g h i j k l m n o p q r s t u v w x Activity Proc a..f Draw Proc g..o Draw VSync VSync Latency a g f o

Slide 18

Slide 18 text

Framerate Drawing Drawing faster is a good start

Slide 19

Slide 19 text

Framerate Drawing Drawing faster is a good start

Slide 20

Slide 20 text

Framerate But that's not quite all there is to it... Drawing Drawing faster is a good start

Slide 21

Slide 21 text

Drawing: The Big Picture Event Set Property Value Invalidate Measure & Layout Prepare Draw Update DisplayList Draw DisplayList Swap Buffers Composite Windows Post Buffer Display List Dequeue Buffer Enqueue Buffer Activity SurfaceFlinger

Slide 22

Slide 22 text

Something Happens Draw Display Activity SurfaceFlinger

Slide 23

Slide 23 text

Something Happens Draw Display Something Happens Draw Display Event Set Property Value Invalidate

Slide 24

Slide 24 text

Something Happens Draw Display Something Happens Draw Display Measure & Layout

Slide 25

Slide 25 text

Something Happens Draw Display Something Happens Draw Display Measure & Layout Prepare Draw Dequeue Buffer

Slide 26

Slide 26 text

Something Happens Draw Display Something Happens Draw Display Measure & Layout Prepare Draw Update DisplayList Display List Dequeue Buffer

Slide 27

Slide 27 text

Something Happens Draw Display Something Happens Draw Display Measure & Layout Prepare Draw Update DisplayList Draw DisplayList Display List Dequeue Buffer

Slide 28

Slide 28 text

Something Happens Draw Display Something Happens Draw Display Measure & Layout Prepare Draw Update DisplayList Draw DisplayList Swap Buffers Display List Dequeue Buffer Enqueue Buffer

Slide 29

Slide 29 text

Something Happens Draw Display Something Happens Draw Display Composite Windows Post Buffer

Slide 30

Slide 30 text

Something Happens Draw Display Something Happens Draw Display Event Set Property Value Invalidate Measure & Layout Prepare Draw Update DisplayList Draw DisplayList Swap Buffers Composite Windows Post Buffer Display List Dequeue Buffer Enqueue Buffer Activity SurfaceFlinger

Slide 31

Slide 31 text

VSync Synchronizing rendering with the display refresh 60 fps Displays refresh at 60 Hz, allowing apps to render at 60fps VSync (vertical sync) is a way to synchronize the rendering sub-system with the refresh of the hardware display.

Slide 32

Slide 32 text

In practice, the display refresh rate will be between 55 and 60 Hz. If your app does not hit 60 fps you might just be maxing out the device’s refresh rate. adb shell dumpsys SurfaceFlinger will tell you the exact refresh rate of your display.

Slide 33

Slide 33 text

Android has always used vsync to avoid tearing. Tearing happens when swapping buffers does not happen at the vsync. When this occurs, you will see part of the screen showing the previous buffer and part of the screen showing the new buffer. This effect can be seen in many games on consoles for instance. Prior to Android 4.1 Jelly Bean, animations and drawing requests were however not vsync’d.

Slide 34

Slide 34 text

Tearing Android has always used vsync to avoid tearing. Tearing happens when swapping buffers does not happen at the vsync. When this occurs, you will see part of the screen showing the previous buffer and part of the screen showing the new buffer. This effect can be seen in many games on consoles for instance. Prior to Android 4.1 Jelly Bean, animations and drawing requests were however not vsync’d.

Slide 35

Slide 35 text

Getting the Pixels to the Screen Time CPU GPU Visible Update DisplayList Draw DisplayList Display

Slide 36

Slide 36 text

Drawing without VSync 1 0 1 Time Display 1 1 2 2 2 CPU GPU 3 VSync VSync VSync VSync 3 3 4 4

Slide 37

Slide 37 text

Drawing without VSync 1 0 1 Time Display 1 1 2 2 2 CPU GPU 3 VSync VSync VSync VSync 3 3 4 4 Jank!

Slide 38

Slide 38 text

Drawing with VSync 1 0 1 Time Display 1 2 3 2 2 CPU GPU 4 VSync VSync VSync VSync 3 3 4 4

Slide 39

Slide 39 text

Drawing with DisplayLists set property invalidate set property invalidate set property invalidate set property invalidate Update DisplayList Draw DisplayList Display List VSync

Slide 40

Slide 40 text

Drawing with DisplayList Properties set property set property set property set property Draw DisplayList Display List VSync DLProps

Slide 41

Slide 41 text

DisplayList Properties • Free with ViewPropertyAnimator • Or use ObjectAnimator with View properties - alpha - translationX/Y - scaleX/Y - rotation/X/Y

Slide 42

Slide 42 text

0 1 2 3 Time in ms Frame With DisplayList Properties Without DisplayList Properties Comparison of drawing the transition from launcher to the list of all apps with and without display list properties. You can see that display list properties cost almost nothing

Slide 43

Slide 43 text

Parallel Processing and Double Buffering B A B Time Display VSync B A B A A B B A A CPU GPU A VSync VSync VSync

Slide 44

Slide 44 text

Parallel Processing and Double Buffering B A B Time Display A B B A A CPU GPU A VSync VSync VSync VSync Jank! Jank!

Slide 45

Slide 45 text

Parallel Processing and Double Buffering Triple B A B Time Display A B C C A CPU GPU C A B B A VSync VSync VSync VSync Jank!

Slide 46

Slide 46 text

Window Composition Draw DisplayList Swap Buffers Composite Windows Post Buffer Activity SurfaceFlinger

Slide 47

Slide 47 text

Window Composition GPU Draw DisplayList Swap Buffers Composite Windows Post Buffer Activity SurfaceFlinger Buffer Overlay Overlay Overlay FB FB FB Overlay

Slide 48

Slide 48 text

android:sdk $ cd platform-tools/ android:platform-tools $ adb shell 㾑 dumpsys gfxinfo dumpsys gfxinfo is a useful tool to analyze hardware accelerated apps shows memory usage, number of views and, with the right setting, frame profiling data

Slide 49

Slide 49 text

Must first be enabled Go to settings, then developer options

Slide 50

Slide 50 text

Must first be enabled Go to settings, then developer options

Slide 51

Slide 51 text

Must first be enabled Go to settings, then developer options

Slide 52

Slide 52 text

In Settings > Developer options, enable Profile GPU rendering You must destroy your activity before you’ll see the results

Slide 53

Slide 53 text

In Settings > Developer options, enable Profile GPU rendering You must destroy your activity before you’ll see the results

Slide 54

Slide 54 text

Demo Demo doing a dumpsys on com.android.settings Shows the array of values: Draw = update display lists Process = execute display lists Execute = swap buffers Copy the array and paste it in a spreadsheet to visualize the data. You’ll see the last 128 frames at most. Every time you capture a series of value, the buffer is cleared.

Slide 55

Slide 55 text

0 3 6 9 12 15 Time in ms Frames Update display lists Process display lists Swap buffers Scrolling the main screen in Settings on a Nexus 7 Everything is below 16ms. You can see processing the display lists is usually what takes time (turning Canvas commands into OpenGL primitives)

Slide 56

Slide 56 text

android:sdk $ cd tools/systrace android:systrace $ ./systrace systrace is a new, system-wide, instrumentation tool Useful to see how your app interacts with the rest of the world It can be used for optimization work. For instance if performance looks bad from gfxinfo or gfxinfo looks good but perf is bad

Slide 57

Slide 57 text

Find and click the Enable traces item

Slide 58

Slide 58 text

Find and click the Enable traces item

Slide 59

Slide 59 text

Find and click the Enable traces item

Slide 60

Slide 60 text

Select the traces you want. Most of the time you’ll want to use Graphics and View together, but you should experiment with other traces

Slide 61

Slide 61 text

Select the traces you want. Most of the time you’ll want to use Graphics and View together, but you should experiment with other traces

Slide 62

Slide 62 text

Select the traces you want. Most of the time you’ll want to use Graphics and View together, but you should experiment with other traces

Slide 63

Slide 63 text

Demo Let’s see how it works. Run systrace while scrolling settings, open the result and explain what we see: performTraversals/draw/etc. Open trace-slow.html and show what a bad app looks like and what to do with it. Go in traceview to see what the app does

Slide 64

Slide 64 text

Captures 5 seconds A systrace will capture only 5 seconds of data. You’ll usually run it to analyze an animation, a scroll, etc. You can change this behavior with an argument (-t)

Slide 65

Slide 65 text

Stand-alone HTML output The output is a stand-alone HTML file you can attach to bug reports, email to co-workers, etc. Open the help menu to see all the keys you can use. Most useful: WASD (just like in FPS games on PC) to move around and zoom in/out

Slide 66

Slide 66 text

android:sdk $ cd platform-tools/ android:platform-tools $ adb shell 㾑 dumpsys SurfaceFlinger

Slide 67

Slide 67 text

Demo

Slide 68

Slide 68 text

type | ... | name ----------+ ... +------- OVERLAY | ... | com...SlowListActivity OVERLAY | ... | StatusBar OVERLAY | ... | NavigationBar Here’s a sample output. You’ll find this table at the end of the dump. You want as many windows as possible to go into overlays. Here we have 3 windows on screen and everything is composited with overlays, it’s great

Slide 69

Slide 69 text

type | ... | name ----------+ ... +------- OVERLAY | ... | com...SlowListActivity OVERLAY | ... | StatusBar OVERLAY | ... | NavigationBar ✔ ✔ ✔ Here’s a sample output. You’ll find this table at the end of the dump. You want as many windows as possible to go into overlays. Here we have 3 windows on screen and everything is composited with overlays, it’s great

Slide 70

Slide 70 text

type | ... | name ----------+ ... +------ OVERLAY | ... | com...SlowListActivity FB | ... | PopupWindow:424d4cc8 FB | ... | StatusBar FB | ... | NavigationBar In this case our application creates an extra window, the PopupWindow The windows now cannot all go in overlays and 3 of them must be flattened using GPU composition There is a cost: GPU has more work to do, burns fillrate/bandwidth, etc. You want to avoid this.

Slide 71

Slide 71 text

type | ... | name ----------+ ... +------ OVERLAY | ... | com...SlowListActivity FB | ... | PopupWindow:424d4cc8 FB | ... | StatusBar FB | ... | NavigationBar ✔ ✘ ✘ ✘ In this case our application creates an extra window, the PopupWindow The windows now cannot all go in overlays and 3 of them must be flattened using GPU composition There is a cost: GPU has more work to do, burns fillrate/bandwidth, etc. You want to avoid this.

Slide 72

Slide 72 text

Caveats The number of overlays depends on the device. The opacity of the window may impact whether it goes in an overlay or not. Always use dumpsys while the app is drawing, or shortly after it’s done. Android has an optimization to move everything to FB (GPU) after a short period of time (saves battery when the app doesn’t update)

Slide 73

Slide 73 text

traceview We briefly talked about traceview, you can refer to the official documentation in the SDK It’s a tracing profiler that helps you see what’s going on in your app and how much time it takes It’s one of the most important tools at your disposal, and you can invoke it from ADT or DDMS

Slide 74

Slide 74 text

HierarchyViewer HierarchyViewer is your best friend when it comes to optimizing your UI. Use it stand-alone or as part of ADT. It shows you the tree of views straight from your app. You can inspect numerous properties, capture partial screenshots, force layouts/repaints, export PSD files and much more. Custom properties are supported with an annotation.

Slide 75

Slide 75 text

https://github.com/romainguy/ViewServer Note however that HierarchyViewer will not work out of the box on consumer devices. You must use an emulator, a userdebug or eng build, or use ViewServer.java available on github. Apache 2.0, easy to use and secure. We’re thinking of ways to integrate this directly into ADT.

Slide 76

Slide 76 text

Tracer for OpenGL ES Our newest tool; helps you debug and profile GL apps. Can be useful for hardware accelerated apps to see exactly what’s going on behind the scenes. Shows you how many commands your app generates, how much overdraw they cause, etc. You can also see the time each command takes to execute. Note that the commands are grouped by view, making it easy to read.

Slide 77

Slide 77 text

Allocation Tracker Allocation Tracker is part of DDMS and the easiest way to track down and remove unnecessary allocations from your app. Each allocation has a type, size and stack trace. Anecdote: as I was preparing this talk, I decided to take a screenshot of Allocation Tracker. This lead me to discover numerous unnecessary allocations caused by the GL rendering pipeline and that affected most apps.

Slide 78

Slide 78 text

Tips & Tricks

Slide 79

Slide 79 text

✔ Consistent frame-rate ✔ Lower latency ✔ Faster display list drawing ✔ GPU-free window composition ✔ Faster display list updates Here are the various things you can improve by applying the following tips

Slide 80

Slide 80 text

new Let me tell you how to use this keyword: don’t use it. Use DDMS’ allocation tracker to ensure you allocate only what you need in performance sensitive code paths (onDraw, onMeasure, onLayout, touch events, Adapter.getView, etc.)

Slide 81

Slide 81 text

new Let me tell you how to use this keyword: don’t use it. Use DDMS’ allocation tracker to ensure you allocate only what you need in performance sensitive code paths (onDraw, onMeasure, onLayout, touch events, Adapter.getView, etc.)

Slide 82

Slide 82 text

✔ Consistent frame-rate

Slide 83

Slide 83 text

public void bindView(View view, Context context, Cursor c) { BookViewHolder holder = (BookViewHolder) view.getTag(); String bookId = c.getString(mInternalIdIndex); holder.bookId = bookId; holder.sortTitle = c.getString(mSortTitleIndex); final ShelvesActivity activity = mActivity; if (activity.getScrollState() == SCROLL_STATE_FLING || activity.isPendingCoversUpdate()) { holder.title.setCompoundDrawablesWithIntrinsicBounds( null, null, null, mDefaultCover); holder.queryCover = true; } else { holder.title.setCompoundDrawablesWithIntrinsicBounds( null, null, null, ImageUtilities.getCachedCover(bookId, mDefaultCover)); holder.queryCover = false; } final CharArrayBuffer buffer = holder.buffer; c.copyStringToBuffer(mTitleIndex, buffer); final int size = buffer.sizeCopied; if (size != 0) { holder.title.setText(buffer.data, 0, size); } } In performance sensitive code paths, do less work. Use caches, avoid I/ O, don’t rescale images on the fly, use background tasks, etc. See Jeff Sharkey’s talk.

Slide 84

Slide 84 text

// Do less! In performance sensitive code paths, do less work. Use caches, avoid I/ O, don’t rescale images on the fly, use background tasks, etc. See Jeff Sharkey’s talk.

Slide 85

Slide 85 text

✔ Consistent frame-rate ✔ Lower latency

Slide 86

Slide 86 text

android.view.Choreographer Choreographer is a new API, very simple, in Android 4.1 Jelly Bean. It lets you schedule callbacks on vsync. This is the API used internally by the framework to schedule animations, redraws, etc. This API is great if your app does its own animations; games for instance.

Slide 87

Slide 87 text

// Invalidates at the next v-sync event myView.postInvalidateOnAnimation(); Use this method when implementing animations in your view. This is how the UI toolkit animates scrolls and flings in ListView, ScrollView, etc. Can be invoked from any thread.

Slide 88

Slide 88 text

callback = new Runnable() { public void run() { setupAndStartAnimation(); } } myView.postOnAnimation(callback); Runs an arbitrary action at the next v-sync. Useful to start your custom animations

Slide 89

Slide 89 text

callback = new Choreographer.FrameCallback() { public void doFrame(long frameTime) { render(frameTime); } }; Choreographer c = Choreographer.getInstance(); c.postFrameCallback(callback); If you write a game, you might not have a View, or you’re not using the UI thread, so use Choreographer direction. Simply create a FrameCallback and pass it to Choreographer. Note that there is one Choreographer instance per Looper thread. You can post a callback from any thread, but they will run on the Choreographer’s looper. The frametime in nanoseconds is very useful to synchronize animations on a single time-base. It’s the time at which the vsync event occurred.

Slide 90

Slide 90 text

✔ Consistent frame-rate ✔ Lower latency

Slide 91

Slide 91 text

view.setLayerType(View.LAYER_TYPE_HARDWARE, null); Complex view should be animated with layers enabled. A layer is a GPU snapshot of your view, and it’s extremely efficient to render. For more information, please refer to our Google I/O 2011 talk called “Android Accelerated Rendering”, available on YouTube.

Slide 92

Slide 92 text

view.animate().alpha(0).withLayer(); Starting with Android 4.1 Jelly Bean, an easier way to use layers is to use the new withLayer() API on ViewPropertyAnimator. Easy to write, easy to read, very efficient.

Slide 93

Slide 93 text

✔ Consistent frame-rate ✔ Faster display list drawing

Slide 94

Slide 94 text

✂ CLIP PING Clipping is handled by the UI toolkit to ensure the system only draws what needs to be drawn. Usually you don’t have to do anything but if you have custom drawing code or custom views you should make sure you don’t draw more than what you really need. Here are a couple of things you can do to help.

Slide 95

Slide 95 text

view.invalidate(); Whenever you call View.invalidate() ensure you need to redraw the entire view. In many situations a partial invalidate is enough and will help performance. Simply specify the region of the view that needs to be redrawn. A great example of this is EditText and its blinking cursor.

Slide 96

Slide 96 text

view.invalidate(left, top, right, bottom); Whenever you call View.invalidate() ensure you need to redraw the entire view. In many situations a partial invalidate is enough and will help performance. Simply specify the region of the view that needs to be redrawn. A great example of this is EditText and its blinking cursor.

Slide 97

Slide 97 text

DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList Calling invalidate() on a View will cause that entire View (and any view it intersects) to redraw. In this example, a complex view causes all of its children to redraw. Each display list must be executed.

Slide 98

Slide 98 text

DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList invalidate() Calling invalidate() on a View will cause that entire View (and any view it intersects) to redraw. In this example, a complex view causes all of its children to redraw. Each display list must be executed.

Slide 99

Slide 99 text

DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList invalidate() Draw display lists Calling invalidate() on a View will cause that entire View (and any view it intersects) to redraw. In this example, a complex view causes all of its children to redraw. Each display list must be executed.

Slide 100

Slide 100 text

DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList invalidate() Draw display lists Calling invalidate() on a View will cause that entire View (and any view it intersects) to redraw. In this example, a complex view causes all of its children to redraw. Each display list must be executed.

Slide 101

Slide 101 text

DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList With invalidate(l, t, r, b) the rendering pipeline can cull (i.e. ignore) entire parts of the render tree. This leads to significant performance improvements when used properly.

Slide 102

Slide 102 text

DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList invalidate(l, t, r, b) With invalidate(l, t, r, b) the rendering pipeline can cull (i.e. ignore) entire parts of the render tree. This leads to significant performance improvements when used properly.

Slide 103

Slide 103 text

DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList invalidate(l, t, r, b) Draw display lists With invalidate(l, t, r, b) the rendering pipeline can cull (i.e. ignore) entire parts of the render tree. This leads to significant performance improvements when used properly.

Slide 104

Slide 104 text

DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList DisplayList invalidate(l, t, r, b) Draw display lists With invalidate(l, t, r, b) the rendering pipeline can cull (i.e. ignore) entire parts of the render tree. This leads to significant performance improvements when used properly.

Slide 105

Slide 105 text

✔ Faster display list drawing

Slide 106

Slide 106 text

In developer settings, use “Show GPU view updates” to enable a tool that flashes the region of the screen you invalidate. This is very useful to ensure you only invalidate what’s needed.

Slide 107

Slide 107 text

In developer settings, use “Show GPU view updates” to enable a tool that flashes the region of the screen you invalidate. This is very useful to ensure you only invalidate what’s needed.

Slide 108

Slide 108 text

Don’t draw invisible items invalidate(l,t,r,b) is useful to tell the system what parts of the screen to redraw. It is equally important to never draw pieces of the UI that will never be visible to the user. In this section we’ll focus on a real-world example, using the Google application, new in Android 4.1 Jelly Bean. When the app shows you suggestion cards, they can appear stacked. If you use standard views, overdraw will occur.

Slide 109

Slide 109 text

Let’s concentrate on two of the cards to see how they are implemented.

Slide 110

Slide 110 text

Let’s concentrate on two of the cards to see how they are implemented.

Slide 111

Slide 111 text

Let’s concentrate on two of the cards to see how they are implemented.

Slide 112

Slide 112 text

If you just stack the two cards using regular Views, here is how they will be drawn. First the bottom view, then the top one. There is quite a lot of overdraw happening here, highlighted in red. What can we do to get rid of that overdraw?

Slide 113

Slide 113 text

If you just stack the two cards using regular Views, here is how they will be drawn. First the bottom view, then the top one. There is quite a lot of overdraw happening here, highlighted in red. What can we do to get rid of that overdraw?

Slide 114

Slide 114 text

If you just stack the two cards using regular Views, here is how they will be drawn. First the bottom view, then the top one. There is quite a lot of overdraw happening here, highlighted in red. What can we do to get rid of that overdraw?

Slide 115

Slide 115 text

If you just stack the two cards using regular Views, here is how they will be drawn. First the bottom view, then the top one. There is quite a lot of overdraw happening here, highlighted in red. What can we do to get rid of that overdraw?

Slide 116

Slide 116 text

@Override public void onDraw(Canvas c) { c.save(); if (stacked) { c.clipRect(headerLeft, headerTop, headerRight, headerBottom); } drawHeader(c); drawContent(c); c.restore(); } The trick is to set the clip rect to include only the “header” of the stacked card. This way the content won’t be drawn at all.

Slide 117

Slide 117 text

Here’s what the render pass looks like now that we properly clip the content of the bottom card. No more wasted cycles on drawing hidden content.

Slide 118

Slide 118 text

clipRect Here’s what the render pass looks like now that we properly clip the content of the bottom card. No more wasted cycles on drawing hidden content.

Slide 119

Slide 119 text

clipRect Here’s what the render pass looks like now that we properly clip the content of the bottom card. No more wasted cycles on drawing hidden content.

Slide 120

Slide 120 text

clipRect Here’s what the render pass looks like now that we properly clip the content of the bottom card. No more wasted cycles on drawing hidden content.

Slide 121

Slide 121 text

✔ Faster display list drawing Properly clipping your custom views will help reduce the time spent drawing display lists. But we can do better.

Slide 122

Slide 122 text

private void drawContent(Canvas c) { for (Item item : itemsList) { if (!c.quickReject(item.l, item.t, item.r, item.b, Canvas.EdgeType.BW)) { item.draw(c); } } } If quickReject() returns true, then the specified rectangle is outside of the current clip region. Which means whatever you draw within the bounds of the specified rectangle will not show up on screen. In this case you can simply avoid calling your drawing code. This is what the UI toolkit does automatically with views.

Slide 123

Slide 123 text

✔ Faster display list drawing ✔ Faster display list updates Any piece of code you can avoid running is a win for performance and quickReject can help you.

Slide 124

Slide 124 text

Dim layer The dim layer is a special layer on Android, managed by the window manager and SurfaceFlinger. Any window can request the dim layer to draw attention to the foreground. It helps the user by giving context (you are still performing the same task) but removes distractions.

Slide 125

Slide 125 text

getWindow().addFlags( WindowManager.LayoutParams.FLAG_DIM_BEHIND); Requesting a dim layer is very easy. Just set the appropriate flag on your activity’s or dialog’s window. You can also change the dim amount.

Slide 126

Slide 126 text

type | ... | name ----------+ ... +------ OVERLAY | ... | com...MyActivity FB | ... | DimAnimator FB | ... | StatusBar FB | ... | NavigationBar Using a dim layer will unfortunately introduce a new surface that SurfaceFlinger must composite. This is usually enough to make apps fall out of the optimized all-overlays case. In addition, the dim layer is *always* composited by the GPU. Even if there are enough overlays available to do the composition, the dim layer will force a GPU composition.

Slide 127

Slide 127 text

type | ... | name ----------+ ... +------ OVERLAY | ... | com...MyActivity FB | ... | DimAnimator FB | ... | StatusBar FB | ... | NavigationBar ✔ ✘ ✘ ✘ Using a dim layer will unfortunately introduce a new surface that SurfaceFlinger must composite. This is usually enough to make apps fall out of the optimized all-overlays case. In addition, the dim layer is *always* composited by the GPU. Even if there are enough overlays available to do the composition, the dim layer will force a GPU composition.

Slide 128

Slide 128 text

getWindow().addFlags( WindowManager.LayoutParams.FLAG_DIM_BEHIND); If you need the extra resources, use a background drawable instead. This is what Android 4.1 Jelly Bean does in the quick contact window to ensure the opening animation is smooth, with a consistent frame-rate.

Slide 129

Slide 129 text

getWindow().addFlags( WindowManager.LayoutParams.FLAG_DIM_BEHIND); getWindow().setBackground( new ColorDrawable(0x7f000000)); If you need the extra resources, use a background drawable instead. This is what Android 4.1 Jelly Bean does in the quick contact window to ensure the opening animation is smooth, with a consistent frame-rate.

Slide 130

Slide 130 text

✔ Faster display list drawing ✔ GPU-free window composition If you avoid using the dim layer, you can avoid spending GPU resources compositing the special dim layer. This will help improve the time spent drawing display lists. The fewer layers that need to be composited, the better.

Slide 131

Slide 131 text

Users love butter

Slide 132

Slide 132 text

Users love butter Spread the word

Slide 133

Slide 133 text

For More Information Google I/O 2011 Parleys.com Accelerated Android Rendering Various Android GUI performance talks

Slide 134

Slide 134 text

Q&A +Chet Haase +Romain Guy @chethaase @romainguy

Slide 135

Slide 135 text

Developers