Merge "Remove ZEN notification visibility setting"
diff --git a/Android.mk b/Android.mk
index 936b41a..43b7e59 100644
--- a/Android.mk
+++ b/Android.mk
@@ -330,11 +330,10 @@
 	telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl \
 	telecomm/java/com/android/internal/telecomm/ICallServiceLookupResponse.aidl \
 	telecomm/java/com/android/internal/telecomm/ICallServiceProvider.aidl \
-	telecomm/java/com/android/internal/telecomm/ICallServiceSelector.aidl \
-	telecomm/java/com/android/internal/telecomm/ICallServiceSelectorAdapter.aidl \
 	telecomm/java/com/android/internal/telecomm/IInCallAdapter.aidl \
 	telecomm/java/com/android/internal/telecomm/IInCallService.aidl \
 	telecomm/java/com/android/internal/telecomm/ITelecommService.aidl \
+	telecomm/java/com/android/internal/telecomm/RemoteServiceCallback.aidl \
 	telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl \
 	telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \
 	telephony/java/com/android/internal/telephony/ITelephony.aidl \
@@ -824,6 +823,7 @@
 		$(framework_docs_LOCAL_DROIDDOC_OPTIONS) \
 		-toroot / \
 		-hdf android.whichdoc online \
+		-briefdocs \
 		$(sample_groups) \
 		-hdf android.hasSamples true \
 		-samplesdir $(samples_dir)
diff --git a/api/current.txt b/api/current.txt
index 326c5b6..75db903 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -261,10 +261,13 @@
     field public static final int actionModeCloseDrawable = 16843484; // 0x10102dc
     field public static final int actionModeCopyDrawable = 16843538; // 0x1010312
     field public static final int actionModeCutDrawable = 16843537; // 0x1010311
+    field public static final int actionModeFindDrawable = 16843900; // 0x101047c
     field public static final int actionModePasteDrawable = 16843539; // 0x1010313
     field public static final int actionModeSelectAllDrawable = 16843646; // 0x101037e
+    field public static final int actionModeShareDrawable = 16843899; // 0x101047b
     field public static final int actionModeSplitBackground = 16843677; // 0x101039d
     field public static final int actionModeStyle = 16843668; // 0x1010394
+    field public static final int actionModeWebSearchDrawable = 16843901; // 0x101047d
     field public static final int actionOverflowButtonStyle = 16843510; // 0x10102f6
     field public static final int actionOverflowMenuStyle = 16843846; // 0x1010446
     field public static final int actionProviderClass = 16843657; // 0x1010389
@@ -510,7 +513,7 @@
     field public static final int excludeClass = 16843844; // 0x1010444
     field public static final int excludeFromRecents = 16842775; // 0x1010017
     field public static final int excludeId = 16843843; // 0x1010443
-    field public static final int excludeViewName = 16843856; // 0x1010450
+    field public static final int excludeName = 16843856; // 0x1010450
     field public static final int exitFadeDuration = 16843533; // 0x101030d
     field public static final int expandableListPreferredChildIndicatorLeft = 16842834; // 0x1010052
     field public static final int expandableListPreferredChildIndicatorRight = 16842835; // 0x1010053
@@ -1154,9 +1157,9 @@
     field public static final int targetClass = 16842799; // 0x101002f
     field public static final int targetDescriptions = 16843680; // 0x10103a0
     field public static final int targetId = 16843740; // 0x10103dc
+    field public static final int targetName = 16843855; // 0x101044f
     field public static final int targetPackage = 16842785; // 0x1010021
     field public static final int targetSdkVersion = 16843376; // 0x1010270
-    field public static final int targetViewName = 16843855; // 0x101044f
     field public static final int taskAffinity = 16842770; // 0x1010012
     field public static final int taskCloseEnterAnimation = 16842942; // 0x10100be
     field public static final int taskCloseExitAnimation = 16842943; // 0x10100bf
@@ -1239,6 +1242,8 @@
     field public static final int thumbTintMode = 16843892; // 0x1010474
     field public static final int thumbnail = 16843429; // 0x10102a5
     field public static final int tileMode = 16843265; // 0x1010201
+    field public static final int tileModeX = 16843897; // 0x1010479
+    field public static final int tileModeY = 16843898; // 0x101047a
     field public static final int timeZone = 16843724; // 0x10103cc
     field public static final int tint = 16843041; // 0x1010121
     field public static final int tintMode = 16843797; // 0x1010415
@@ -1266,6 +1271,7 @@
     field public static final int transformPivotY = 16843553; // 0x1010321
     field public static final int transition = 16843743; // 0x10103df
     field public static final int transitionGroup = 16843803; // 0x101041b
+    field public static final int transitionName = 16843802; // 0x101041a
     field public static final int transitionOrdering = 16843744; // 0x10103e0
     field public static final int translateX = 16843868; // 0x101045c
     field public static final int translateY = 16843869; // 0x101045d
@@ -1300,7 +1306,6 @@
     field public static final int verticalGap = 16843328; // 0x1010240
     field public static final int verticalScrollbarPosition = 16843572; // 0x1010334
     field public static final int verticalSpacing = 16843029; // 0x1010115
-    field public static final int viewName = 16843802; // 0x101041a
     field public static final int viewportHeight = 16843805; // 0x101041d
     field public static final int viewportWidth = 16843804; // 0x101041c
     field public static final int visibility = 16842972; // 0x10100dc
@@ -11253,6 +11258,17 @@
     method public void addTransition(int, int, android.graphics.drawable.AnimationDrawable, boolean);
   }
 
+  public class AnimatedVectorDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Animatable {
+    ctor public AnimatedVectorDrawable();
+    method public void draw(android.graphics.Canvas);
+    method public int getOpacity();
+    method public boolean isRunning();
+    method public void setAlpha(int);
+    method public void setColorFilter(android.graphics.ColorFilter);
+    method public void start();
+    method public void stop();
+  }
+
   public class AnimationDrawable extends android.graphics.drawable.DrawableContainer implements android.graphics.drawable.Animatable java.lang.Runnable {
     ctor public AnimationDrawable();
     method public void addFrame(android.graphics.drawable.Drawable, int);
@@ -11652,8 +11668,6 @@
     method public int getOpacity();
     method public void setAlpha(int);
     method public void setColorFilter(android.graphics.ColorFilter);
-    method public void setPadding(android.graphics.Rect);
-    method public void setPadding(int, int, int, int);
   }
 
 }
@@ -15818,7 +15832,14 @@
   }
 
   public final class MediaSessionManager {
+    method public void addActiveSessionsListener(android.media.session.MediaSessionManager.SessionListener, android.content.ComponentName);
     method public android.media.session.MediaSession createSession(java.lang.String);
+    method public java.util.List<android.media.session.MediaController> getActiveSessions(android.content.ComponentName);
+  }
+
+  public static abstract class MediaSessionManager.SessionListener {
+    ctor public MediaSessionManager.SessionListener();
+    method public abstract void onActiveSessionsChanged(java.util.List<android.media.session.MediaController>);
   }
 
   public final class MediaSessionToken implements android.os.Parcelable {
@@ -23449,6 +23470,7 @@
   protected static abstract interface ContactsContract.ContactOptionsColumns {
     field public static final java.lang.String CUSTOM_RINGTONE = "custom_ringtone";
     field public static final java.lang.String LAST_TIME_CONTACTED = "last_time_contacted";
+    field public static final java.lang.String PINNED = "pinned";
     field public static final java.lang.String SEND_TO_VOICEMAIL = "send_to_voicemail";
     field public static final java.lang.String STARRED = "starred";
     field public static final java.lang.String TIMES_CONTACTED = "times_contacted";
@@ -23726,6 +23748,13 @@
     field public static final int UNDEFINED = 0; // 0x0
   }
 
+  public static final class ContactsContract.PinnedPositions {
+    ctor public ContactsContract.PinnedPositions();
+    field public static final int DEMOTED = -1; // 0xffffffff
+    field public static final java.lang.String UNDEMOTE_METHOD = "undemote";
+    field public static final int UNPINNED = 2147483647; // 0x7fffffff
+  }
+
   public static final class ContactsContract.Preferences {
     ctor public ContactsContract.Preferences();
     field public static final java.lang.String DISPLAY_ORDER = "android.contacts.DISPLAY_ORDER";
@@ -23768,6 +23797,8 @@
     ctor public ContactsContract.QuickContact();
     method public static void showQuickContact(android.content.Context, android.view.View, android.net.Uri, int, java.lang.String[]);
     method public static void showQuickContact(android.content.Context, android.graphics.Rect, android.net.Uri, int, java.lang.String[]);
+    field public static final java.lang.String ACTION_QUICK_CONTACT = "com.android.contacts.action.QUICK_CONTACT";
+    field public static final java.lang.String EXTRA_EXCLUDE_MIMES = "exclude_mimes";
     field public static final int MODE_LARGE = 3; // 0x3
     field public static final int MODE_MEDIUM = 2; // 0x2
     field public static final int MODE_SMALL = 1; // 0x1
@@ -24530,6 +24561,7 @@
     field public static final java.lang.String PARENTAL_CONTROL_REDIRECT_URL = "parental_control_redirect_url";
     field public static final java.lang.String SELECTED_INPUT_METHOD_SUBTYPE = "selected_input_method_subtype";
     field public static final java.lang.String SETTINGS_CLASSNAME = "settings_classname";
+    field public static final java.lang.String SKIP_FIRST_USE_HINTS = "skip_first_use_hints";
     field public static final java.lang.String SYS_PROP_SETTING_VERSION = "sys.settings_secure_version";
     field public static final java.lang.String TOUCH_EXPLORATION_ENABLED = "touch_exploration_enabled";
     field public static final deprecated java.lang.String TTS_DEFAULT_COUNTRY = "tts_default_country";
@@ -27551,7 +27583,6 @@
     method protected final android.telecomm.CallServiceAdapter getAdapter();
     method public final android.os.IBinder getBinder();
     method public abstract void hold(java.lang.String);
-    method public abstract void isCompatibleWith(android.telecomm.CallInfo);
     method protected void onAdapterAttached(android.telecomm.CallServiceAdapter);
     method public abstract void onAudioStateChanged(java.lang.String, android.telecomm.CallAudioState);
     method public final android.os.IBinder onBind(android.content.Intent);
@@ -27564,8 +27595,9 @@
     method public abstract void unhold(java.lang.String);
   }
 
-  public final class CallServiceAdapter {
+  public final class CallServiceAdapter implements android.os.IBinder.DeathRecipient {
     method public void addConferenceCall(java.lang.String);
+    method public void binderDied();
     method public void handleFailedOutgoingCall(android.telecomm.ConnectionRequest, int, java.lang.String);
     method public void handleSuccessfulOutgoingCall(java.lang.String);
     method public void handoffCall(java.lang.String);
@@ -27574,7 +27606,6 @@
     method public void setActive(java.lang.String);
     method public void setDialing(java.lang.String);
     method public void setDisconnected(java.lang.String, int, java.lang.String);
-    method public void setIsCompatibleWith(java.lang.String, boolean);
     method public void setOnHold(java.lang.String);
     method public void setRequestingRingback(java.lang.String, boolean);
     method public void setRinging(java.lang.String);
@@ -27609,22 +27640,6 @@
     method public android.os.IBinder onBind(android.content.Intent);
   }
 
-  public abstract class CallServiceSelector extends android.app.Service {
-    ctor protected CallServiceSelector();
-    method protected final void cancelOutgoingCall(android.telecomm.CallInfo);
-    method protected final android.telecomm.CallServiceSelectorAdapter getAdapter();
-    method protected final java.util.Collection<android.telecomm.CallInfo> getCalls();
-    method protected void onAdapterAttached(android.telecomm.CallServiceSelectorAdapter);
-    method public final android.os.IBinder onBind(android.content.Intent);
-    method protected abstract void select(android.telecomm.CallInfo, java.util.List<android.telecomm.CallServiceDescriptor>);
-  }
-
-  public final class CallServiceSelectorAdapter {
-    method public void cancelOutgoingCall(java.lang.String);
-    method public void setHandoffInfo(java.lang.String, android.net.Uri, android.os.Bundle);
-    method public void setSelectedCallServices(java.lang.String, java.util.List<android.telecomm.CallServiceDescriptor>);
-  }
-
   public final class CallState extends java.lang.Enum {
     method public static android.telecomm.CallState valueOf(java.lang.String);
     method public static final android.telecomm.CallState[] values();
@@ -27645,6 +27660,7 @@
     method public java.util.List<android.telecomm.Connection> getChildConnections();
     method public final android.net.Uri getHandle();
     method public android.telecomm.Connection getParentConnection();
+    method public boolean isConferenceCapable();
     method public boolean isConferenceConnection();
     method public boolean isRequestingRingback();
     method protected void onAbort();
@@ -27713,10 +27729,12 @@
   public final class ConnectionRequest implements android.os.Parcelable {
     ctor public ConnectionRequest(android.net.Uri, android.os.Bundle);
     ctor public ConnectionRequest(java.lang.String, android.net.Uri, android.os.Bundle);
+    ctor public ConnectionRequest(android.telecomm.Subscription, java.lang.String, android.net.Uri, android.os.Bundle);
     method public int describeContents();
     method public java.lang.String getCallId();
     method public android.os.Bundle getExtras();
     method public android.net.Uri getHandle();
+    method public android.telecomm.Subscription getSubscription();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
   }
@@ -27726,17 +27744,18 @@
     method public final void abort(java.lang.String);
     method public final void answer(java.lang.String);
     method public final void call(android.telecomm.CallInfo);
+    method public void createRemoteOutgoingConnection(android.telecomm.ConnectionRequest, android.telecomm.SimpleResponse<android.telecomm.ConnectionRequest, android.telecomm.RemoteConnection>);
     method public final void disconnect(java.lang.String);
     method public java.util.Collection<android.telecomm.Connection> getAllConnections();
     method public final void hold(java.lang.String);
-    method public final void isCompatibleWith(android.telecomm.CallInfo);
+    method public void lookupRemoteSubscriptions(android.net.Uri, android.telecomm.SimpleResponse<android.net.Uri, java.util.List<android.telecomm.Subscription>>);
+    method public void maybeRespondToSubscriptionLookup();
     method public final void onAudioStateChanged(java.lang.String, android.telecomm.CallAudioState);
     method public void onConnectionAdded(android.telecomm.Connection);
     method public void onConnectionRemoved(android.telecomm.Connection);
     method public void onCreateConferenceConnection(java.lang.String, android.telecomm.Connection, android.telecomm.Response<java.lang.String, android.telecomm.Connection>);
     method public void onCreateConnections(android.telecomm.ConnectionRequest, android.telecomm.Response<android.telecomm.ConnectionRequest, android.telecomm.Connection>);
     method public void onCreateIncomingConnection(android.telecomm.ConnectionRequest, android.telecomm.Response<android.telecomm.ConnectionRequest, android.telecomm.Connection>);
-    method public void onFindSubscriptions(android.net.Uri, android.telecomm.Response<android.net.Uri, android.telecomm.Subscription>);
     method public final void onPostDialContinue(java.lang.String, boolean);
     method public final void onPostDialWait(android.telecomm.Connection, java.lang.String);
     method public final void playDtmfTone(java.lang.String, char);
@@ -27800,11 +27819,46 @@
     method protected abstract void updateCall(android.telecomm.InCallCall);
   }
 
+  public final class RemoteConnection {
+    method public void addListener(android.telecomm.RemoteConnection.Listener);
+    method public void answer();
+    method public void disconnect();
+    method public int getDisconnectCause();
+    method public java.lang.String getDisconnectMessage();
+    method public void hold();
+    method public void playDtmf(char);
+    method public void postDialContinue(boolean);
+    method public void reject();
+    method public void removeListener(android.telecomm.RemoteConnection.Listener);
+    method public void stopDtmf();
+    method public void unhold();
+  }
+
+  public static abstract interface RemoteConnection.Listener {
+    method public abstract void onAudioStateChanged(android.telecomm.RemoteConnection, android.telecomm.CallAudioState);
+    method public abstract void onDestroyed(android.telecomm.RemoteConnection);
+    method public abstract void onDisconnected(android.telecomm.RemoteConnection, int, java.lang.String);
+    method public abstract void onPostDialWait(android.telecomm.RemoteConnection, java.lang.String);
+    method public abstract void onRequestingRingback(android.telecomm.RemoteConnection, boolean);
+    method public abstract void onStateChanged(android.telecomm.RemoteConnection, int);
+  }
+
+  public class RemoteConnectionService implements android.os.IBinder.DeathRecipient {
+    method public void binderDied();
+    method public void createOutgoingConnection(android.telecomm.ConnectionRequest, android.telecomm.SimpleResponse<android.telecomm.ConnectionRequest, android.telecomm.RemoteConnection>);
+    method public java.util.List<android.telecomm.Subscription> lookupSubscriptions(android.net.Uri);
+  }
+
   public abstract interface Response {
     method public abstract void onError(IN, int, java.lang.String);
     method public abstract void onResult(IN, OUT...);
   }
 
+  public abstract interface SimpleResponse {
+    method public abstract void onError(IN);
+    method public abstract void onResult(IN, OUT);
+  }
+
   public class Subscription implements android.os.Parcelable {
     ctor public Subscription(android.content.ComponentName, java.lang.String, android.net.Uri, int, int, int, boolean, boolean);
     method public int describeContents();
@@ -27825,7 +27879,6 @@
     ctor public TelecommConstants();
     field public static final java.lang.String ACTION_CALL_SERVICE;
     field public static final java.lang.String ACTION_CALL_SERVICE_PROVIDER;
-    field public static final java.lang.String ACTION_CALL_SERVICE_SELECTOR;
     field public static final java.lang.String ACTION_INCOMING_CALL = "android.intent.action.INCOMING_CALL";
     field public static final char DTMF_CHARACTER_PAUSE = 44; // 0x002c ','
     field public static final char DTMF_CHARACTER_WAIT = 59; // 0x003b ';'
@@ -30535,8 +30588,8 @@
     method public android.transition.TransitionPropagation getPropagation();
     method public long getStartDelay();
     method public java.util.List<java.lang.Integer> getTargetIds();
+    method public java.util.List<java.lang.String> getTargetNames();
     method public java.util.List<java.lang.Class> getTargetTypes();
-    method public java.util.List<java.lang.String> getTargetViewNames();
     method public java.util.List<android.view.View> getTargets();
     method public java.lang.String[] getTransitionProperties();
     method public android.transition.TransitionValues getTransitionValues(android.view.View, boolean);
@@ -30554,7 +30607,7 @@
     field public static final int MATCH_ID = 3; // 0x3
     field public static final int MATCH_INSTANCE = 1; // 0x1
     field public static final int MATCH_ITEM_ID = 4; // 0x4
-    field public static final int MATCH_VIEW_NAME = 2; // 0x2
+    field public static final int MATCH_NAME = 2; // 0x2
   }
 
   public static abstract class Transition.EpicenterCallback {
@@ -32745,13 +32798,13 @@
     method protected int getTopPaddingOffset();
     method public android.view.TouchDelegate getTouchDelegate();
     method public java.util.ArrayList<android.view.View> getTouchables();
+    method public java.lang.String getTransitionName();
     method public float getTranslationX();
     method public float getTranslationY();
     method public float getTranslationZ();
     method public int getVerticalFadingEdgeLength();
     method public int getVerticalScrollbarPosition();
     method public int getVerticalScrollbarWidth();
-    method public java.lang.String getViewName();
     method public android.view.ViewTreeObserver getViewTreeObserver();
     method public int getVisibility();
     method public final int getWidth();
@@ -33008,13 +33061,13 @@
     method public void setTextDirection(int);
     method public final void setTop(int);
     method public void setTouchDelegate(android.view.TouchDelegate);
+    method public final void setTransitionName(java.lang.String);
     method public void setTranslationX(float);
     method public void setTranslationY(float);
     method public void setTranslationZ(float);
     method public void setVerticalFadingEdgeEnabled(boolean);
     method public void setVerticalScrollBarEnabled(boolean);
     method public void setVerticalScrollbarPosition(int);
-    method public final void setViewName(java.lang.String);
     method public void setVisibility(int);
     method public void setWillNotCacheDrawing(boolean);
     method public void setWillNotDraw(boolean);
@@ -36440,12 +36493,14 @@
     ctor public EdgeEffect(android.content.Context);
     method public boolean draw(android.graphics.Canvas);
     method public void finish();
+    method public int getColor();
     method public int getMaxHeight();
     method public boolean isFinished();
     method public void onAbsorb(int);
     method public void onPull(float);
     method public void onPull(float, float);
     method public void onRelease();
+    method public void setColor(int);
     method public void setSize(int, int);
   }
 
@@ -38163,6 +38218,7 @@
     method public android.graphics.drawable.Drawable getLogo();
     method public java.lang.CharSequence getLogoDescription();
     method public android.view.Menu getMenu();
+    method public java.lang.CharSequence getNavigationContentDescription();
     method public android.graphics.drawable.Drawable getNavigationIcon();
     method public java.lang.CharSequence getSubtitle();
     method public java.lang.CharSequence getTitle();
@@ -38188,9 +38244,11 @@
     method public void setSubtitle(int);
     method public void setSubtitle(java.lang.CharSequence);
     method public void setSubtitleTextAppearance(android.content.Context, int);
+    method public void setSubtitleTextColor(int);
     method public void setTitle(int);
     method public void setTitle(java.lang.CharSequence);
     method public void setTitleTextAppearance(android.content.Context, int);
+    method public void setTitleTextColor(int);
     method public boolean showOverflowMenu();
   }
 
@@ -38337,6 +38395,22 @@
 
 }
 
+package com.android.internal.telecomm {
+
+  public abstract interface RemoteServiceCallback implements android.os.IInterface {
+    method public abstract void onError() throws android.os.RemoteException;
+    method public abstract void onResult(java.util.List<android.content.ComponentName>, java.util.List<android.os.IBinder>) throws android.os.RemoteException;
+  }
+
+  public static abstract class RemoteServiceCallback.Stub extends android.os.Binder implements com.android.internal.telecomm.RemoteServiceCallback {
+    ctor public RemoteServiceCallback.Stub();
+    method public android.os.IBinder asBinder();
+    method public static com.android.internal.telecomm.RemoteServiceCallback asInterface(android.os.IBinder);
+    method public boolean onTransact(int, android.os.Parcel, android.os.Parcel, int) throws android.os.RemoteException;
+  }
+
+}
+
 package com.android.internal.util {
 
   public abstract interface Predicate {
@@ -48279,6 +48353,35 @@
     method public V replace(K, V);
   }
 
+  public class ConcurrentLinkedDeque extends java.util.AbstractCollection implements java.util.Deque java.io.Serializable {
+    ctor public ConcurrentLinkedDeque();
+    ctor public ConcurrentLinkedDeque(java.util.Collection<? extends E>);
+    method public void addFirst(E);
+    method public void addLast(E);
+    method public java.util.Iterator<E> descendingIterator();
+    method public E element();
+    method public E getFirst();
+    method public E getLast();
+    method public java.util.Iterator<E> iterator();
+    method public boolean offer(E);
+    method public boolean offerFirst(E);
+    method public boolean offerLast(E);
+    method public E peek();
+    method public E peekFirst();
+    method public E peekLast();
+    method public E poll();
+    method public E pollFirst();
+    method public E pollLast();
+    method public E pop();
+    method public void push(E);
+    method public E remove();
+    method public E removeFirst();
+    method public boolean removeFirstOccurrence(java.lang.Object);
+    method public E removeLast();
+    method public boolean removeLastOccurrence(java.lang.Object);
+    method public int size();
+  }
+
   public class ConcurrentLinkedQueue extends java.util.AbstractQueue implements java.util.Queue java.io.Serializable {
     ctor public ConcurrentLinkedQueue();
     ctor public ConcurrentLinkedQueue(java.util.Collection<? extends E>);
@@ -48519,6 +48622,94 @@
     method public static java.util.concurrent.ScheduledExecutorService unconfigurableScheduledExecutorService(java.util.concurrent.ScheduledExecutorService);
   }
 
+  public class ForkJoinPool extends java.util.concurrent.AbstractExecutorService {
+    ctor public ForkJoinPool();
+    ctor public ForkJoinPool(int);
+    ctor public ForkJoinPool(int, java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory, java.lang.Thread.UncaughtExceptionHandler, boolean);
+    method public boolean awaitQuiescence(long, java.util.concurrent.TimeUnit);
+    method public boolean awaitTermination(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method protected int drainTasksTo(java.util.Collection<? super java.util.concurrent.ForkJoinTask<?>>);
+    method public void execute(java.util.concurrent.ForkJoinTask<?>);
+    method public void execute(java.lang.Runnable);
+    method public int getActiveThreadCount();
+    method public boolean getAsyncMode();
+    method public java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory getFactory();
+    method public int getParallelism();
+    method public int getPoolSize();
+    method public int getQueuedSubmissionCount();
+    method public long getQueuedTaskCount();
+    method public int getRunningThreadCount();
+    method public long getStealCount();
+    method public java.lang.Thread.UncaughtExceptionHandler getUncaughtExceptionHandler();
+    method public boolean hasQueuedSubmissions();
+    method public T invoke(java.util.concurrent.ForkJoinTask<T>);
+    method public boolean isQuiescent();
+    method public boolean isShutdown();
+    method public boolean isTerminated();
+    method public boolean isTerminating();
+    method public static void managedBlock(java.util.concurrent.ForkJoinPool.ManagedBlocker) throws java.lang.InterruptedException;
+    method protected java.util.concurrent.ForkJoinTask<?> pollSubmission();
+    method public void shutdown();
+    method public java.util.List<java.lang.Runnable> shutdownNow();
+    method public java.util.concurrent.ForkJoinTask<T> submit(java.util.concurrent.ForkJoinTask<T>);
+    field public static final java.util.concurrent.ForkJoinPool.ForkJoinWorkerThreadFactory defaultForkJoinWorkerThreadFactory;
+  }
+
+  public static abstract interface ForkJoinPool.ForkJoinWorkerThreadFactory {
+    method public abstract java.util.concurrent.ForkJoinWorkerThread newThread(java.util.concurrent.ForkJoinPool);
+  }
+
+  public static abstract interface ForkJoinPool.ManagedBlocker {
+    method public abstract boolean block() throws java.lang.InterruptedException;
+    method public abstract boolean isReleasable();
+  }
+
+  public abstract class ForkJoinTask implements java.util.concurrent.Future java.io.Serializable {
+    ctor public ForkJoinTask();
+    method public static java.util.concurrent.ForkJoinTask<?> adapt(java.lang.Runnable);
+    method public static java.util.concurrent.ForkJoinTask<T> adapt(java.lang.Runnable, T);
+    method public static java.util.concurrent.ForkJoinTask<T> adapt(java.util.concurrent.Callable<? extends T>);
+    method public boolean cancel(boolean);
+    method public void complete(V);
+    method public void completeExceptionally(java.lang.Throwable);
+    method protected abstract boolean exec();
+    method public final java.util.concurrent.ForkJoinTask<V> fork();
+    method public final V get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
+    method public final V get(long, java.util.concurrent.TimeUnit) throws java.util.concurrent.ExecutionException, java.lang.InterruptedException, java.util.concurrent.TimeoutException;
+    method public final java.lang.Throwable getException();
+    method public static java.util.concurrent.ForkJoinPool getPool();
+    method public static int getQueuedTaskCount();
+    method public abstract V getRawResult();
+    method public static int getSurplusQueuedTaskCount();
+    method public static void helpQuiesce();
+    method public static boolean inForkJoinPool();
+    method public final V invoke();
+    method public static void invokeAll(java.util.concurrent.ForkJoinTask<?>, java.util.concurrent.ForkJoinTask<?>);
+    method public static void invokeAll(java.util.concurrent.ForkJoinTask<?>...);
+    method public static java.util.Collection<T> invokeAll(java.util.Collection<T>);
+    method public final boolean isCancelled();
+    method public final boolean isCompletedAbnormally();
+    method public final boolean isCompletedNormally();
+    method public final boolean isDone();
+    method public final V join();
+    method protected static java.util.concurrent.ForkJoinTask<?> peekNextLocalTask();
+    method protected static java.util.concurrent.ForkJoinTask<?> pollNextLocalTask();
+    method protected static java.util.concurrent.ForkJoinTask<?> pollTask();
+    method public final void quietlyInvoke();
+    method public final void quietlyJoin();
+    method public void reinitialize();
+    method protected abstract void setRawResult(V);
+    method public boolean tryUnfork();
+  }
+
+  public class ForkJoinWorkerThread extends java.lang.Thread {
+    ctor protected ForkJoinWorkerThread(java.util.concurrent.ForkJoinPool);
+    method public java.util.concurrent.ForkJoinPool getPool();
+    method public int getPoolIndex();
+    method protected void onStart();
+    method protected void onTermination(java.lang.Throwable);
+  }
+
   public abstract interface Future {
     method public abstract boolean cancel(boolean);
     method public abstract V get() throws java.util.concurrent.ExecutionException, java.lang.InterruptedException;
@@ -48603,6 +48794,52 @@
     method public E take() throws java.lang.InterruptedException;
   }
 
+  public class LinkedTransferQueue extends java.util.AbstractQueue implements java.io.Serializable java.util.concurrent.TransferQueue {
+    ctor public LinkedTransferQueue();
+    ctor public LinkedTransferQueue(java.util.Collection<? extends E>);
+    method public int drainTo(java.util.Collection<? super E>);
+    method public int drainTo(java.util.Collection<? super E>, int);
+    method public int getWaitingConsumerCount();
+    method public boolean hasWaitingConsumer();
+    method public java.util.Iterator<E> iterator();
+    method public boolean offer(E, long, java.util.concurrent.TimeUnit);
+    method public boolean offer(E);
+    method public E peek();
+    method public E poll(long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+    method public E poll();
+    method public void put(E);
+    method public int remainingCapacity();
+    method public int size();
+    method public E take() throws java.lang.InterruptedException;
+    method public void transfer(E) throws java.lang.InterruptedException;
+    method public boolean tryTransfer(E);
+    method public boolean tryTransfer(E, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+  }
+
+  public class Phaser {
+    ctor public Phaser();
+    ctor public Phaser(int);
+    ctor public Phaser(java.util.concurrent.Phaser);
+    ctor public Phaser(java.util.concurrent.Phaser, int);
+    method public int arrive();
+    method public int arriveAndAwaitAdvance();
+    method public int arriveAndDeregister();
+    method public int awaitAdvance(int);
+    method public int awaitAdvanceInterruptibly(int) throws java.lang.InterruptedException;
+    method public int awaitAdvanceInterruptibly(int, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException, java.util.concurrent.TimeoutException;
+    method public int bulkRegister(int);
+    method public void forceTermination();
+    method public int getArrivedParties();
+    method public java.util.concurrent.Phaser getParent();
+    method public final int getPhase();
+    method public int getRegisteredParties();
+    method public java.util.concurrent.Phaser getRoot();
+    method public int getUnarrivedParties();
+    method public boolean isTerminated();
+    method protected boolean onAdvance(int, int);
+    method public int register();
+  }
+
   public class PriorityBlockingQueue extends java.util.AbstractQueue implements java.util.concurrent.BlockingQueue java.io.Serializable {
     ctor public PriorityBlockingQueue();
     ctor public PriorityBlockingQueue(int);
@@ -48623,6 +48860,22 @@
     method public E take() throws java.lang.InterruptedException;
   }
 
+  public abstract class RecursiveAction extends java.util.concurrent.ForkJoinTask {
+    ctor public RecursiveAction();
+    method protected abstract void compute();
+    method protected final boolean exec();
+    method public final java.lang.Void getRawResult();
+    method protected final void setRawResult(java.lang.Void);
+  }
+
+  public abstract class RecursiveTask extends java.util.concurrent.ForkJoinTask {
+    ctor public RecursiveTask();
+    method protected abstract V compute();
+    method protected final boolean exec();
+    method public final V getRawResult();
+    method protected final void setRawResult(V);
+  }
+
   public class RejectedExecutionException extends java.lang.RuntimeException {
     ctor public RejectedExecutionException();
     ctor public RejectedExecutionException(java.lang.String);
@@ -48661,12 +48914,14 @@
     method protected java.util.concurrent.RunnableScheduledFuture<V> decorateTask(java.util.concurrent.Callable<V>, java.util.concurrent.RunnableScheduledFuture<V>);
     method public boolean getContinueExistingPeriodicTasksAfterShutdownPolicy();
     method public boolean getExecuteExistingDelayedTasksAfterShutdownPolicy();
+    method public boolean getRemoveOnCancelPolicy();
     method public java.util.concurrent.ScheduledFuture<?> schedule(java.lang.Runnable, long, java.util.concurrent.TimeUnit);
     method public java.util.concurrent.ScheduledFuture<V> schedule(java.util.concurrent.Callable<V>, long, java.util.concurrent.TimeUnit);
     method public java.util.concurrent.ScheduledFuture<?> scheduleAtFixedRate(java.lang.Runnable, long, long, java.util.concurrent.TimeUnit);
     method public java.util.concurrent.ScheduledFuture<?> scheduleWithFixedDelay(java.lang.Runnable, long, long, java.util.concurrent.TimeUnit);
     method public void setContinueExistingPeriodicTasksAfterShutdownPolicy(boolean);
     method public void setExecuteExistingDelayedTasksAfterShutdownPolicy(boolean);
+    method public void setRemoveOnCancelPolicy(boolean);
   }
 
   public class Semaphore implements java.io.Serializable {
@@ -48712,6 +48967,15 @@
     method public abstract java.lang.Thread newThread(java.lang.Runnable);
   }
 
+  public class ThreadLocalRandom extends java.util.Random {
+    method public static java.util.concurrent.ThreadLocalRandom current();
+    method public double nextDouble(double);
+    method public double nextDouble(double, double);
+    method public int nextInt(int, int);
+    method public long nextLong(long);
+    method public long nextLong(long, long);
+  }
+
   public class ThreadPoolExecutor extends java.util.concurrent.AbstractExecutorService {
     ctor public ThreadPoolExecutor(int, int, long, java.util.concurrent.TimeUnit, java.util.concurrent.BlockingQueue<java.lang.Runnable>);
     ctor public ThreadPoolExecutor(int, int, long, java.util.concurrent.TimeUnit, java.util.concurrent.BlockingQueue<java.lang.Runnable>, java.util.concurrent.ThreadFactory);
@@ -48799,6 +49063,14 @@
     ctor public TimeoutException(java.lang.String);
   }
 
+  public abstract interface TransferQueue implements java.util.concurrent.BlockingQueue {
+    method public abstract int getWaitingConsumerCount();
+    method public abstract boolean hasWaitingConsumer();
+    method public abstract void transfer(E) throws java.lang.InterruptedException;
+    method public abstract boolean tryTransfer(E);
+    method public abstract boolean tryTransfer(E, long, java.util.concurrent.TimeUnit) throws java.lang.InterruptedException;
+  }
+
 }
 
 package java.util.concurrent.atomic {
@@ -49008,6 +49280,7 @@
     method public final int getWaitQueueLength(java.util.concurrent.locks.AbstractQueuedLongSynchronizer.ConditionObject);
     method public final java.util.Collection<java.lang.Thread> getWaitingThreads(java.util.concurrent.locks.AbstractQueuedLongSynchronizer.ConditionObject);
     method public final boolean hasContended();
+    method public final boolean hasQueuedPredecessors();
     method public final boolean hasQueuedThreads();
     method public final boolean hasWaiters(java.util.concurrent.locks.AbstractQueuedLongSynchronizer.ConditionObject);
     method protected boolean isHeldExclusively();
@@ -49054,6 +49327,7 @@
     method public final int getWaitQueueLength(java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject);
     method public final java.util.Collection<java.lang.Thread> getWaitingThreads(java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject);
     method public final boolean hasContended();
+    method public final boolean hasQueuedPredecessors();
     method public final boolean hasQueuedThreads();
     method public final boolean hasWaiters(java.util.concurrent.locks.AbstractQueuedSynchronizer.ConditionObject);
     method protected boolean isHeldExclusively();
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index d1bea2e..d683851 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -175,10 +175,13 @@
         System.out.println("Performing full transport backup");
 
         String pkg;
+        ArrayList<String> allPkgs = new ArrayList<String>();
         while ((pkg = nextArg()) != null) {
-            System.out.println("    Package " + pkg + " ...");
+            allPkgs.add(pkg);
+        }
+        if (allPkgs.size() > 0) {
             try {
-                mBmgr.fullTransportBackup(new String[] { pkg });
+                mBmgr.fullTransportBackup(allPkgs.toArray(new String[allPkgs.size()]));
             } catch (RemoteException e) {
                 System.err.println(e.toString());
                 System.err.println(BMGR_NOT_RUNNING_ERR);
@@ -474,6 +477,7 @@
         System.err.println("       bmgr restore PACKAGE");
         System.err.println("       bmgr run");
         System.err.println("       bmgr wipe TRANSPORT PACKAGE");
+        System.err.println("       bmgr fullbackup PACKAGE...");
         System.err.println("");
         System.err.println("The 'backup' command schedules a backup pass for the named package.");
         System.err.println("Note that the backup pass will effectively be a no-op if the package");
@@ -489,11 +493,11 @@
         System.err.println("");
         System.err.println("The 'list transports' command reports the names of the backup transports");
         System.err.println("currently available on the device.  These names can be passed as arguments");
-        System.err.println("to the 'transport' and 'wipe' commands.  The currently selected transport");
+        System.err.println("to the 'transport' and 'wipe' commands.  The currently active transport");
         System.err.println("is indicated with a '*' character.");
         System.err.println("");
         System.err.println("The 'list sets' command reports the token and name of each restore set");
-        System.err.println("available to the device via the current transport.");
+        System.err.println("available to the device via the currently active transport.");
         System.err.println("");
         System.err.println("The 'transport' command designates the named transport as the currently");
         System.err.println("active one.  This setting is persistent across reboots.");
@@ -521,5 +525,8 @@
         System.err.println("erased from the given transport's storage.  The next backup operation");
         System.err.println("that the given application performs will rewrite its entire data set.");
         System.err.println("Transport names to use here are those reported by 'list transports'.");
+        System.err.println("");
+        System.err.println("The 'fullbackup' command induces a full-data stream backup for one or more");
+        System.err.println("packages.  The data is sent via the currently active transport.");
     }
 }
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index 8947550..da56a77 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -469,7 +469,10 @@
      */
     public static <T> ObjectAnimator ofFloat(T target, Property<T, Float> xProperty,
             Property<T, Float> yProperty, Path path) {
-        return ofFloat(target, xProperty.getName(), yProperty.getName(), path);
+        Keyframe[][] keyframes = PropertyValuesHolder.createKeyframes(path, false);
+        PropertyValuesHolder x = PropertyValuesHolder.ofKeyframe(xProperty, keyframes[0]);
+        PropertyValuesHolder y = PropertyValuesHolder.ofKeyframe(yProperty, keyframes[1]);
+        return ofPropertyValuesHolder(target, x, y);
     }
 
     /**
diff --git a/core/java/android/animation/StateListAnimator.java b/core/java/android/animation/StateListAnimator.java
index bc4843d..810f050 100644
--- a/core/java/android/animation/StateListAnimator.java
+++ b/core/java/android/animation/StateListAnimator.java
@@ -141,7 +141,7 @@
             return;
         }
         if (mLastMatch != null) {
-            cancel(mLastMatch);
+            cancel();
         }
         mLastMatch = match;
         if (match != null) {
@@ -151,13 +151,15 @@
 
     private void start(Tuple match) {
         match.mAnimator.setTarget(getTarget());
-        mRunningAnimator = match.mAnimator;
-        match.mAnimator.start();
+        mRunningAnimator = match.mAnimator.clone();
+        mRunningAnimator.start();
     }
 
-    private void cancel(Tuple lastMatch) {
-        lastMatch.mAnimator.cancel();
-        lastMatch.mAnimator.setTarget(null);
+    private void cancel() {
+        if (mRunningAnimator != null) {
+            mRunningAnimator.cancel();
+            mRunningAnimator = null;
+        }
     }
 
     /**
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index d0d0289..83cbaa1 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -5139,78 +5139,7 @@
             return onCreateView(name, context, attrs);
         }
         
-        String fname = attrs.getAttributeValue(null, "class");
-        TypedArray a = 
-            context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Fragment);
-        if (fname == null) {
-            fname = a.getString(com.android.internal.R.styleable.Fragment_name);
-        }
-        int id = a.getResourceId(com.android.internal.R.styleable.Fragment_id, View.NO_ID);
-        String tag = a.getString(com.android.internal.R.styleable.Fragment_tag);
-        a.recycle();
-        
-        int containerId = parent != null ? parent.getId() : 0;
-        if (containerId == View.NO_ID && id == View.NO_ID && tag == null) {
-            throw new IllegalArgumentException(attrs.getPositionDescription()
-                    + ": Must specify unique android:id, android:tag, or have a parent with an id for " + fname);
-        }
-
-        // If we restored from a previous state, we may already have
-        // instantiated this fragment from the state and should use
-        // that instance instead of making a new one.
-        Fragment fragment = id != View.NO_ID ? mFragments.findFragmentById(id) : null;
-        if (fragment == null && tag != null) {
-            fragment = mFragments.findFragmentByTag(tag);
-        }
-        if (fragment == null && containerId != View.NO_ID) {
-            fragment = mFragments.findFragmentById(containerId);
-        }
-
-        if (FragmentManagerImpl.DEBUG) Log.v(TAG, "onCreateView: id=0x"
-                + Integer.toHexString(id) + " fname=" + fname
-                + " existing=" + fragment);
-        if (fragment == null) {
-            fragment = Fragment.instantiate(this, fname);
-            fragment.mFromLayout = true;
-            fragment.mFragmentId = id != 0 ? id : containerId;
-            fragment.mContainerId = containerId;
-            fragment.mTag = tag;
-            fragment.mInLayout = true;
-            fragment.mFragmentManager = mFragments;
-            fragment.onInflate(this, attrs, fragment.mSavedFragmentState);
-            mFragments.addFragment(fragment, true);
-
-        } else if (fragment.mInLayout) {
-            // A fragment already exists and it is not one we restored from
-            // previous state.
-            throw new IllegalArgumentException(attrs.getPositionDescription()
-                    + ": Duplicate id 0x" + Integer.toHexString(id)
-                    + ", tag " + tag + ", or parent id 0x" + Integer.toHexString(containerId)
-                    + " with another fragment for " + fname);
-        } else {
-            // This fragment was retained from a previous instance; get it
-            // going now.
-            fragment.mInLayout = true;
-            // If this fragment is newly instantiated (either right now, or
-            // from last saved state), then give it the attributes to
-            // initialize itself.
-            if (!fragment.mRetaining) {
-                fragment.onInflate(this, attrs, fragment.mSavedFragmentState);
-            }
-            mFragments.moveToState(fragment);
-        }
-
-        if (fragment.mView == null) {
-            throw new IllegalStateException("Fragment " + fname
-                    + " did not create a view.");
-        }
-        if (id != 0) {
-            fragment.mView.setId(id);
-        }
-        if (fragment.mView.getTag() == null) {
-            fragment.mView.setTag(tag);
-        }
-        return fragment.mView;
+        return mFragments.onCreateView(parent, name, context, attrs);
     }
 
     /**
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 9160452..0ecead9 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -29,8 +29,6 @@
 import android.view.Window;
 
 import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
 
 /**
  * Helper class for building an options Bundle that can be used with
@@ -398,14 +396,14 @@
                 if (sharedElementName == null) {
                     throw new IllegalArgumentException("Shared element name must not be null");
                 }
-                String viewName = sharedElement.first.getViewName();
-                if (viewName == null) {
+                String name = sharedElement.first.getTransitionName();
+                if (name == null) {
                     throw new IllegalArgumentException("Shared elements must have non-null " +
-                            "viewNames");
+                            "transitionNames");
                 }
 
                 names.add(sharedElementName);
-                mappedNames.add(viewName);
+                mappedNames.add(name);
             }
         }
 
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index fa9b1e3..c351cd5 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -281,7 +281,7 @@
     public ArrayList<String> getMappedNames() {
         ArrayList<String> names = new ArrayList<String>(mSharedElements.size());
         for (int i = 0; i < mSharedElements.size(); i++) {
-            names.add(mSharedElements.get(i).getViewName());
+            names.add(mSharedElements.get(i).getTransitionName());
         }
         return names;
     }
@@ -358,9 +358,9 @@
                 String name = mAllSharedElementNames.get(i);
                 View sharedElement = sharedElements.get(name);
                 if (sharedElement != null) {
-                    if (sharedElement.getViewName() == null) {
+                    if (sharedElement.getTransitionName() == null) {
                         throw new IllegalArgumentException("Shared elements must have " +
-                                "non-null viewNames");
+                                "non-null transitionNames");
                     }
                     mSharedElementNames.add(name);
                     mSharedElements.add(sharedElement);
@@ -494,7 +494,7 @@
                 if (bitmap != null) {
                     snapshot.setBackground(new BitmapDrawable(resources, bitmap));
                 }
-                snapshot.setViewName(name);
+                snapshot.setTransitionName(name);
                 setSharedElementState(snapshot, name, state, parentLoc);
                 snapshots.add(snapshot);
             }
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 22b36f3..13b922c 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -48,11 +48,13 @@
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
+import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.view.Display;
@@ -1490,6 +1492,15 @@
         }
     }
 
+    /**
+     * @hide
+     */
+    @Override
+    public Bitmap getUserIcon(int userId) {
+        UserManager um = UserManager.get(mContext);
+        return um.getUserIcon(userId);
+    }
+
     private final ContextImpl mContext;
     private final IPackageManager mPM;
 
diff --git a/core/java/android/app/BackStackRecord.java b/core/java/android/app/BackStackRecord.java
index 01a388f..4433a3a 100644
--- a/core/java/android/app/BackStackRecord.java
+++ b/core/java/android/app/BackStackRecord.java
@@ -581,13 +581,13 @@
 
     @Override
     public FragmentTransaction setSharedElement(View sharedElement, String name) {
-        String viewName = sharedElement.getViewName();
-        if (viewName == null) {
-            throw new IllegalArgumentException("Unique viewNames are required for all" +
+        String transitionName = sharedElement.getTransitionName();
+        if (transitionName == null) {
+            throw new IllegalArgumentException("Unique transitionNames are required for all" +
                     " sharedElements");
         }
         mSharedElementSourceNames = new ArrayList<String>(1);
-        mSharedElementSourceNames.add(viewName);
+        mSharedElementSourceNames.add(transitionName);
 
         mSharedElementTargetNames = new ArrayList<String>(1);
         mSharedElementTargetNames.add(name);
@@ -603,12 +603,12 @@
             ArrayList<String> sourceNames = new ArrayList<String>(sharedElements.length);
             ArrayList<String> targetNames = new ArrayList<String>(sharedElements.length);
             for (int i = 0; i < sharedElements.length; i++) {
-                String viewName = sharedElements[i].first.getViewName();
-                if (viewName == null) {
-                    throw new IllegalArgumentException("Unique viewNames are required for all" +
-                            " sharedElements");
+                String transitionName = sharedElements[i].first.getTransitionName();
+                if (transitionName == null) {
+                    throw new IllegalArgumentException("Unique transitionNames are required for all"
+                            + " sharedElements");
                 }
-                sourceNames.add(viewName);
+                sourceNames.add(transitionName);
                 targetNames.add(sharedElements[i].second);
             }
             mSharedElementSourceNames = sourceNames;
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 6c0d379..2ff3d57 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -23,6 +23,7 @@
 import android.content.Intent;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -1104,7 +1105,15 @@
      * inflation.  Maybe this should become a public API. Note sure.
      */
     public LayoutInflater getLayoutInflater(Bundle savedInstanceState) {
-        return mActivity.getLayoutInflater();
+        // Newer platform versions use the child fragment manager's LayoutInflaterFactory.
+        if (mActivity.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.L) {
+            LayoutInflater result = mActivity.getLayoutInflater().cloneInContext(mActivity);
+            getChildFragmentManager(); // Init if needed; use raw implementation below.
+            result.setPrivateFactory(mChildFragmentManager.getLayoutInflaterFactory());
+            return result;
+        } else {
+            return mActivity.getLayoutInflater();
+        }
     }
     
     /**
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index b8f1962..a97fa65 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -19,6 +19,7 @@
 import android.animation.Animator;
 import android.animation.AnimatorInflater;
 import android.animation.AnimatorListenerAdapter;
+import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.os.Bundle;
@@ -27,11 +28,13 @@
 import android.os.Looper;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.AttributeSet;
 import android.util.DebugUtils;
 import android.util.Log;
 import android.util.LogWriter;
 import android.util.SparseArray;
 import android.util.SuperNotCalledException;
+import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuItem;
@@ -397,7 +400,7 @@
 /**
  * Container for fragments associated with an activity.
  */
-final class FragmentManagerImpl extends FragmentManager {
+final class FragmentManagerImpl extends FragmentManager implements LayoutInflater.Factory2 {
     static boolean DEBUG = false;
     static final String TAG = "FragmentManager";
     
@@ -432,7 +435,7 @@
     boolean mDestroyed;
     String mNoTransactionsBecause;
     boolean mHavePendingDeferredStart;
-    
+
     // Temporary vars for state save and restore.
     Bundle mStateBundle = null;
     SparseArray<Parcelable> mStateArray = null;
@@ -2052,4 +2055,100 @@
         }
         return animAttr;
     }
+
+    @Override
+    public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
+        if (!"fragment".equals(name)) {
+            return null;
+        }
+
+        String fname = attrs.getAttributeValue(null, "class");
+        TypedArray a =
+                context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.Fragment);
+        if (fname == null) {
+            fname = a.getString(com.android.internal.R.styleable.Fragment_name);
+        }
+        int id = a.getResourceId(com.android.internal.R.styleable.Fragment_id, View.NO_ID);
+        String tag = a.getString(com.android.internal.R.styleable.Fragment_tag);
+        a.recycle();
+
+        int containerId = parent != null ? parent.getId() : 0;
+        if (containerId == View.NO_ID && id == View.NO_ID && tag == null) {
+            throw new IllegalArgumentException(attrs.getPositionDescription()
+                    + ": Must specify unique android:id, android:tag, or have a parent with"
+                    + " an id for " + fname);
+        }
+
+        // If we restored from a previous state, we may already have
+        // instantiated this fragment from the state and should use
+        // that instance instead of making a new one.
+        Fragment fragment = id != View.NO_ID ? findFragmentById(id) : null;
+        if (fragment == null && tag != null) {
+            fragment = findFragmentByTag(tag);
+        }
+        if (fragment == null && containerId != View.NO_ID) {
+            fragment = findFragmentById(containerId);
+        }
+
+        if (FragmentManagerImpl.DEBUG) Log.v(TAG, "onCreateView: id=0x"
+                + Integer.toHexString(id) + " fname=" + fname
+                + " existing=" + fragment);
+        if (fragment == null) {
+            fragment = Fragment.instantiate(context, fname);
+            fragment.mFromLayout = true;
+            fragment.mFragmentId = id != 0 ? id : containerId;
+            fragment.mContainerId = containerId;
+            fragment.mTag = tag;
+            fragment.mInLayout = true;
+            fragment.mFragmentManager = this;
+            fragment.onInflate(mActivity, attrs, fragment.mSavedFragmentState);
+            addFragment(fragment, true);
+        } else if (fragment.mInLayout) {
+            // A fragment already exists and it is not one we restored from
+            // previous state.
+            throw new IllegalArgumentException(attrs.getPositionDescription()
+                    + ": Duplicate id 0x" + Integer.toHexString(id)
+                    + ", tag " + tag + ", or parent id 0x" + Integer.toHexString(containerId)
+                    + " with another fragment for " + fname);
+        } else {
+            // This fragment was retained from a previous instance; get it
+            // going now.
+            fragment.mInLayout = true;
+            // If this fragment is newly instantiated (either right now, or
+            // from last saved state), then give it the attributes to
+            // initialize itself.
+            if (!fragment.mRetaining) {
+                fragment.onInflate(mActivity, attrs, fragment.mSavedFragmentState);
+            }
+        }
+
+        // If we haven't finished entering the CREATED state ourselves yet,
+        // push the inflated child fragment along.
+        if (mCurState < Fragment.CREATED && fragment.mFromLayout) {
+            moveToState(fragment, Fragment.CREATED, 0, 0, false);
+        } else {
+            moveToState(fragment);
+        }
+
+        if (fragment.mView == null) {
+            throw new IllegalStateException("Fragment " + fname
+                    + " did not create a view.");
+        }
+        if (id != 0) {
+            fragment.mView.setId(id);
+        }
+        if (fragment.mView.getTag() == null) {
+            fragment.mView.setTag(tag);
+        }
+        return fragment.mView;
+    }
+
+    @Override
+    public View onCreateView(String name, Context context, AttributeSet attrs) {
+        return null;
+    }
+
+    LayoutInflater.Factory2 getLayoutInflaterFactory() {
+        return this;
+    }
 }
diff --git a/core/java/android/app/FragmentTransaction.java b/core/java/android/app/FragmentTransaction.java
index 7479ecd..b6ea3c3 100644
--- a/core/java/android/app/FragmentTransaction.java
+++ b/core/java/android/app/FragmentTransaction.java
@@ -184,10 +184,10 @@
     /**
      * Used with {@link #setCustomTransition(int, int)} to map a View from a removed or hidden
      * Fragment to a View from a shown or added Fragment.
-     * <var>sharedElement</var> must have a unique viewName in the View hierarchy.
+     * <var>sharedElement</var> must have a unique transitionName in the View hierarchy.
      * @param sharedElement A View in a disappearing Fragment to match with a View in an
      *                      appearing Fragment.
-     * @param name The viewName for a View in an appearing Fragment to match to the shared
+     * @param name The transitionName for a View in an appearing Fragment to match to the shared
      *             element.
      */
     public abstract FragmentTransaction setSharedElement(View sharedElement, String name);
@@ -195,8 +195,8 @@
     /**
      * Used with {@link #setCustomTransition(int, int)} to map multiple Views from removed or hidden
      * Fragments to a Views from a shown or added Fragments. Views in
-     * <var>sharedElements</var> must have unique viewNames in the View hierarchy.
-     * @param sharedElements Pairs of Views in disappearing Fragments to viewNames in
+     * <var>sharedElements</var> must have unique transitionNames in the View hierarchy.
+     * @param sharedElements Pairs of Views in disappearing Fragments to transitionNames in
      *                       appearing Fragments.
      */
     public abstract FragmentTransaction setSharedElements(Pair<View, String>... sharedElements);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index b94fd41..84f7e5f 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -91,7 +91,10 @@
      * Use the default notification sound. This will ignore any given
      * {@link #sound}.
      *
-
+     * <p>
+     * A notification that is noisy is more likely to be presented as a heads-up notification.
+     * </p>
+     *
      * @see #defaults
      */
 
@@ -102,6 +105,10 @@
      * {@link #vibrate}. Using phone vibration requires the
      * {@link android.Manifest.permission#VIBRATE VIBRATE} permission.
      *
+     * <p>
+     * A notification that vibrates is more likely to be presented as a heads-up notification.
+     * </p>
+     *
      * @see #defaults
      */
 
@@ -195,6 +202,11 @@
     /**
      * An intent to launch instead of posting the notification to the status bar.
      *
+     * <p>
+     * The system UI may choose to display a heads-up notification, instead of
+     * launching this intent, while the user is using the device.
+     * </p>
+     *
      * @see Notification.Builder#setFullScreenIntent
      */
     public PendingIntent fullScreenIntent;
@@ -228,9 +240,10 @@
 
     /**
      * @hide
-     * A medium-format version of {@link #contentView}, giving the Notification an
-     * opportunity to add action buttons to contentView. The system UI may
-     * choose to show this as a popup notification at its discretion.
+     * A medium-format version of {@link #contentView}, providing the Notification an
+     * opportunity to add action buttons to contentView. At its discretion, the system UI may
+     * choose to show this as a heads-up notification, which will pop up so the user can see
+     * it without leaving their current activity.
      */
     public RemoteViews headsUpContentView;
 
@@ -243,6 +256,10 @@
      * The sound to play.
      *
      * <p>
+     * A notification that is noisy is more likely to be presented as a heads-up notification.
+     * </p>
+     *
+     * <p>
      * To play the default notification sound, see {@link #defaults}.
      * </p>
      */
@@ -269,6 +286,10 @@
      * To vibrate the default pattern, see {@link #defaults}.
      * </p>
      *
+     * <p>
+     * A notification that vibrates is more likely to be presented as a heads-up notification.
+     * </p>
+     *
      * @see android.os.Vibrator#vibrate(long[],int)
      */
     public long[] vibrate;
@@ -443,6 +464,12 @@
      * situations, while the user might be interrupted for a higher-priority notification. The
      * system will make a determination about how to interpret this priority when presenting
      * the notification.
+     *
+     * <p>
+     * A notification that is at least {@link #PRIORITY_HIGH} is more likely to be presented
+     * as a heads-up notification.
+     * </p>
+     *
      */
     @Priority
     public int priority;
@@ -724,7 +751,8 @@
     public static final String EXTRA_SCORE_MODIFIED = "android.scoreModified";
 
     /**
-     * Not used.
+     * {@link #extras} key: used to provide hints about the appropriateness of
+     * displaying this notification as a heads-up notification.
      * @hide
      */
     public static final String EXTRA_AS_HEADS_UP = "headsup";
@@ -755,19 +783,27 @@
     public static final String EXTRA_MEDIA_SESSION = "android.mediaSession";
 
     /**
-     * Value for {@link #EXTRA_AS_HEADS_UP}.
+     * Value for {@link #EXTRA_AS_HEADS_UP} that indicates this notification should not be
+     * displayed in the heads up space.
+     *
+     * <p>
+     * If this notification has a {@link #fullScreenIntent}, then it will always launch the
+     * full-screen intent when posted.
+     * </p>
      * @hide
      */
     public static final int HEADS_UP_NEVER = 0;
 
     /**
-     * Default value for {@link #EXTRA_AS_HEADS_UP}.
+     * Default value for {@link #EXTRA_AS_HEADS_UP} that indicates this notification may be
+     * displayed as a heads up.
      * @hide
      */
     public static final int HEADS_UP_ALLOWED = 1;
 
     /**
-     * Value for {@link #EXTRA_AS_HEADS_UP}.
+     * Value for {@link #EXTRA_AS_HEADS_UP} that indicates this notification is a
+     * good candidate for display as a heads up.
      * @hide
      */
     public static final int HEADS_UP_REQUESTED = 2;
@@ -1903,6 +1939,11 @@
          * to turn it off and use a normal notification, as this can be extremely
          * disruptive.
          *
+         * <p>
+         * The system UI may choose to display a heads-up notification, instead of
+         * launching this intent, while the user is using the device.
+         * </p>
+         *
          * @param intent The pending intent to launch.
          * @param highPriority Passing true will cause this notification to be sent
          *          even if other notifications are suppressed.
@@ -1958,6 +1999,10 @@
          *
          * It will be played on the {@link #STREAM_DEFAULT default stream} for notifications.
          *
+         * <p>
+         * A notification that is noisy is more likely to be presented as a heads-up notification.
+         * </p>
+         *
          * @see Notification#sound
          */
         public Builder setSound(Uri sound) {
@@ -1971,6 +2016,10 @@
          *
          * See {@link android.media.AudioManager} for the <code>STREAM_</code> constants.
          *
+         * <p>
+         * A notification that is noisy is more likely to be presented as a heads-up notification.
+         * </p>
+         *
          * @see Notification#sound
          */
         public Builder setSound(Uri sound, int streamType) {
@@ -1982,11 +2031,13 @@
         /**
          * Set the vibration pattern to use.
          *
-
          * See {@link android.os.Vibrator#vibrate(long[], int)} for a discussion of the
          * <code>pattern</code> parameter.
          *
-
+         * <p>
+         * A notification that vibrates is more likely to be presented as a heads-up notification.
+         * </p>
+         *
          * @see Notification#vibrate
          */
         public Builder setVibrate(long[] pattern) {
diff --git a/core/java/android/app/SharedElementListener.java b/core/java/android/app/SharedElementListener.java
index e03e42e..14fbfab 100644
--- a/core/java/android/app/SharedElementListener.java
+++ b/core/java/android/app/SharedElementListener.java
@@ -108,7 +108,7 @@
      * @param names The names of all shared elements transferred from the calling Activity
      *              to the started Activity.
      * @param sharedElements The mapping of shared element names to Views. The best guess
-     *                       will be filled into sharedElements based on the View names.
+     *                       will be filled into sharedElements based on the transitionNames.
      */
     public void remapSharedElements(List<String> names, Map<String, View> sharedElements) {}
 }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index df6be8b..4351f9d 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -2349,7 +2349,7 @@
      * <p>Any packages that shares uid with an allowed package will also be allowed
      * to activate lock task.
      *
-     * This function can only be called by the device owner or the profile owner.
+     * This function can only be called by the device owner.
      * @param packages The list of packages allowed to enter lock task mode
      *
      * @see Activity#startLockTask()
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index e757b56..720315d 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -29,6 +29,7 @@
 import android.content.pm.PackageParser.PackageParserException;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
+import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.Environment;
@@ -197,6 +198,12 @@
     public static final int MATCH_DEFAULT_ONLY   = 0x00010000;
 
     /**
+     * Resolution and querying flag: do not resolve intents cross-profile.
+     * @hide
+     */
+    public static final int NO_CROSS_PROFILE = 0x00020000;
+
+    /**
      * Flag for {@link addCrossProfileIntentFilter}: if the cross-profile intent has been set by the
      * profile owner.
      * @hide
@@ -2309,6 +2316,7 @@
      * @see #MATCH_DEFAULT_ONLY
      * @see #GET_INTENT_FILTERS
      * @see #GET_RESOLVED_FILTER
+     * @see #NO_CROSS_PROFILE
      * @hide
      */
     public abstract List<ResolveInfo> queryIntentActivitiesAsUser(Intent intent,
@@ -3618,4 +3626,8 @@
      */
     public abstract void addCrossProfileIntentsForPackage(String packageName,
             int sourceUserId, int targetUserId);
+    /**
+     * @hide
+     */
+    public abstract Bitmap getUserIcon(int userId);
 }
diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java
index 1ff41c0..1f9d60c 100644
--- a/core/java/android/content/pm/ResolveInfo.java
+++ b/core/java/android/content/pm/ResolveInfo.java
@@ -19,8 +19,11 @@
 import android.content.ComponentName;
 import android.content.IntentFilter;
 import android.graphics.drawable.Drawable;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.Printer;
 import android.util.Slog;
@@ -127,6 +130,18 @@
     public String resolvePackageName;
 
     /**
+     * If not equal to UserHandle.USER_CURRENT, then the intent will be forwarded to this user.
+     * @hide
+     */
+    public int targetUserId;
+
+    /**
+     * If true, then loadIcon will return the icon of the target user.
+     * @hide
+     */
+    public boolean showTargetUserIcon;
+
+    /**
      * @hide Target comes from system process?
      */
     public boolean system;
@@ -202,6 +217,10 @@
                 return dr;
             }
         }
+        if (showTargetUserIcon) {
+            Bitmap bm = pm.getUserIcon(targetUserId);
+            return new BitmapDrawable(bm);
+        }
         return ci.loadIcon(pm);
     }
     
@@ -215,7 +234,9 @@
     public final int getIconResource() {
         if (icon != 0) return icon;
         final ComponentInfo ci = getComponentInfo();
-        if (ci != null) return ci.getIconResource();
+        if (ci != null && !showTargetUserIcon) {
+            return ci.getIconResource();
+        }
         return 0;
     }
 
@@ -250,6 +271,7 @@
     }
     
     public ResolveInfo() {
+        targetUserId = UserHandle.USER_CURRENT;
     }
 
     public ResolveInfo(ResolveInfo orig) {
@@ -266,6 +288,7 @@
         icon = orig.icon;
         resolvePackageName = orig.resolvePackageName;
         system = orig.system;
+        targetUserId = orig.targetUserId;
     }
 
     public String toString() {
@@ -285,6 +308,13 @@
         }
         sb.append(" m=0x");
         sb.append(Integer.toHexString(match));
+        if (targetUserId != UserHandle.USER_CURRENT) {
+            sb.append(" targetUserId=");
+            sb.append(targetUserId);
+        }
+        if (showTargetUserIcon) {
+            sb.append(" [showTargetUserIcon]");
+        }
         sb.append('}');
         return sb.toString();
     }
@@ -320,6 +350,8 @@
         TextUtils.writeToParcel(nonLocalizedLabel, dest, parcelableFlags);
         dest.writeInt(icon);
         dest.writeString(resolvePackageName);
+        dest.writeInt(targetUserId);
+        dest.writeInt(showTargetUserIcon ? 1 : 0);
         dest.writeInt(system ? 1 : 0);
     }
 
@@ -363,6 +395,8 @@
                 = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
         icon = source.readInt();
         resolvePackageName = source.readString();
+        targetUserId = source.readInt();
+        showTargetUserIcon = source.readInt() != 0;
         system = source.readInt() != 0;
     }
     
@@ -374,6 +408,13 @@
         }
 
         public final int compare(ResolveInfo a, ResolveInfo b) {
+            // We want to put the one targeted to another user at the end of the dialog.
+            if (a.targetUserId != UserHandle.USER_CURRENT) {
+                return 1;
+            }
+            if (b.targetUserId != UserHandle.USER_CURRENT) {
+                return -1;
+            }
             CharSequence  sa = a.loadLabel(mPM);
             if (sa == null) sa = a.activityInfo.name;
             CharSequence  sb = b.loadLabel(mPM);
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
index abd69c1..03dd354 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -17,7 +17,9 @@
 package android.hardware.camera2.legacy;
 
 import android.hardware.Camera;
+import android.hardware.Camera.CameraInfo;
 import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.ICameraDeviceCallbacks;
 import android.hardware.camera2.ICameraDeviceUser;
@@ -25,7 +27,9 @@
 import android.hardware.camera2.impl.CameraMetadataNative;
 import android.hardware.camera2.utils.CameraBinderDecorator;
 import android.hardware.camera2.utils.CameraRuntimeException;
+import android.os.ConditionVariable;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.RemoteException;
 import android.util.Log;
 import android.util.SparseArray;
@@ -33,7 +37,6 @@
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * Compatibility implementation of the Camera2 API binder interface.
@@ -53,6 +56,7 @@
     private static final String TAG = "CameraDeviceUserShim";
 
     private static final boolean DEBUG = Log.isLoggable(LegacyCameraDevice.DEBUG_PROP, Log.DEBUG);
+    private static final int OPEN_CAMERA_TIMEOUT_MS = 5000; // 5 sec (same as api1 cts timeout)
 
     private final LegacyCameraDevice mLegacyDevice;
 
@@ -60,29 +64,143 @@
     private int mSurfaceIdCounter;
     private boolean mConfiguring;
     private final SparseArray<Surface> mSurfaces;
+    private final CameraCharacteristics mCameraCharacteristics;
+    private final CameraLooper mCameraInit;
 
-    protected CameraDeviceUserShim(int cameraId, LegacyCameraDevice legacyCamera) {
+    protected CameraDeviceUserShim(int cameraId, LegacyCameraDevice legacyCamera,
+            CameraCharacteristics characteristics, CameraLooper cameraInit) {
         mLegacyDevice = legacyCamera;
         mConfiguring = false;
         mSurfaces = new SparseArray<Surface>();
+        mCameraCharacteristics = characteristics;
+        mCameraInit = cameraInit;
 
         mSurfaceIdCounter = 0;
     }
 
+    /**
+     * Create a separate looper/thread for the camera to run on; open the camera.
+     *
+     * <p>Since the camera automatically latches on to the current thread's looper,
+     * it's important that we have our own thread with our own looper to guarantee
+     * that the camera callbacks get correctly posted to our own thread.</p>
+     */
+    private static class CameraLooper implements Runnable, AutoCloseable {
+        private final int mCameraId;
+        private Looper mLooper;
+        private volatile int mInitErrors;
+        private final Camera mCamera = Camera.openUninitialized();
+        private final ConditionVariable mStartDone = new ConditionVariable();
+        private final Thread mThread;
+
+        /**
+         * Spin up a new thread, immediately open the camera in the background.
+         *
+         * <p>Use {@link #waitForOpen} to block until the camera is finished opening.</p>
+         *
+         * @param cameraId numeric camera Id
+         *
+         * @see #waitForOpen
+         */
+        public CameraLooper(int cameraId) {
+            mCameraId = cameraId;
+
+            mThread = new Thread(this);
+            mThread.start();
+        }
+
+        public Camera getCamera() {
+            return mCamera;
+        }
+
+        @Override
+        public void run() {
+            // Set up a looper to be used by camera.
+            Looper.prepare();
+
+            // Save the looper so that we can terminate this thread
+            // after we are done with it.
+            mLooper = Looper.myLooper();
+            mInitErrors = mCamera.cameraInitUnspecified(mCameraId);
+
+            mStartDone.open();
+            Looper.loop();  // Blocks forever until #close is called.
+        }
+
+        /**
+         * Quit the looper safely; then join until the thread shuts down.
+         */
+        @Override
+        public void close() {
+            if (mLooper == null) {
+                return;
+            }
+
+            mLooper.quitSafely();
+            try {
+                mThread.join();
+            } catch (InterruptedException e) {
+                throw new AssertionError(e);
+            }
+
+            mLooper = null;
+        }
+
+        /**
+         * Block until the camera opens; then return its initialization error code (if any).
+         *
+         * @param timeoutMs timeout in milliseconds
+         *
+         * @return int error code
+         *
+         * @throws CameraRuntimeException if the camera open times out with ({@code CAMERA_ERROR})
+         */
+        public int waitForOpen(int timeoutMs) {
+            // Block until the camera is open asynchronously
+            if (!mStartDone.block(timeoutMs)) {
+                Log.e(TAG, "waitForOpen - Camera failed to open after timeout of "
+                        + OPEN_CAMERA_TIMEOUT_MS + " ms");
+                try {
+                    mCamera.release();
+                } catch (RuntimeException e) {
+                    Log.e(TAG, "connectBinderShim - Failed to release camera after timeout ", e);
+                }
+
+                throw new CameraRuntimeException(CameraAccessException.CAMERA_ERROR);
+            }
+
+            return mInitErrors;
+        }
+    }
+
     public static CameraDeviceUserShim connectBinderShim(ICameraDeviceCallbacks callbacks,
                                                          int cameraId) {
         if (DEBUG) {
             Log.d(TAG, "Opening shim Camera device");
         }
-        // TODO: Move open/init into LegacyCameraDevice thread when API is switched to async.
-        Camera legacyCamera = Camera.openUninitialized();
-        int initErrors = legacyCamera.cameraInitUnspecified(cameraId);
+
+        /*
+         * Put the camera open on a separate thread with its own looper; otherwise
+         * if the main thread is used then the callbacks might never get delivered
+         * (e.g. in CTS which run its own default looper only after tests)
+         */
+
+        CameraLooper init = new CameraLooper(cameraId);
+
+        // TODO: Make this async instead of blocking
+        int initErrors = init.waitForOpen(OPEN_CAMERA_TIMEOUT_MS);
+        Camera legacyCamera = init.getCamera();
 
         // Check errors old HAL initialization
         CameraBinderDecorator.throwOnError(initErrors);
 
+        CameraInfo info = new CameraInfo();
+        Camera.getCameraInfo(cameraId, info);
+
+        CameraCharacteristics characteristics =
+                LegacyMetadataMapper.createCharacteristics(legacyCamera.getParameters(), info);
         LegacyCameraDevice device = new LegacyCameraDevice(cameraId, legacyCamera, callbacks);
-        return new CameraDeviceUserShim(cameraId, device);
+        return new CameraDeviceUserShim(cameraId, device, characteristics, init);
     }
 
     @Override
@@ -90,7 +208,12 @@
         if (DEBUG) {
             Log.d(TAG, "disconnect called.");
         }
-        mLegacyDevice.close();
+
+        try {
+            mLegacyDevice.close();
+        } finally {
+            mCameraInit.close();
+        }
     }
 
     @Override
@@ -218,8 +341,17 @@
         if (DEBUG) {
             Log.d(TAG, "createDefaultRequest called.");
         }
-        // TODO: implement createDefaultRequest.
-        Log.e(TAG, "createDefaultRequest unimplemented.");
+
+        CameraMetadataNative template;
+        try {
+            template =
+                    LegacyMetadataMapper.createRequestTemplate(mCameraCharacteristics, templateId);
+        } catch (IllegalArgumentException e) {
+            Log.e(TAG, "createDefaultRequest - invalid templateId specified");
+            return CameraBinderDecorator.BAD_VALUE;
+        }
+
+        request.swap(template);
         return CameraBinderDecorator.NO_ERROR;
     }
 
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index cb951b3..b6264dc 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -29,12 +29,14 @@
 import android.os.HandlerThread;
 import android.os.RemoteException;
 import android.util.Log;
+import android.util.Size;
 import android.view.Surface;
 
 import java.util.ArrayList;
 import java.util.List;
 
 import static android.hardware.camera2.utils.CameraBinderDecorator.*;
+import static com.android.internal.util.Preconditions.*;
 
 /**
  * This class emulates the functionality of a Camera2 device using a the old Camera class.
@@ -367,9 +369,27 @@
         }
     }
 
+    /**
+     * Query the surface for its currently configured default buffer size.
+     * @param surface a non-{@code null} {@code Surface}
+     * @return the width and height of the surface
+     *
+     * @throws NullPointerException if the {@code surface} was {@code null}
+     * @throws IllegalStateException if the {@code surface} was invalid
+     */
+    static Size getSurfaceSize(Surface surface) {
+        checkNotNull(surface);
+
+        int[] dimens = new int[2];
+        nativeDetectSurfaceDimens(surface, /*out*/dimens);
+
+        return new Size(dimens[0], dimens[1]);
+    }
+
     protected static native int nativeDetectSurfaceType(Surface surface);
 
-    protected static native void nativeDetectSurfaceDimens(Surface surface, int[] dimens);
+    protected static native void nativeDetectSurfaceDimens(Surface surface,
+            /*out*/int[/*2*/] dimens);
 
     protected static native void nativeConfigureSurface(Surface surface, int width, int height,
                                                         int pixelFormat);
diff --git a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
index 1cde2c4..f702556 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyMetadataMapper.java
@@ -21,6 +21,8 @@
 import android.hardware.Camera.CameraInfo;
 import android.hardware.Camera.Size;
 import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CameraMetadata;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureResult;
 import android.hardware.camera2.impl.CameraMetadataNative;
@@ -32,6 +34,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Objects;
 
 import static com.android.internal.util.Preconditions.*;
 import static android.hardware.camera2.CameraCharacteristics.*;
@@ -56,6 +59,42 @@
     private static final long APPROXIMATE_JPEG_ENCODE_TIME = 600; // ms
     private static final long NS_PER_MS = 1000000;
 
+    /*
+     * Development hijinks: Lie about not supporting certain capabilities
+     *
+     * - Unblock some CTS tests from running whose main intent is not the metadata itself
+     *
+     * TODO: Remove these constants and strip out any code that previously relied on them
+     * being set to true.
+     */
+    private static final boolean LIE_ABOUT_FLASH = true;
+    private static final boolean LIE_ABOUT_AE = true;
+    private static final boolean LIE_ABOUT_AF = true;
+    private static final boolean LIE_ABOUT_AWB = true;
+
+    /**
+     * Create characteristics for a legacy device by mapping the {@code parameters}
+     * and {@code info}
+     *
+     * @param parameters A non-{@code null} parameters set
+     * @param info Camera info with camera facing direction and angle of orientation
+     *
+     * @return static camera characteristics for a camera device
+     *
+     * @throws NullPointerException if any of the args were {@code null}
+     */
+    public static CameraCharacteristics createCharacteristics(Camera.Parameters parameters,
+            CameraInfo info) {
+        checkNotNull(parameters, "parameters must not be null");
+        checkNotNull(info, "info must not be null");
+
+        String paramStr = parameters.flatten();
+        android.hardware.CameraInfo outerInfo = new android.hardware.CameraInfo();
+        outerInfo.info = info;
+
+        return createCharacteristics(paramStr, outerInfo);
+    }
+
     /**
      * Create characteristics for a legacy device by mapping the {@code parameters}
      * and {@code info}
@@ -99,7 +138,8 @@
     private static void mapCameraParameters(CameraMetadataNative m, Camera.Parameters p) {
         m.set(INFO_SUPPORTED_HARDWARE_LEVEL, INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED);
         mapStreamConfigs(m, p);
-        mapAeConfig(m, p);
+        mapControlAe(m, p);
+        mapControlAwb(m, p);
         mapCapabilities(m, p);
         mapLens(m, p);
         mapFlash(m, p);
@@ -164,8 +204,10 @@
     }
 
     @SuppressWarnings({"unchecked"})
-    private static void mapAeConfig(CameraMetadataNative m, Camera.Parameters p) {
-
+    private static void mapControlAe(CameraMetadataNative m, Camera.Parameters p) {
+        /*
+         * control.aeAvailableTargetFpsRanges
+         */
         List<int[]> fpsRanges = p.getSupportedPreviewFpsRange();
         if (fpsRanges == null) {
             throw new AssertionError("Supported FPS ranges cannot be null.");
@@ -182,6 +224,10 @@
         }
         m.set(CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, ranges);
 
+        /*
+         * control.aeAvailableAntiBandingModes
+         */
+
         List<String> antiBandingModes = p.getSupportedAntibanding();
         int antiBandingModesSize = antiBandingModes.size();
         if (antiBandingModesSize > 0) {
@@ -198,6 +244,49 @@
             }
             m.set(CONTROL_AE_AVAILABLE_ANTIBANDING_MODES, Arrays.copyOf(modes, j));
         }
+
+        /*
+         * control.aeAvailableModes
+         */
+        List<String> flashModes = p.getSupportedFlashModes();
+
+        String[] flashModeStrings = new String[] {
+                Camera.Parameters.FLASH_MODE_AUTO,
+                Camera.Parameters.FLASH_MODE_ON,
+                Camera.Parameters.FLASH_MODE_RED_EYE,
+                // Map these manually
+                Camera.Parameters.FLASH_MODE_TORCH,
+                Camera.Parameters.FLASH_MODE_OFF,
+        };
+        int[] flashModeInts = new int[] {
+                CONTROL_AE_MODE_ON,
+                CONTROL_AE_MODE_ON_AUTO_FLASH,
+                CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE
+        };
+        int[] aeAvail = convertStringListToIntArray(flashModes, flashModeStrings, flashModeInts);
+
+        // No flash control -> AE is always on
+        if (aeAvail == null || aeAvail.length == 0) {
+            aeAvail = new int[] {
+                    CONTROL_AE_MODE_ON
+            };
+        }
+
+        if (LIE_ABOUT_FLASH) {
+            // TODO: Remove this branch
+            Log.w(TAG, "mapControlAe - lying; saying we only support CONTROL_AE_MODE_ON");
+            aeAvail = new int[] {
+                    CONTROL_AE_MODE_ON
+            };
+        }
+
+        m.set(CONTROL_AE_AVAILABLE_MODES, aeAvail);
+    }
+
+    private static void mapControlAwb(CameraMetadataNative m, Camera.Parameters p) {
+        if (!LIE_ABOUT_AWB) {
+            throw new AssertionError("Not implemented yet");
+        }
     }
 
     private static void mapCapabilities(CameraMetadataNative m, Camera.Parameters p) {
@@ -226,6 +315,12 @@
             }
         }
 
+        if (LIE_ABOUT_FLASH && flashAvailable) {
+            // TODO: remove this branch
+            Log.w(TAG, "mapFlash - lying; saying we never support flash");
+            flashAvailable = false;
+        }
+
         m.set(FLASH_INFO_AVAILABLE, flashAvailable);
     }
 
@@ -320,7 +415,52 @@
                                                       CaptureRequest request,
                                                       long timestamp) {
         CameraMetadataNative result = new CameraMetadataNative();
+
+        /*
+         * control
+         */
+        // control.afState
+        if (LIE_ABOUT_AF) {
+            // TODO: Implement autofocus state machine
+            result.set(CaptureResult.CONTROL_AF_MODE, request.get(CaptureRequest.CONTROL_AF_MODE));
+        }
+
+        // control.aeState
+        if (LIE_ABOUT_AE) {
+            // Lie to pass CTS temporarily.
+            // TODO: Implement precapture trigger, after which we can report CONVERGED ourselves
+            result.set(CaptureResult.CONTROL_AE_STATE,
+                    CONTROL_AE_STATE_CONVERGED);
+
+            result.set(CaptureResult.CONTROL_AE_MODE,
+                    request.get(CaptureRequest.CONTROL_AE_MODE));
+        }
+
+        // control.awbLock
+        result.set(CaptureResult.CONTROL_AWB_LOCK, params.getAutoWhiteBalanceLock());
+
+        // control.awbState
+        if (LIE_ABOUT_AWB) {
+            // Lie to pass CTS temporarily.
+            // TODO: CTS needs to be updated not to query this value
+            // for LIMITED devices unless its guaranteed to be available.
+            result.set(CaptureResult.CONTROL_AWB_STATE,
+                    CameraMetadata.CONTROL_AWB_STATE_CONVERGED);
+            // TODO: Read the awb mode from parameters instead
+            result.set(CaptureResult.CONTROL_AWB_MODE,
+                    request.get(CaptureRequest.CONTROL_AWB_MODE));
+        }
+
+        /*
+         * lens
+         */
+        // lens.focalLength
         result.set(CaptureResult.LENS_FOCAL_LENGTH, params.getFocalLength());
+
+        /*
+         * sensor
+         */
+        // sensor.timestamp
         result.set(CaptureResult.SENSOR_TIMESTAMP, timestamp);
 
         // TODO: Remaining result metadata tags conversions.
@@ -335,17 +475,149 @@
      */
     public static void convertRequestMetadata(CaptureRequest request,
             /*out*/Camera.Parameters params) {
+
+        /*
+         * control.ae*
+         */
+        // control.aeAntibandingMode
         Integer antiBandingMode = request.get(CaptureRequest.CONTROL_AE_ANTIBANDING_MODE);
         if (antiBandingMode != null) {
             String legacyMode = convertAntiBandingModeToLegacy(antiBandingMode);
             if (legacyMode != null) params.setAntibanding(legacyMode);
         }
 
+        // control.aeTargetFpsRange
         Range<Integer> aeFpsRange = request.get(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE);
         if (aeFpsRange != null) {
             int[] legacyFps = convertAeFpsRangeToLegacy(aeFpsRange);
             params.setPreviewFpsRange(legacyFps[Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
                     legacyFps[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
         }
+
+        /*
+         * control
+         */
+        // control.awbLock
+        Boolean awbLock = request.get(CaptureRequest.CONTROL_AWB_LOCK);
+        params.setAutoWhiteBalanceLock(awbLock == null ? false : awbLock);
+    }
+
+    /**
+     * Create an int[] from the List<> by using {@code convertFrom} and {@code convertTo}
+     * as a one-to-one map (via the index).
+     *
+     * <p>Strings not appearing in {@code convertFrom} are ignored (with a warning);
+     * strings appearing in {@code convertFrom} but not {@code convertTo} are silently
+     * dropped.</p>
+     *
+     * @param list Source list of strings
+     * @param convertFrom Conversion list of strings
+     * @param convertTo Conversion list of ints
+     * @return An array of ints where the values correspond to the ones in {@code convertTo}
+     *         or {@code null} if {@code list} was {@code null}
+     */
+    private static int[] convertStringListToIntArray(
+            List<String> list, String[] convertFrom, int[] convertTo) {
+        if (list == null) {
+            return null;
+        }
+
+        List<Integer> convertedList = new ArrayList<>(list.size());
+
+        for (String str : list) {
+            int strIndex = getArrayIndex(convertFrom, str);
+
+            // Guard against bad API1 values
+            if (strIndex < 0) {
+                Log.w(TAG, "Ignoring invalid parameter " + str);
+                continue;
+            }
+
+            // Ignore values we can't map into (intentional)
+            if (strIndex < convertTo.length) {
+                convertedList.add(convertTo[strIndex]);
+            }
+        }
+
+        int[] returnArray = new int[convertedList.size()];
+        for (int i = 0; i < returnArray.length; ++i) {
+            returnArray[i] = convertedList.get(i);
+        }
+
+        return returnArray;
+    }
+
+    /** Return the index of {@code needle} in the {@code array}, or else {@code -1} */
+    private static <T> int getArrayIndex(T[] array, T needle) {
+        if (needle == null) {
+            return -1;
+        }
+
+        int index = 0;
+        for (T elem : array) {
+            if (Objects.equals(elem, needle)) {
+                return index;
+            }
+            index++;
+        }
+
+        return -1;
+    }
+
+    /**
+     * Create a request template
+     *
+     * @param c a non-{@code null} camera characteristics for this camera
+     * @param templateId a non-negative template ID
+     *
+     * @return a non-{@code null} request template
+     *
+     * @throws IllegalArgumentException if {@code templateId} was invalid
+     *
+     * @see android.hardware.camera2.CameraDevice#TEMPLATE_MANUAL
+     */
+    public static CameraMetadataNative createRequestTemplate(
+            CameraCharacteristics c, int templateId) {
+        if (templateId < 0 || templateId > CameraDevice.TEMPLATE_MANUAL) {
+            throw new IllegalArgumentException("templateId out of range");
+        }
+
+        CameraMetadataNative m = new CameraMetadataNative();
+
+        /*
+         * NOTE: If adding new code here and it needs to query the static info,
+         * query the camera characteristics, so we can reuse this for api2 code later
+         * to create our own templates in the framework
+         */
+
+        if (LIE_ABOUT_AWB) {
+            m.set(CaptureRequest.CONTROL_AWB_MODE, CameraMetadata.CONTROL_AWB_MODE_AUTO);
+        } else {
+            throw new AssertionError("Valid control.awbMode not implemented yet");
+        }
+
+        // control.aeMode
+        m.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
+        // AE is always unconditionally available in API1 devices
+
+        // control.afMode
+        {
+            Float minimumFocusDistance = c.get(LENS_INFO_MINIMUM_FOCUS_DISTANCE);
+
+            int afMode;
+            if (minimumFocusDistance != null &&
+                    minimumFocusDistance == LENS_INFO_MINIMUM_FOCUS_DISTANCE_FIXED_FOCUS) {
+                // Cannot control auto-focus with fixed-focus cameras
+                afMode = CameraMetadata.CONTROL_AF_MODE_OFF;
+            } else {
+                // If a minimum focus distance is reported; the camera must have AF
+                afMode = CameraMetadata.CONTROL_AF_MODE_AUTO;
+            }
+
+            m.set(CaptureRequest.CONTROL_AF_MODE, afMode);
+        }
+
+        // TODO: map other request template values
+        return m;
     }
 }
diff --git a/core/java/android/hardware/camera2/legacy/RequestQueue.java b/core/java/android/hardware/camera2/legacy/RequestQueue.java
index 6bedc48..7820648 100644
--- a/core/java/android/hardware/camera2/legacy/RequestQueue.java
+++ b/core/java/android/hardware/camera2/legacy/RequestQueue.java
@@ -77,7 +77,8 @@
         long ret = INVALID_FRAME;
         if (mRepeatingRequest != null && mRepeatingRequest.getRequestId() == requestId) {
             mRepeatingRequest = null;
-            ret = mCurrentRepeatingFrameNumber;
+            ret = (mCurrentRepeatingFrameNumber == INVALID_FRAME) ? INVALID_FRAME :
+                    mCurrentRepeatingFrameNumber - 1;
             mCurrentRepeatingFrameNumber = INVALID_FRAME;
         } else {
             Log.e(TAG, "cancel failed: no repeating request exists for request id: " + requestId);
@@ -105,7 +106,8 @@
         long ret = INVALID_FRAME;
         if (burst.isRepeating()) {
             if (mRepeatingRequest != null) {
-                ret = mCurrentRepeatingFrameNumber;
+                ret = (mCurrentRepeatingFrameNumber == INVALID_FRAME) ? INVALID_FRAME :
+                        mCurrentRepeatingFrameNumber - 1;
             }
             mCurrentRepeatingFrameNumber = INVALID_FRAME;
             mRepeatingRequest = burst;
diff --git a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
index a4b1099..efc2b0e 100644
--- a/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
+++ b/core/java/android/hardware/camera2/legacy/RequestThreadManager.java
@@ -64,7 +64,7 @@
     private static final int MSG_CLEANUP = 3;
 
     private static final int PREVIEW_FRAME_TIMEOUT = 300; // ms
-    private static final int JPEG_FRAME_TIMEOUT = 1000; // ms
+    private static final int JPEG_FRAME_TIMEOUT = 3000; // ms (same as CTS for API2)
 
     private static final float ASPECT_RATIO_TOLERANCE = 0.01f;
     private boolean mPreviewRunning = false;
@@ -105,11 +105,11 @@
 
 
     /**
-     * Comparator for {@link Size} objects.
+     * Comparator for {@link Size} objects by the area.
      *
-     * <p>This comparator compares by rectangle area.  Tiebreaks on width.</p>
+     * <p>This comparator totally orders by rectangle area. Tiebreaks on width.</p>
      */
-    private static class SizeComparator implements Comparator<Size> {
+    private static class SizeAreaComparator implements Comparator<Size> {
         @Override
         public int compare(Size size, Size size2) {
             if (size == null || size2 == null) {
@@ -262,7 +262,11 @@
     }
 
     private void doJpegCapture(RequestHolder request) throws IOException {
+        if (DEBUG) Log.d(TAG, "doJpegCapture");
+
         if (!mPreviewRunning) {
+            if (DEBUG) Log.d(TAG, "doJpegCapture - create fake surface");
+
             createDummySurface();
             mCamera.setPreviewTexture(mDummyTexture);
             startPreview();
@@ -373,6 +377,18 @@
             }
         }
 
+        Size smallestSupportedJpegSize = calculatePictureSize(mCallbackOutputs, mParams);
+        if (smallestSupportedJpegSize != null) {
+            /*
+             * Set takePicture size to the smallest supported JPEG size large enough
+             * to scale/crop out of for the bounding rectangle of the configured JPEG sizes.
+             */
+
+            Log.i(TAG, "configureOutputs - set take picture size to " + smallestSupportedJpegSize);
+            mParams.setPictureSize(
+                    smallestSupportedJpegSize.getWidth(), smallestSupportedJpegSize.getHeight());
+        }
+
         // TODO: Detect and optimize single-output paths here to skip stream teeing.
         if (mGLThreadManager == null) {
             mGLThreadManager = new GLThreadManager(mCameraId);
@@ -385,10 +401,105 @@
         if (mPreviewTexture != null) {
             mPreviewTexture.setOnFrameAvailableListener(mPreviewCallback);
         }
+
+        // TODO: configure the JPEG surface with some arbitrary size
+        // using LegacyCameraDevice.nativeConfigureSurface
+    }
+
+    /**
+     * Find a JPEG size (that is supported by the legacy camera device) which is equal to or larger
+     * than all of the configured {@code JPEG} outputs (by both width and height).
+     *
+     * <p>If multiple supported JPEG sizes are larger, select the smallest of them which
+     * still satisfies the above constraint.</p>
+     *
+     * <p>As a result, the returned size is guaranteed to be usable without needing
+     * to upscale any of the outputs. If only one {@code JPEG} surface is used,
+     * then no scaling/cropping is necessary between the taken picture and
+     * the {@code JPEG} output surface.</p>
+     *
+     * @param callbackOutputs a non-{@code null} list of {@code Surface}s with any image formats
+     * @param params api1 parameters (used for reading only)
+     *
+     * @return a size large enough to fit all of the configured {@code JPEG} outputs, or
+     *          {@code null} if the {@code callbackOutputs} did not have any {@code JPEG}
+     *          surfaces.
+     */
+    private Size calculatePictureSize(
+            Collection<Surface> callbackOutputs, Camera.Parameters params) {
+        /*
+         * Find the largest JPEG size (if any), from the configured outputs:
+         * - the api1 picture size should be set to the smallest legal size that's at least as large
+         *   as the largest configured JPEG size
+         */
+        List<Size> configuredJpegSizes = new ArrayList<Size>();
+        for (Surface callbackSurface : callbackOutputs) {
+            int format = LegacyCameraDevice.nativeDetectSurfaceType(callbackSurface);
+
+            if (format != CameraMetadataNative.NATIVE_JPEG_FORMAT) {
+                continue; // Ignore non-JPEG callback formats
+            }
+
+            Size jpegSize = LegacyCameraDevice.getSurfaceSize(callbackSurface);
+            configuredJpegSizes.add(jpegSize);
+        }
+        if (!configuredJpegSizes.isEmpty()) {
+            /*
+             * Find the largest configured JPEG width, and height, independently
+             * of the rest.
+             *
+             * The rest of the JPEG streams can be cropped out of this smallest bounding
+             * rectangle.
+             */
+            int maxConfiguredJpegWidth = -1;
+            int maxConfiguredJpegHeight = -1;
+            for (Size jpegSize : configuredJpegSizes) {
+                maxConfiguredJpegWidth = jpegSize.getWidth() > maxConfiguredJpegWidth ?
+                        jpegSize.getWidth() : maxConfiguredJpegWidth;
+                maxConfiguredJpegHeight = jpegSize.getHeight() > maxConfiguredJpegHeight ?
+                        jpegSize.getHeight() : maxConfiguredJpegHeight;
+            }
+            Size smallestBoundJpegSize = new Size(maxConfiguredJpegWidth, maxConfiguredJpegHeight);
+
+            List<Size> supportedJpegSizes = convertSizeList(params.getSupportedPictureSizes());
+
+            /*
+             * Find the smallest supported JPEG size that can fit the smallest bounding
+             * rectangle for the configured JPEG sizes.
+             */
+            List<Size> candidateSupportedJpegSizes = new ArrayList<>();
+            for (Size supportedJpegSize : supportedJpegSizes) {
+                if (supportedJpegSize.getWidth() >= maxConfiguredJpegWidth &&
+                    supportedJpegSize.getHeight() >= maxConfiguredJpegHeight) {
+                    candidateSupportedJpegSizes.add(supportedJpegSize);
+                }
+            }
+
+            if (candidateSupportedJpegSizes.isEmpty()) {
+                throw new AssertionError(
+                        "Could not find any supported JPEG sizes large enough to fit " +
+                        smallestBoundJpegSize);
+            }
+
+            Size smallestSupportedJpegSize = Collections.min(candidateSupportedJpegSizes,
+                    new SizeAreaComparator());
+
+            if (!smallestSupportedJpegSize.equals(smallestBoundJpegSize)) {
+                Log.w(TAG,
+                        String.format(
+                                "configureOutputs - Will need to crop picture %s into "
+                                + "smallest bound size %s",
+                                smallestSupportedJpegSize, smallestBoundJpegSize));
+            }
+
+            return smallestSupportedJpegSize;
+        }
+
+        return null;
     }
 
     private static Size findLargestByArea(List<Size> sizes) {
-        return Collections.max(sizes, new SizeComparator());
+        return Collections.max(sizes, new SizeAreaComparator());
     }
 
     private static boolean checkAspectRatiosMatch(Size a, Size b) {
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index ba31243..b68ce36 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -68,6 +68,7 @@
  */
 public class ConnectivityManager {
     private static final String TAG = "ConnectivityManager";
+    private static final boolean LEGACY_DBG = true; // STOPSHIP
 
     /**
      * A change in network connectivity has occurred. A default connection has either
@@ -823,6 +824,14 @@
 
         NetworkRequest request = null;
         synchronized (sLegacyRequests) {
+            if (LEGACY_DBG) {
+                Log.d(TAG, "Looking for legacyRequest for netCap with hash: " + netCap + " (" +
+                        netCap.hashCode() + ")");
+                Log.d(TAG, "sLegacyRequests has:");
+                for (NetworkCapabilities nc : sLegacyRequests.keySet()) {
+                    Log.d(TAG, "  " + nc + " (" + nc.hashCode() + ")");
+                }
+            }
             LegacyRequest l = sLegacyRequests.get(netCap);
             if (l != null) {
                 Log.d(TAG, "renewing startUsingNetworkFeature request " + l.networkRequest);
@@ -837,7 +846,7 @@
             request = requestNetworkForFeatureLocked(netCap);
         }
         if (request != null) {
-            Log.d(TAG, "starting startUsingNeworkFeature for request " + request);
+            Log.d(TAG, "starting startUsingNetworkFeature for request " + request);
             return PhoneConstants.APN_REQUEST_STARTED;
         } else {
             Log.d(TAG, " request Failed");
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index 318aabe..0a422c6 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -190,13 +190,20 @@
             }
     };
 
+    @Override
     public boolean equals(Object obj) {
         if (obj instanceof Network == false) return false;
         Network other = (Network)obj;
         return this.netId == other.netId;
     }
 
+    @Override
     public int hashCode() {
         return netId * 11;
     }
+
+    @Override
+    public String toString() {
+        return Integer.toString(netId);
+    }
 }
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index e42c3fe..3252d19 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -692,10 +692,12 @@
 
     /**
      * Returns the value associated with the given key, or defaultValue if
-     * no mapping of the desired type exists for the given key.
+     * no mapping of the desired type exists for the given key or if a null
+     * value is explicitly associatd with the given key.
      *
      * @param key a String, or null
-     * @param defaultValue Value to return if key does not exist
+     * @param defaultValue Value to return if key does not exist or if a null
+     *     value is associated with the given key.
      * @return the CharSequence value associated with the given key, or defaultValue
      *     if no valid CharSequence object is currently mapped to that key.
      */
diff --git a/core/java/android/preference/PreferenceGroupAdapter.java b/core/java/android/preference/PreferenceGroupAdapter.java
index 381a5f0..5a0b9e9 100644
--- a/core/java/android/preference/PreferenceGroupAdapter.java
+++ b/core/java/android/preference/PreferenceGroupAdapter.java
@@ -27,6 +27,7 @@
 import android.view.ViewGroup;
 import android.widget.Adapter;
 import android.widget.BaseAdapter;
+import android.widget.FrameLayout;
 import android.widget.ListView;
 
 /**
@@ -95,6 +96,9 @@
     private int mHighlightedPosition = -1;
     private Drawable mHighlightedDrawable;
 
+    private static ViewGroup.LayoutParams sWrapperLayoutParams = new ViewGroup.LayoutParams(
+            ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+
     private static class PreferenceLayout implements Comparable<PreferenceLayout> {
         private int resId;
         private int widgetResId;
@@ -235,14 +239,18 @@
 
         // If it's not one of the cached ones, set the convertView to null so that 
         // the layout gets re-created by the Preference.
-        if (Collections.binarySearch(mPreferenceLayouts, mTempPreferenceLayout) < 0) {
+        if (Collections.binarySearch(mPreferenceLayouts, mTempPreferenceLayout) < 0 ||
+                (getItemViewType(position) == getHighlightItemViewType())) {
             convertView = null;
         }
         View result = preference.getView(convertView, parent);
         if (position == mHighlightedPosition && mHighlightedDrawable != null) {
-            result.setBackgroundDrawable(mHighlightedDrawable);
+            ViewGroup wrapper = new FrameLayout(parent.getContext());
+            wrapper.setLayoutParams(sWrapperLayoutParams);
+            wrapper.setBackgroundDrawable(mHighlightedDrawable);
+            wrapper.addView(result);
+            result = wrapper;
         }
-        result.setTag(preference.getKey());
         return result;
     }
 
@@ -273,8 +281,16 @@
         return true;
     }
 
+    private int getHighlightItemViewType() {
+        return getViewTypeCount() - 1;
+    }
+
     @Override
     public int getItemViewType(int position) {
+        if (position == mHighlightedPosition) {
+            return getHighlightItemViewType();
+        }
+
         if (!mHasReturnedViewTypeCount) {
             mHasReturnedViewTypeCount = true;
         }
@@ -302,7 +318,7 @@
             mHasReturnedViewTypeCount = true;
         }
         
-        return Math.max(1, mPreferenceLayouts.size());
+        return Math.max(1, mPreferenceLayouts.size()) + 1;
     }
 
 }
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index 8038a38..0d69b3b 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -811,7 +811,6 @@
          * The position at which the contact is pinned. If {@link PinnedPositions#UNPINNED},
          * the contact is not pinned. Also see {@link PinnedPositions}.
          * <P>Type: INTEGER </P>
-         * @hide
          */
         public static final String PINNED = "pinned";
 
@@ -7745,8 +7744,8 @@
 
     /**
      * <p>
-     * API allowing applications to send pinning information for specified contacts to the
-     * Contacts Provider.
+     * Contact-specific information about whether or not a contact has been pinned by the user
+     * at a particular position within the system contact application's user interface.
      * </p>
      *
      * <p>
@@ -7771,47 +7770,8 @@
      * pinned positions can be positive integers that range anywhere from 0 to
      * {@link PinnedPositions#UNPINNED}.
      * </p>
-     *
-     * <p>
-     * When using {@link PinnedPositions#UPDATE_URI} to update the pinned positions of
-     * certain contacts, it may make sense for your application to star any pinned contacts
-     * by default. To specify this behavior, set the boolean query parameter
-     * {@link PinnedPositions#STAR_WHEN_PINNING} to true to force all pinned and unpinned
-     * contacts to be automatically starred and unstarred.
-     * </p>
-     *
-     * @hide
      */
     public static final class PinnedPositions {
-
-        /**
-         * <p>
-         * This URI allows applications to update pinned positions for a provided set of contacts.
-         * </p>
-         *
-         * <p>
-         * The list of contactIds to pin and their corresponding pinned positions should be
-         * provided in key-value pairs stored in a {@link ContentValues} object where the key
-         * is a valid contactId, while each pinned position is a positive integer.
-         * </p>
-         *
-         * <p>
-         * Example:
-         * <pre>
-         * ContentValues values = new ContentValues();
-         * values.put("10", 20);
-         * values.put("12", 2);
-         * values.put("15", PinnedPositions.UNPINNED);
-         * int count = resolver.update(PinnedPositions.UPDATE_URI, values, null, null);
-         * </pre>
-         *
-         * This pins the contact with id 10 at position 20, the contact with id 12 at position 2,
-         * and unpins the contact with id 15.
-         * </p>
-         */
-        public static final Uri UPDATE_URI = Uri.withAppendedPath(AUTHORITY_URI,
-                "pinned_position_update");
-
         /**
          * <p>
          * The method to invoke in order to undemote a formerly demoted contact. The contact id of
@@ -7826,7 +7786,6 @@
          * resolver.call(ContactsContract.AUTHORITY_URI, PinnedPositions.UNDEMOTE_METHOD,
          *         String.valueOf(contactId), null);
          * </pre>
-         *
          * </p>
          */
         public static final String UNDEMOTE_METHOD = "undemote";
@@ -7844,65 +7803,16 @@
          * just hidden from view.
          */
         public static final int DEMOTED = -1;
-
-        /**
-         * <p> Clients can provide this value as a pinned position to undemote a formerly demoted
-         * contact. If the contact was formerly demoted, it will be restored to an
-         * {@link #UNPINNED} position. If it was otherwise already pinned at another position,
-         * it will not be affected.
-         * </p>
-         *
-         * <p>
-         * Example:
-         * <pre>
-         * ContentValues values = new ContentValues();
-         * values.put("15", PinnedPositions.UNDEMOTE);
-         * int count = resolver.update(ContactsContract.PinnedPositions.UPDATE_URI.buildUpon()
-         *          .build(), values, null, null);
-         * </pre>
-         *
-         * This restores the contact with id 15 to an {@link #UNPINNED} position, meaning that
-         * other apps (e.g. the Dialer) that were formerly hiding this contact from view based on
-         * its {@link #DEMOTED} position will start displaying it again.
-         * </p>
-         */
-        public static final String UNDEMOTE = "undemote";
-
-        /**
-         * <p>
-         * A boolean query parameter that can be used with {@link #UPDATE_URI}.
-         * If "1" or "true", any contact that is pinned or unpinned will be correspondingly
-         * starred or unstarred. Otherwise, starring information will not be affected by pinned
-         * updates. This is false by default.
-         * </p>
-         *
-         * <p>
-         * Example:
-         * <pre>
-         * ContentValues values = new ContentValues();
-         * values.put("10", 20);
-         * values.put("15", PinnedPositions.UNPINNED);
-         * int count = resolver.update(ContactsContract.PinnedPositions.UPDATE_URI.buildUpon()
-         *          .appendQueryParameter(PinnedPositions.FORCE_STAR_WHEN_PINNING, "true").build(),
-         *          values, null, null);
-         * </pre>
-         *
-         * This will pin the contact with id 10 at position 20 and star it automatically if not
-         * already starred, and unpin the contact with id 15, and unstar it automatically if not
-         * already unstarred.
-         * </p>
-         */
-        public static final String STAR_WHEN_PINNING = "star_when_pinning";
     }
 
     /**
-     * Helper methods to display QuickContact dialogs that allow users to pivot on
+     * Helper methods to display QuickContact dialogs that display all the information belonging to
      * a specific {@link Contacts} entry.
      */
     public static final class QuickContact {
         /**
-         * Action used to trigger person pivot dialog.
-         * @hide
+         * Action used to launch the system contacts application and bring up a QuickContact dialog
+         * for the provided {@link Contacts} entry.
          */
         public static final String ACTION_QUICK_CONTACT =
                 "com.android.contacts.action.QUICK_CONTACT";
@@ -7922,9 +7832,8 @@
         public static final String EXTRA_MODE = "mode";
 
         /**
-         * Extra used to indicate a list of specific MIME-types to exclude and
-         * not display. Stored as a {@link String} array.
-         * @hide
+         * Extra used to indicate a list of specific MIME-types to exclude and not display in the
+         * QuickContacts dialog. Stored as a {@link String} array.
          */
         public static final String EXTRA_EXCLUDE_MIMES = "exclude_mimes";
 
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index 0fe764f..325917e 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -40,6 +40,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.Arrays;
 
 /**
  * The Media provider contains meta data for all available media on both internal
@@ -671,6 +672,7 @@
                         if (sThumbBuf == null) {
                             sThumbBuf = new byte[MiniThumbFile.BYTES_PER_MINTHUMB];
                         }
+                        Arrays.fill(sThumbBuf, (byte)0);
                         if (thumbFile.getMiniThumbFromFile(origId, sThumbBuf) != null) {
                             bitmap = BitmapFactory.decodeByteArray(sThumbBuf, 0, sThumbBuf.length);
                             if (bitmap == null) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 270775b..01e1f8a 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4583,11 +4583,9 @@
 
         /**
          * If enabled, apps should try to skip any introductory hints on first launch. This might
-         * apply to users that are already familiar with the environment or temporary users, like
-         * guests.
+         * apply to users that are already familiar with the environment or temporary users.
          * <p>
          * Type : int (0 to show hints, 1 to skip showing hints)
-         * @hide
          */
         public static final String SKIP_FIRST_USE_HINTS = "skip_first_use_hints";
 
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index e936232..0017eb1 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -89,8 +89,8 @@
  * out-in behavior. Finally, note the use of the <code>targets</code> sub-tag, which
  * takes a set of {@link android.R.styleable#TransitionTarget target} tags, each
  * of which lists a specific <code>targetId</code>, <code>targetClass</code>,
- * <code>targetViewName</code>, <code>excludeId</code>, <code>excludeClass</code>, or
- * <code>excludeViewName</code>, which this transition acts upon.
+ * <code>targetName</code>, <code>excludeId</code>, <code>excludeClass</code>, or
+ * <code>excludeName</code>, which this transition acts upon.
  * Use of targets is optional, but can be used to either limit the time spent checking
  * attributes on unchanging views, or limiting the types of animations run on specific views.
  * In this case, we know that only the <code>grayscaleContainer</code> will be
@@ -115,9 +115,9 @@
 
     /**
      * With {@link #setMatchOrder(int...)}, chooses to match by
-     * {@link android.view.View#getViewName()}. Null names will not be matched.
+     * {@link android.view.View#getTransitionName()}. Null names will not be matched.
      */
-    public static final int MATCH_VIEW_NAME = 0x2;
+    public static final int MATCH_NAME = 0x2;
 
     /**
      * With {@link #setMatchOrder(int...)}, chooses to match by
@@ -135,7 +135,7 @@
     private static final int MATCH_LAST = MATCH_ITEM_ID;
 
     private static final int[] DEFAULT_MATCH_ORDER = {
-        MATCH_VIEW_NAME,
+        MATCH_NAME,
         MATCH_INSTANCE,
         MATCH_ID,
         MATCH_ITEM_ID,
@@ -207,7 +207,7 @@
     EpicenterCallback mEpicenterCallback;
 
     // For Fragment shared element transitions, linking views explicitly by mismatching
-    // viewNames.
+    // transitionNames.
     ArrayMap<String, String> mNameOverrides;
 
     /**
@@ -378,17 +378,17 @@
     /**
      * Sets the order in which Transition matches View start and end values.
      * <p>
-     * The default behavior is to match first by {@link android.view.View#getViewName()},
+     * The default behavior is to match first by {@link android.view.View#getTransitionName()},
      * then by View instance, then by {@link android.view.View#getId()} and finally
      * by its item ID if it is in a direct child of ListView. The caller can
      * choose to have only some or all of the values of {@link #MATCH_INSTANCE},
-     * {@link #MATCH_VIEW_NAME}, {@link #MATCH_ITEM_ID}, and {@link #MATCH_ID}. Only
+     * {@link #MATCH_NAME}, {@link #MATCH_ITEM_ID}, and {@link #MATCH_ID}. Only
      * the match algorithms supplied will be used to determine whether Views are the
      * the same in both the start and end Scene. Views that do not match will be considered
      * as entering or leaving the Scene.
      * </p>
      * @param matches A list of zero or more of {@link #MATCH_INSTANCE},
-     *                {@link #MATCH_VIEW_NAME}, {@link #MATCH_ITEM_ID}, and {@link #MATCH_ID}.
+     *                {@link #MATCH_NAME}, {@link #MATCH_ITEM_ID}, and {@link #MATCH_ID}.
      *                If none are provided, then the default match order will be set.
      */
     public void setMatchOrder(int... matches) {
@@ -500,9 +500,9 @@
     }
 
     /**
-     * Match start/end values by Adapter viewName. Adds matched values to startValuesList
+     * Match start/end values by Adapter transitionName. Adds matched values to startValuesList
      * and endValuesList and removes them from unmatchedStart and unmatchedEnd, using
-     * startNames and endNames as a guide for which Views have unique viewNames.
+     * startNames and endNames as a guide for which Views have unique transitionNames.
      */
     private void matchNames(ArrayList<TransitionValues> startValuesList,
             ArrayList<TransitionValues> endValuesList,
@@ -563,7 +563,7 @@
                 case MATCH_INSTANCE:
                     matchInstances(startValuesList, endValuesList, unmatchedStart, unmatchedEnd);
                     break;
-                case MATCH_VIEW_NAME:
+                case MATCH_NAME:
                     matchNames(startValuesList, endValuesList, unmatchedStart, unmatchedEnd,
                             startValues.nameValues, endValues.nameValues);
                     break;
@@ -718,8 +718,8 @@
                 }
             }
         }
-        if (mTargetNameExcludes != null && target != null && target.getViewName() != null) {
-            if (mTargetNameExcludes.contains(target.getViewName())) {
+        if (mTargetNameExcludes != null && target != null && target.getTransitionName() != null) {
+            if (mTargetNameExcludes.contains(target.getTransitionName())) {
                 return false;
             }
         }
@@ -731,7 +731,7 @@
         if (mTargetIds.contains(targetId) || mTargets.contains(target)) {
             return true;
         }
-        if (mTargetNames != null && mTargetNames.contains(target.getViewName())) {
+        if (mTargetNames != null && mTargetNames.contains(target.getTransitionName())) {
             return true;
         }
         if (mTargetTypes != null) {
@@ -882,18 +882,18 @@
     }
 
     /**
-     * Adds the viewName of a target view that this Transition is interested in
+     * Adds the transitionName of a target view that this Transition is interested in
      * animating. By default, there are no targetNames, and a Transition will
      * listen for changes on every view in the hierarchy below the sceneRoot
      * of the Scene being transitioned into. Setting targetNames constrains
-     * the Transition to only listen for, and act on, views with these viewNames.
-     * Views with different viewNames, or no viewName whatsoever, will be ignored.
+     * the Transition to only listen for, and act on, views with these transitionNames.
+     * Views with different transitionNames, or no transitionName whatsoever, will be ignored.
      *
-     * <p>Note that viewNames should be unique within the view hierarchy.</p>
+     * <p>Note that transitionNames should be unique within the view hierarchy.</p>
      *
-     * @see android.view.View#getViewName()
-     * @param targetName The viewName of a target view, must be non-null.
-     * @return The Transition to which the target viewName is added.
+     * @see android.view.View#getTransitionName()
+     * @param targetName The transitionName of a target view, must be non-null.
+     * @return The Transition to which the target transitionName is added.
      * Returning the same object makes it easier to chain calls during
      * construction, such as
      * <code>transitionSet.addTransitions(new Fade()).addTarget(someName);</code>
@@ -958,10 +958,10 @@
     }
 
     /**
-     * Removes the given targetName from the list of viewNames that this Transition
+     * Removes the given targetName from the list of transitionNames that this Transition
      * is interested in animating.
      *
-     * @param targetName The viewName of a target view, must not be null.
+     * @param targetName The transitionName of a target view, must not be null.
      * @return The Transition from which the targetName is removed.
      * Returning the same object makes it easier to chain calls during
      * construction, such as
@@ -1003,28 +1003,28 @@
     }
 
     /**
-     * Whether to add the given viewName to the list of target viewNames to exclude from this
-     * transition. The <code>exclude</code> parameter specifies whether the target
+     * Whether to add the given transitionName to the list of target transitionNames to exclude
+     * from this transition. The <code>exclude</code> parameter specifies whether the target
      * should be added to or removed from the excluded list.
      *
      * <p>Excluding targets is a general mechanism for allowing transitions to run on
      * a view hierarchy while skipping target views that should not be part of
      * the transition. For example, you may want to avoid animating children
      * of a specific ListView or Spinner. Views can be excluded by their
-     * id, their instance reference, their viewName, or by the Class of that view
+     * id, their instance reference, their transitionName, or by the Class of that view
      * (eg, {@link Spinner}).</p>
      *
      * @see #excludeTarget(View, boolean)
      * @see #excludeTarget(int, boolean)
      * @see #excludeTarget(Class, boolean)
      *
-     * @param targetViewName The name of a target to ignore when running this transition.
+     * @param targetName The name of a target to ignore when running this transition.
      * @param exclude Whether to add the target to or remove the target from the
      * current list of excluded targets.
      * @return This transition object.
      */
-    public Transition excludeTarget(String targetViewName, boolean exclude) {
-        mTargetNameExcludes = excludeObject(mTargetNameExcludes, targetViewName, exclude);
+    public Transition excludeTarget(String targetName, boolean exclude) {
+        mTargetNameExcludes = excludeObject(mTargetNameExcludes, targetName, exclude);
         return this;
     }
 
@@ -1248,7 +1248,7 @@
     /**
      * Returns the list of target IDs that this transition limits itself to
      * tracking and animating. If the list is null or empty for
-     * {@link #getTargetIds()}, {@link #getTargets()}, {@link #getTargetViewNames()}, and
+     * {@link #getTargetIds()}, {@link #getTargets()}, {@link #getTargetNames()}, and
      * {@link #getTargetTypes()} then this transition is
      * not limited to specific views, and will handle changes to any views
      * in the hierarchy of a scene change.
@@ -1262,7 +1262,7 @@
     /**
      * Returns the list of target views that this transition limits itself to
      * tracking and animating. If the list is null or empty for
-     * {@link #getTargetIds()}, {@link #getTargets()}, {@link #getTargetViewNames()}, and
+     * {@link #getTargetIds()}, {@link #getTargets()}, {@link #getTargetNames()}, and
      * {@link #getTargetTypes()} then this transition is
      * not limited to specific views, and will handle changes to any views
      * in the hierarchy of a scene change.
@@ -1274,23 +1274,31 @@
     }
 
     /**
-     * Returns the list of target viewNames that this transition limits itself to
+     * Returns the list of target transitionNames that this transition limits itself to
      * tracking and animating. If the list is null or empty for
-     * {@link #getTargetIds()}, {@link #getTargets()}, {@link #getTargetViewNames()}, and
+     * {@link #getTargetIds()}, {@link #getTargets()}, {@link #getTargetNames()}, and
      * {@link #getTargetTypes()} then this transition is
      * not limited to specific views, and will handle changes to any views
      * in the hierarchy of a scene change.
      *
-     * @return the list of target viewNames
+     * @return the list of target transitionNames
+     */
+    public List<String> getTargetNames() {
+        return mTargetNames;
+    }
+
+    /**
+     * To be removed before L release.
+     * @hide
      */
     public List<String> getTargetViewNames() {
         return mTargetNames;
     }
 
     /**
-     * Returns the list of target viewNames that this transition limits itself to
+     * Returns the list of target transitionNames that this transition limits itself to
      * tracking and animating. If the list is null or empty for
-     * {@link #getTargetIds()}, {@link #getTargets()}, {@link #getTargetViewNames()}, and
+     * {@link #getTargetIds()}, {@link #getTargets()}, {@link #getTargetNames()}, and
      * {@link #getTargetTypes()} then this transition is
      * not limited to specific views, and will handle changes to any views
      * in the hierarchy of a scene change.
@@ -1380,10 +1388,10 @@
                 transitionValuesMaps.idValues.put(id, view);
             }
         }
-        String name = view.getViewName();
+        String name = view.getTransitionName();
         if (name != null) {
             if (transitionValuesMaps.nameValues.containsKey(name)) {
-                // Duplicate viewNames: cannot match by viewName.
+                // Duplicate transitionNames: cannot match by transitionName.
                 transitionValuesMaps.nameValues.put(name, null);
             } else {
                 transitionValuesMaps.nameValues.put(name, view);
diff --git a/core/java/android/transition/TransitionInflater.java b/core/java/android/transition/TransitionInflater.java
index 5b7c737..551f78c 100644
--- a/core/java/android/transition/TransitionInflater.java
+++ b/core/java/android/transition/TransitionInflater.java
@@ -30,7 +30,6 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.StringTokenizer;
 
 /**
@@ -43,6 +42,8 @@
  */
 public class TransitionInflater {
     private static final String MATCH_INSTANCE = "instance";
+    private static final String MATCH_NAME = "name";
+    /** To be removed before L release */
     private static final String MATCH_VIEW_NAME = "viewName";
     private static final String MATCH_ID = "id";
     private static final String MATCH_ITEM_ID = "itemId";
@@ -90,8 +91,6 @@
     /**
      * Loads a {@link TransitionManager} object from a resource
      *
-     *
-     *
      * @param resource The resource id of the transition manager to load
      * @return The loaded TransitionManager object
      * @throws android.content.res.Resources.NotFoundException when the
@@ -235,20 +234,20 @@
                         com.android.internal.R.styleable.TransitionTarget);
                 int id = a.getResourceId(
                         com.android.internal.R.styleable.TransitionTarget_targetId, -1);
-                String viewName;
+                String transitionName;
                 if (id >= 0) {
                     transition.addTarget(id);
                 } else if ((id = a.getResourceId(
                         com.android.internal.R.styleable.TransitionTarget_excludeId, -1)) >= 0) {
                     transition.excludeTarget(id, true);
-                } else if ((viewName = a.getString(
-                            com.android.internal.R.styleable.TransitionTarget_targetViewName))
+                } else if ((transitionName = a.getString(
+                            com.android.internal.R.styleable.TransitionTarget_targetName))
                         != null) {
-                    transition.addTarget(viewName);
-                } else if ((viewName = a.getString(
-                        com.android.internal.R.styleable.TransitionTarget_excludeViewName))
+                    transition.addTarget(transitionName);
+                } else if ((transitionName = a.getString(
+                        com.android.internal.R.styleable.TransitionTarget_excludeName))
                         != null) {
-                    transition.excludeTarget(viewName, true);
+                    transition.excludeTarget(transitionName, true);
                 } else {
                     String className = a.getString(
                             com.android.internal.R.styleable.TransitionTarget_excludeClass);
@@ -282,8 +281,10 @@
                 matches[index] = Transition.MATCH_ID;
             } else if (MATCH_INSTANCE.equalsIgnoreCase(token)) {
                 matches[index] = Transition.MATCH_INSTANCE;
+            } else if (MATCH_NAME.equalsIgnoreCase(token)) {
+                matches[index] = Transition.MATCH_NAME;
             } else if (MATCH_VIEW_NAME.equalsIgnoreCase(token)) {
-                matches[index] = Transition.MATCH_VIEW_NAME;
+                matches[index] = Transition.MATCH_NAME;
             } else if (MATCH_ITEM_ID.equalsIgnoreCase(token)) {
                 matches[index] = Transition.MATCH_ITEM_ID;
             } else if (token.isEmpty()) {
diff --git a/core/java/android/transition/TransitionSet.java b/core/java/android/transition/TransitionSet.java
index c04be4f..495814a 100644
--- a/core/java/android/transition/TransitionSet.java
+++ b/core/java/android/transition/TransitionSet.java
@@ -244,11 +244,11 @@
     }
 
     @Override
-    public Transition excludeTarget(String targetViewName, boolean exclude) {
+    public Transition excludeTarget(String targetName, boolean exclude) {
         for (int i = 0; i < mTransitions.size(); i++) {
-            mTransitions.get(i).excludeTarget(targetViewName, exclude);
+            mTransitions.get(i).excludeTarget(targetName, exclude);
         }
-        return super.excludeTarget(targetViewName, exclude);
+        return super.excludeTarget(targetName, exclude);
     }
 
     @Override
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 9fafc48..dcd9ba9 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -234,12 +234,11 @@
     protected static native long nFinishRecording(long renderer);
 
     @Override
-    public int drawDisplayList(RenderNode displayList, Rect dirty, int flags) {
-        return nDrawDisplayList(mRenderer, displayList.getNativeDisplayList(),
-                dirty, flags);
+    public int drawRenderNode(RenderNode renderNode, Rect dirty, int flags) {
+        return nDrawRenderNode(mRenderer, renderNode.getNativeDisplayList(), dirty, flags);
     }
 
-    private static native int nDrawDisplayList(long renderer, long displayList,
+    private static native int nDrawRenderNode(long renderer, long renderNode,
             Rect dirty, int flags);
 
     ///////////////////////////////////////////////////////////////////////////
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
index b8e7d8c..263ebda 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -61,16 +61,16 @@
      * Draws the specified display list onto this canvas. The display list can only
      * be drawn if {@link android.view.RenderNode#isValid()} returns true.
      *
-     * @param displayList The display list to replay.
+     * @param renderNode The RenderNode to replay.
      */
-    public void drawDisplayList(RenderNode displayList) {
-        drawDisplayList(displayList, null, RenderNode.FLAG_CLIP_CHILDREN);
+    public void drawRenderNode(RenderNode renderNode) {
+        drawRenderNode(renderNode, null, RenderNode.FLAG_CLIP_CHILDREN);
     }
 
     /**
      * Draws the specified display list onto this canvas.
      *
-     * @param displayList The display list to replay.
+     * @param renderNode The RenderNode to replay.
      * @param dirty Ignored, can be null.
      * @param flags Optional flags about drawing, see {@link RenderNode} for
      *              the possible flags.
@@ -80,7 +80,7 @@
      *
      * @hide
      */
-    public abstract int drawDisplayList(RenderNode displayList, Rect dirty, int flags);
+    public abstract int drawRenderNode(RenderNode renderNode, Rect dirty, int flags);
 
     /**
      * Draws the specified layer onto this canvas.
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index c0e42a3..cfb4af2 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -387,17 +387,6 @@
     abstract boolean copyLayerInto(HardwareLayer layer, Bitmap bitmap);
 
     /**
-     * Schedules the functor for execution in either kModeProcess or
-     * kModeProcessNoContext, depending on whether or not there is an EGLContext.
-     *
-     * @param functor The native functor to invoke
-     * @param waitForCompletion If true, this will not return until the functor
-     *                          has invoked. If false, the functor may be invoked
-     *                          asynchronously.
-     */
-    abstract void invokeFunctor(long functor, boolean waitForCompletion);
-
-    /**
      * Initializes the hardware renderer for the specified surface and setup the
      * renderer for drawing, if needed. This is invoked when the ViewAncestor has
      * potentially lost the hardware renderer. The hardware renderer should be
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index b9ed801..577415e 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -311,7 +311,7 @@
         if (mFactory == null) {
             mFactory = mFactory2 = factory;
         } else {
-            mFactory = new FactoryMerger(factory, factory, mFactory, mFactory2);
+            mFactory = mFactory2 = new FactoryMerger(factory, factory, mFactory, mFactory2);
         }
     }
 
@@ -319,7 +319,11 @@
      * @hide for use by framework
      */
     public void setPrivateFactory(Factory2 factory) {
-        mPrivateFactory = factory;
+        if (mPrivateFactory == null) {
+            mPrivateFactory = factory;
+        } else {
+            mPrivateFactory = new FactoryMerger(factory, factory, mPrivateFactory, mPrivateFactory);
+        }
     }
 
     /**
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 166edc2..bfab654 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -64,9 +64,9 @@
 
     // Keep in sync with DrawFrameTask.h SYNC_* flags
     // Nothing interesting to report
-    private static final int SYNC_OK = 0x0;
+    private static final int SYNC_OK = 0;
     // Needs a ViewRoot invalidate
-    private static final int SYNC_INVALIDATE_REQUIRED = 0x1;
+    private static final int SYNC_INVALIDATE_REQUIRED = 1 << 0;
 
     private static final String[] VISUALIZERS = {
         PROFILE_PROPERTY_VISUALIZE_BARS,
@@ -80,13 +80,13 @@
     private boolean mProfilingEnabled;
 
     ThreadedRenderer(Context context, boolean translucent) {
-        AtlasInitializer.sInstance.init(context);
-
         long rootNodePtr = nCreateRootRenderNode();
         mRootNode = RenderNode.adopt(rootNodePtr);
         mRootNode.setClipToBounds(false);
         mNativeProxy = nCreateProxy(translucent, rootNodePtr);
 
+        AtlasInitializer.sInstance.init(context, mNativeProxy);
+
         // Setup timing
         mChoreographer = Choreographer.getInstance();
         nSetFrameInterval(mNativeProxy, mChoreographer.getFrameIntervalNanos());
@@ -222,7 +222,7 @@
         try {
             canvas.save();
             callbacks.onHardwarePreDraw(canvas);
-            canvas.drawDisplayList(view.getDisplayList());
+            canvas.drawRenderNode(view.getDisplayList());
             callbacks.onHardwarePostDraw(canvas);
             canvas.restore();
         } finally {
@@ -259,9 +259,8 @@
         }
     }
 
-    @Override
-    void invokeFunctor(long functor, boolean waitForCompletion) {
-        nInvokeFunctor(mNativeProxy, functor, waitForCompletion);
+    static void invokeFunctor(long functor, boolean waitForCompletion) {
+        nInvokeFunctor(functor, waitForCompletion);
     }
 
     @Override
@@ -342,7 +341,7 @@
 
         private AtlasInitializer() {}
 
-        synchronized void init(Context context) {
+        synchronized void init(Context context, long renderProxy) {
             if (mInitialized) return;
             IBinder binder = ServiceManager.getService("assetatlas");
             if (binder == null) return;
@@ -356,7 +355,7 @@
                         if (map != null) {
                             // TODO Remove after fixing b/15425820
                             validateMap(context, map);
-                            nSetAtlas(buffer, map);
+                            nSetAtlas(renderProxy, buffer, map);
                             mInitialized = true;
                         }
                         // If IAssetAtlas is not the same class as the IBinder
@@ -399,7 +398,7 @@
 
     static native void setupShadersDiskCache(String cacheFile);
 
-    private static native void nSetAtlas(GraphicBuffer buffer, long[] map);
+    private static native void nSetAtlas(long nativeProxy, GraphicBuffer buffer, long[] map);
 
     private static native long nCreateRootRenderNode();
     private static native long nCreateProxy(boolean translucent, long rootRenderNode);
@@ -419,7 +418,7 @@
     private static native void nRunWithGlContext(long nativeProxy, Runnable runnable);
     private static native void nDestroyCanvasAndSurface(long nativeProxy);
 
-    private static native void nInvokeFunctor(long nativeProxy, long functor, boolean waitForCompletion);
+    private static native void nInvokeFunctor(long functor, boolean waitForCompletion);
 
     private static native long nCreateDisplayListLayer(long nativeProxy, int width, int height);
     private static native long nCreateTextureLayer(long nativeProxy);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index d25ef16..829e089 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -672,7 +672,7 @@
  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
  * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
  * @attr ref android.R.styleable#View_stateListAnimator
- * @attr ref android.R.styleable#View_viewName
+ * @attr ref android.R.styleable#View_transitionName
  * @attr ref android.R.styleable#View_soundEffectsEnabled
  * @attr ref android.R.styleable#View_tag
  * @attr ref android.R.styleable#View_textAlignment
@@ -3193,18 +3193,18 @@
     private boolean mHasBackgroundTint = false;
 
     /**
-     * Display list used for backgrounds.
+     * RenderNode used for backgrounds.
      * <p>
      * When non-null and valid, this is expected to contain an up-to-date copy
-     * of the background drawable. It is cleared on temporary detach and reset
+     * of the background drawable. It is cleared on temporary detach, and reset
      * on cleanup.
      */
-    private RenderNode mBackgroundDisplayList;
+    private RenderNode mBackgroundRenderNode;
 
     private int mBackgroundResource;
     private boolean mBackgroundSizeChanged;
 
-    private String mViewName;
+    private String mTransitionName;
 
     static class ListenerInfo {
         /**
@@ -3894,7 +3894,7 @@
                     if (fadingEdge != FADING_EDGE_NONE) {
                         viewFlagValues |= fadingEdge;
                         viewFlagMasks |= FADING_EDGE_MASK;
-                        initializeFadingEdge(a);
+                        initializeFadingEdgeInternal(a);
                     }
                     break;
                 case R.styleable.View_scrollbarStyle:
@@ -4016,8 +4016,8 @@
                 case R.styleable.View_accessibilityLiveRegion:
                     setAccessibilityLiveRegion(a.getInt(attr, ACCESSIBILITY_LIVE_REGION_DEFAULT));
                     break;
-                case R.styleable.View_viewName:
-                    setViewName(a.getString(attr));
+                case R.styleable.View_transitionName:
+                    setTransitionName(a.getString(attr));
                     break;
                 case R.styleable.View_nestedScrollingEnabled:
                     setNestedScrollingEnabled(a.getBoolean(attr, false));
@@ -4108,7 +4108,7 @@
         }
 
         if (initializeScrollbars) {
-            initializeScrollbars(a);
+            initializeScrollbarsInternal(a);
         }
 
         a.recycle();
@@ -4236,6 +4236,32 @@
      * @param a the styled attributes set to initialize the fading edges from
      */
     protected void initializeFadingEdge(TypedArray a) {
+        // This method probably shouldn't have been included in the SDK to begin with.
+        // It relies on 'a' having been initialized using an attribute filter array that is
+        // not publicly available to the SDK. The old method has been renamed
+        // to initializeFadingEdgeInternal and hidden for framework use only;
+        // this one initializes using defaults to make it safe to call for apps.
+
+        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
+
+        initializeFadingEdgeInternal(arr);
+
+        arr.recycle();
+    }
+
+    /**
+     * <p>
+     * Initializes the fading edges from a given set of styled attributes. This
+     * method should be called by subclasses that need fading edges and when an
+     * instance of these subclasses is created programmatically rather than
+     * being inflated from XML. This method is automatically called when the XML
+     * is inflated.
+     * </p>
+     *
+     * @param a the styled attributes set to initialize the fading edges from
+     * @hide This is the real method; the public one is shimmed to be safe to call from apps.
+     */
+    protected void initializeFadingEdgeInternal(TypedArray a) {
         initScrollCache();
 
         mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
@@ -4350,6 +4376,31 @@
      * @param a the styled attributes set to initialize the scrollbars from
      */
     protected void initializeScrollbars(TypedArray a) {
+        // It's not safe to use this method from apps. The parameter 'a' must have been obtained
+        // using the View filter array which is not available to the SDK. As such, internal
+        // framework usage now uses initializeScrollbarsInternal and we grab a default
+        // TypedArray with the right filter instead here.
+        TypedArray arr = mContext.obtainStyledAttributes(com.android.internal.R.styleable.View);
+
+        initializeScrollbarsInternal(arr);
+
+        // We ignored the method parameter. Recycle the one we actually did use.
+        arr.recycle();
+    }
+
+    /**
+     * <p>
+     * Initializes the scrollbars from a given set of styled attributes. This
+     * method should be called by subclasses that need scrollbars and when an
+     * instance of these subclasses is created programmatically rather than
+     * being inflated from XML. This method is automatically called when the XML
+     * is inflated.
+     * </p>
+     *
+     * @param a the styled attributes set to initialize the scrollbars from
+     * @hide
+     */
+    protected void initializeScrollbarsInternal(TypedArray a) {
         initScrollCache();
 
         final ScrollabilityCache scrollabilityCache = mScrollCache;
@@ -12958,33 +13009,6 @@
         }
     }
 
-    /**
-     * This method ensures the hardware renderer is in a valid state
-     * before executing the specified action.
-     *
-     * This method will attempt to set a valid state even if the window
-     * the renderer is attached to was destroyed.
-     *
-     * This method is not guaranteed to work. If the hardware renderer
-     * does not exist or cannot be put in a valid state, this method
-     * will not executed the specified action.
-     *
-     * The specified action is executed synchronously.
-     *
-     * @param action The action to execute after the renderer is in a valid state
-     *
-     * @return True if the specified Runnable was executed, false otherwise
-     *
-     * @hide
-     */
-    public boolean executeHardwareAction(Runnable action) {
-        //noinspection SimplifiableIfStatement
-        if (mAttachInfo != null && mAttachInfo.mHardwareRenderer != null) {
-            return mAttachInfo.mHardwareRenderer.safelyRun(action);
-        }
-        return false;
-    }
-
     void invalidateInheritedLayoutMode(int layoutModeOfRoot) {
     }
 
@@ -13755,8 +13779,8 @@
             mRenderNode.destroyDisplayListData();
         }
 
-        if (mBackgroundDisplayList != null && mBackgroundDisplayList.isValid()) {
-            mBackgroundDisplayList.destroyDisplayListData();
+        if (mBackgroundRenderNode != null && mBackgroundRenderNode.isValid()) {
+            mBackgroundRenderNode.destroyDisplayListData();
         }
     }
 
@@ -14471,7 +14495,7 @@
             mPrivateFlags &= ~PFLAG_INVALIDATED;
         }
 
-        RenderNode displayList = null;
+        RenderNode renderNode = null;
         Bitmap cache = null;
         boolean hasDisplayList = false;
         if (caching) {
@@ -14506,12 +14530,12 @@
         }
         useDisplayListProperties &= hasDisplayList;
         if (useDisplayListProperties) {
-            displayList = getDisplayList();
-            if (!displayList.isValid()) {
+            renderNode = getDisplayList();
+            if (!renderNode.isValid()) {
                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
                 // to getDisplayList(), the display list will be marked invalid and we should not
                 // try to use it again.
-                displayList = null;
+                renderNode = null;
                 hasDisplayList = false;
                 useDisplayListProperties = false;
             }
@@ -14565,7 +14589,7 @@
                 if (transformToApply != null) {
                     if (concatMatrix) {
                         if (useDisplayListProperties) {
-                            displayList.setAnimationMatrix(transformToApply.getMatrix());
+                            renderNode.setAnimationMatrix(transformToApply.getMatrix());
                         } else {
                             // Undo the scroll translation, apply the transformation matrix,
                             // then redo the scroll translate to get the correct result.
@@ -14608,7 +14632,7 @@
                             layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
                         }
                         if (useDisplayListProperties) {
-                            displayList.setAlpha(alpha * getAlpha() * getTransitionAlpha());
+                            renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
                         } else  if (layerType == LAYER_TYPE_NONE) {
                             final int scrollX = hasDisplayList ? 0 : sx;
                             final int scrollY = hasDisplayList ? 0 : sy;
@@ -14640,12 +14664,12 @@
         }
 
         if (!useDisplayListProperties && hasDisplayList) {
-            displayList = getDisplayList();
-            if (!displayList.isValid()) {
+            renderNode = getDisplayList();
+            if (!renderNode.isValid()) {
                 // Uncommon, but possible. If a view is removed from the hierarchy during the call
                 // to getDisplayList(), the display list will be marked invalid and we should not
                 // try to use it again.
-                displayList = null;
+                renderNode = null;
                 hasDisplayList = false;
             }
         }
@@ -14678,7 +14702,7 @@
                     }
                 } else {
                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
-                    ((HardwareCanvas) canvas).drawDisplayList(displayList, null, flags);
+                    ((HardwareCanvas) canvas).drawRenderNode(renderNode, null, flags);
                 }
             }
         } else if (cache != null) {
@@ -14949,12 +14973,12 @@
         // Attempt to use a display list if requested.
         if (canvas.isHardwareAccelerated() && mAttachInfo != null
                 && mAttachInfo.mHardwareRenderer != null) {
-            mBackgroundDisplayList = getDrawableDisplayList(background, mBackgroundDisplayList);
+            mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);
 
-            final RenderNode displayList = mBackgroundDisplayList;
+            final RenderNode displayList = mBackgroundRenderNode;
             if (displayList != null && displayList.isValid()) {
                 setBackgroundDisplayListProperties(displayList);
-                ((HardwareCanvas) canvas).drawDisplayList(displayList);
+                ((HardwareCanvas) canvas).drawRenderNode(displayList);
                 return;
             }
         }
@@ -14985,30 +15009,30 @@
      * specified Drawable.
      *
      * @param drawable Drawable for which to create a display list
-     * @param displayList Existing display list, or {@code null}
+     * @param renderNode Existing RenderNode, or {@code null}
      * @return A valid display list for the specified drawable
      */
-    private RenderNode getDrawableDisplayList(Drawable drawable, RenderNode displayList) {
-        if (displayList == null) {
-            displayList = RenderNode.create(drawable.getClass().getName());
+    private RenderNode getDrawableRenderNode(Drawable drawable, RenderNode renderNode) {
+        if (renderNode == null) {
+            renderNode = RenderNode.create(drawable.getClass().getName());
         }
 
         final Rect bounds = drawable.getBounds();
         final int width = bounds.width();
         final int height = bounds.height();
-        final HardwareCanvas canvas = displayList.start(width, height);
+        final HardwareCanvas canvas = renderNode.start(width, height);
         try {
             drawable.draw(canvas);
         } finally {
-            displayList.end(canvas);
+            renderNode.end(canvas);
         }
 
         // Set up drawable properties that are view-independent.
-        displayList.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
-        displayList.setProjectBackwards(drawable.isProjected());
-        displayList.setProjectionReceiver(true);
-        displayList.setClipToBounds(false);
-        return displayList;
+        renderNode.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
+        renderNode.setProjectBackwards(drawable.isProjected());
+        renderNode.setProjectionReceiver(true);
+        renderNode.setClipToBounds(false);
+        return renderNode;
     }
 
     /**
@@ -18916,15 +18940,15 @@
     }
 
     /**
-     * Adds all Views that have {@link #getViewName()} non-null to namedElements.
-     * @param namedElements Will contain all Views in the hierarchy having a view name.
+     * Adds all Views that have {@link #getTransitionName()} non-null to namedElements.
+     * @param namedElements Will contain all Views in the hierarchy having a transitionName.
      * @hide
      */
     public void findNamedViews(Map<String, View> namedElements) {
         if (getVisibility() == VISIBLE) {
-            String viewName = getViewName();
-            if (viewName != null) {
-                namedElements.put(viewName, this);
+            String transitionName = getTransitionName();
+            if (transitionName != null) {
+                namedElements.put(transitionName, this);
             }
         }
     }
@@ -19326,10 +19350,18 @@
      * Sets the name of the View to be used to identify Views in Transitions.
      * Names should be unique in the View hierarchy.
      *
-     * @param viewName The name of the View to uniquely identify it for Transitions.
+     * @param transitionName The name of the View to uniquely identify it for Transitions.
      */
-    public final void setViewName(String viewName) {
-        mViewName = viewName;
+    public final void setTransitionName(String transitionName) {
+        mTransitionName = transitionName;
+    }
+
+    /**
+     * To be removed before L release.
+     * @hide
+     */
+    public final void setViewName(String transitionName) {
+        setTransitionName(transitionName);
     }
 
     /**
@@ -19341,11 +19373,17 @@
      * @return The name used of the View to be used to identify Views in Transitions or null
      * if no name has been given.
      */
-    public String getViewName() {
-        return mViewName;
+    public String getTransitionName() {
+        return mTransitionName;
     }
 
     /**
+     * To be removed before L release.
+     * @hide
+     */
+    public String getViewName() { return getTransitionName(); }
+
+    /**
      * Interface definition for a callback to be invoked when a hardware key event is
      * dispatched to this view. The callback will be invoked before the key event is
      * given to the view. This is only useful for hardware keyboards; a software input
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 1e72625..45ac073 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2326,13 +2326,13 @@
      * individually during the transition.
      * @return True if the ViewGroup should be acted on together during an Activity transition.
      * The default value is false when the background is null and true when the background
-     * is not null or if {@link #getViewName()} is not null.
+     * is not null or if {@link #getTransitionName()} is not null.
      */
     public boolean isTransitionGroup() {
         if ((mGroupFlags & FLAG_IS_TRANSITION_GROUP_SET) != 0) {
             return ((mGroupFlags & FLAG_IS_TRANSITION_GROUP) != 0);
         } else {
-            return getBackground() != null || getViewName() != null;
+            return getBackground() != null || getTransitionName() != null;
         }
     }
 
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index f574042..84e30c6 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -661,12 +661,17 @@
         }
     }
 
-    public boolean invokeFunctor(long functor, boolean waitForCompletion) {
-        if (mAttachInfo.mHardwareRenderer == null) {
-            return false;
-        }
-        mAttachInfo.mHardwareRenderer.invokeFunctor(functor, waitForCompletion);
-        return true;
+    /**
+     * Schedules the functor for execution in either kModeProcess or
+     * kModeProcessNoContext, depending on whether or not there is an EGLContext.
+     *
+     * @param functor The native functor to invoke
+     * @param waitForCompletion If true, this will not return until the functor
+     *                          has invoked. If false, the functor may be invoked
+     *                          asynchronously.
+     */
+    public void invokeFunctor(long functor, boolean waitForCompletion) {
+        ThreadedRenderer.invokeFunctor(functor, waitForCompletion);
     }
 
     private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) {
diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java
index a92bf59..bf5c84e 100644
--- a/core/java/android/view/WindowManagerInternal.java
+++ b/core/java/android/view/WindowManagerInternal.java
@@ -167,5 +167,5 @@
      * Invalidate all visible windows. Then report back on the callback once all windows have
      * redrawn.
      */
-    public abstract void waitForAllWindowsDrawn(IRemoteCallback callback, long timeout);
+    public abstract void waitForAllWindowsDrawn(Runnable callback, long timeout);
 }
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index d426edc..024600d 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -1154,6 +1154,12 @@
     public void setLastInputMethodWindowLw(WindowState ime, WindowState target);
 
     /**
+     * Show the recents task list app.
+     * @hide
+     */
+    public void showRecentApps();
+
+    /**
      * @return The current height of the input method window.
      */
     public int getInputMethodWindowVisibleHeightLw();
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 372228c..f2692da 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -785,7 +785,7 @@
 
         setVerticalScrollBarEnabled(true);
         TypedArray a = context.obtainStyledAttributes(R.styleable.View);
-        initializeScrollbars(a);
+        initializeScrollbarsInternal(a);
         a.recycle();
     }
 
diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java
index 2502954..90fec23 100644
--- a/core/java/android/widget/EdgeEffect.java
+++ b/core/java/android/widget/EdgeEffect.java
@@ -286,6 +286,22 @@
         mTargetDisplacement = 0.5f;
     }
 
+    /**
+     * Set the color of this edge effect in argb.
+     *
+     * @param color Color in argb
+     */
+    public void setColor(int color) {
+        mPaint.setColor(color);
+    }
+
+    /**
+     * Return the color of this edge effect in argb.
+     * @return The color of this edge effect in argb
+     */
+    public int getColor() {
+        return mPaint.getColor();
+    }
 
     /**
      * Draw into the provided canvas. Assumes that the canvas has been rotated
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 4467128..13a0849 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1420,7 +1420,7 @@
                     blockDisplayList.setLeftTopRightBottom(left, top, right, bottom);
                 }
 
-                ((HardwareCanvas) canvas).drawDisplayList(blockDisplayList, null,
+                ((HardwareCanvas) canvas).drawRenderNode(blockDisplayList, null,
                         0 /* no child clipping, our TextView parent enforces it */);
 
                 endOfPreviousBlock = blockEndLine;
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index 4f1cd68..122df2c 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -124,6 +124,9 @@
     private CharSequence mTitleText;
     private CharSequence mSubtitleText;
 
+    private int mTitleTextColor;
+    private int mSubtitleTextColor;
+
     // Clear me after use.
     private final ArrayList<View> mTempViews = new ArrayList<View>();
 
@@ -498,7 +501,12 @@
                 mTitleTextView = new TextView(context);
                 mTitleTextView.setSingleLine();
                 mTitleTextView.setEllipsize(TextUtils.TruncateAt.END);
-                mTitleTextView.setTextAppearance(context, mTitleTextAppearance);
+                if (mTitleTextAppearance != 0) {
+                    mTitleTextView.setTextAppearance(context, mTitleTextAppearance);
+                }
+                if (mTitleTextColor != 0) {
+                    mTitleTextView.setTextColor(mTitleTextColor);
+                }
             }
             if (mTitleTextView.getParent() == null) {
                 addSystemView(mTitleTextView);
@@ -546,7 +554,12 @@
                 mSubtitleTextView = new TextView(context);
                 mSubtitleTextView.setSingleLine();
                 mSubtitleTextView.setEllipsize(TextUtils.TruncateAt.END);
-                mSubtitleTextView.setTextAppearance(context, mSubtitleTextAppearance);
+                if (mSubtitleTextAppearance != 0) {
+                    mSubtitleTextView.setTextAppearance(context, mSubtitleTextAppearance);
+                }
+                if (mSubtitleTextColor != 0) {
+                    mSubtitleTextView.setTextColor(mSubtitleTextColor);
+                }
             }
             if (mSubtitleTextView.getParent() == null) {
                 addSystemView(mSubtitleTextView);
@@ -583,6 +596,30 @@
     }
 
     /**
+     * Sets the text color of the title, if present.
+     *
+     * @param color The new text color in 0xAARRGGBB format
+     */
+    public void setTitleTextColor(int color) {
+        mTitleTextColor = color;
+        if (mTitleTextView != null) {
+            mTitleTextView.setTextColor(color);
+        }
+    }
+
+    /**
+     * Sets the text color of the subtitle, if present.
+     *
+     * @param color The new text color in 0xAARRGGBB format
+     */
+    public void setSubtitleTextColor(int color) {
+        mSubtitleTextColor = color;
+        if (mSubtitleTextView != null) {
+            mSubtitleTextView.setTextColor(color);
+        }
+    }
+
+    /**
      * Set the icon to use for the toolbar's navigation button.
      *
      * <p>The navigation button appears at the start of the toolbar if present. Setting an icon
@@ -598,6 +635,17 @@
     }
 
     /**
+     * Retrieve the currently configured content description for the navigation button view.
+     * This will be used to describe the navigation action to users through mechanisms such
+     * as screen readers or tooltips.
+     *
+     * @return The navigation button's content description
+     */
+    public CharSequence getNavigationContentDescription() {
+        return mNavButtonView != null ? mNavButtonView.getContentDescription() : null;
+    }
+
+    /**
      * Set a content description for the navigation button if one is present. The content
      * description will be read via screen readers or other accessibility systems to explain
      * the action of the navigation button.
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 183dd05..9d42738 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -259,11 +259,11 @@
         super.onRestoreInstanceState(savedInstanceState);
         if (mAlwaysUseOption) {
             final int checkedPos = mListView.getCheckedItemPosition();
-            final boolean enabled = checkedPos != ListView.INVALID_POSITION;
+            final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION;
             mLastSelected = checkedPos;
-            mAlwaysButton.setEnabled(enabled);
-            mOnceButton.setEnabled(enabled);
-            if (enabled) {
+            setAlwaysButtonEnabled(hasValidSelection, checkedPos);
+            mOnceButton.setEnabled(hasValidSelection);
+            if (hasValidSelection) {
                 mListView.setSelection(checkedPos);
             }
         }
@@ -274,7 +274,7 @@
         final int checkedPos = mListView.getCheckedItemPosition();
         final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION;
         if (mAlwaysUseOption && (!hasValidSelection || mLastSelected != checkedPos)) {
-            mAlwaysButton.setEnabled(hasValidSelection);
+            setAlwaysButtonEnabled(hasValidSelection, checkedPos);
             mOnceButton.setEnabled(hasValidSelection);
             if (hasValidSelection) {
                 mListView.smoothScrollToPosition(checkedPos);
@@ -285,6 +285,17 @@
         }
     }
 
+    private void setAlwaysButtonEnabled(boolean hasValidSelection, int checkedPos) {
+        boolean enabled = false;
+        if (hasValidSelection) {
+            ResolveInfo ri = mAdapter.resolveInfoForPosition(checkedPos);
+            if (ri.targetUserId == UserHandle.USER_CURRENT) {
+                enabled = true;
+            }
+        }
+        mAlwaysButton.setEnabled(enabled);
+    }
+
     public void onButtonClick(View v) {
         final int id = v.getId();
         startSelected(mListView.getCheckedItemPosition(), id == R.id.button_always);
diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java
index 58cd60d..e58d68f 100644
--- a/core/java/com/android/internal/os/ProcessCpuTracker.java
+++ b/core/java/com/android/internal/os/ProcessCpuTracker.java
@@ -442,8 +442,9 @@
                 final String[] procStatsString = mProcessFullStatsStringData;
                 final long[] procStats = mProcessFullStatsData;
                 st.base_uptime = SystemClock.uptimeMillis();
-                if (Process.readProcFile(st.statFile.toString(),
-                        PROCESS_FULL_STATS_FORMAT, procStatsString,
+                String path = st.statFile.toString();
+                //Slog.d(TAG, "Reading proc file: " + path);
+                if (Process.readProcFile(path, PROCESS_FULL_STATS_FORMAT, procStatsString,
                         procStats, null)) {
                     // This is a possible way to filter out processes that
                     // are actually kernel threads...  do we want to?  Some
diff --git a/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java b/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java
index 7fb2efd..30cd11b 100644
--- a/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java
+++ b/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java
@@ -152,6 +152,11 @@
 
         a.recycle();
 
+        if (TextUtils.isEmpty(mToolbar.getNavigationContentDescription())) {
+            mToolbar.setNavigationContentDescription(
+                    getContext().getResources().getText(R.string.action_bar_up_description));
+        }
+
         mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
             final ActionMenuItem mNavItem = new ActionMenuItem(mToolbar.getContext(),
                     0, android.R.id.home, 0, 0, mTitle);
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index a7a1faad..598d6c1 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -491,8 +491,8 @@
     char profile_duration[sizeof("-Xprofile-duration:") + PROPERTY_VALUE_MAX];
     char profile_interval[sizeof("-Xprofile-interval:") + PROPERTY_VALUE_MAX];
     char profile_backoff[sizeof("-Xprofile-backoff:") + PROPERTY_VALUE_MAX];
-    char profile_top_k_threshold[sizeof("-Xprofile-top-k-threshold") + PROPERTY_VALUE_MAX];
-    char profile_top_k_change_threshold[sizeof("-Xprofile-top-k-change-threshold") + PROPERTY_VALUE_MAX];
+    char profile_top_k_threshold[sizeof("-Xprofile-top-k-threshold:") + PROPERTY_VALUE_MAX];
+    char profile_top_k_change_threshold[sizeof("-Xprofile-top-k-change-threshold:") + PROPERTY_VALUE_MAX];
     char langOption[sizeof("-Duser.language=") + 3];
     char regionOption[sizeof("-Duser.region=") + 3];
     char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:") + sizeof(propBuf)];
diff --git a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
index 0048426..57058a6 100644
--- a/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
+++ b/core/jni/android_hardware_camera2_legacy_LegacyCameraDevice.cpp
@@ -15,6 +15,7 @@
  */
 
 #define LOG_TAG "Legacy-CameraDevice-JNI"
+// #define LOG_NDEBUG 0
 #include <utils/Log.h>
 #include <utils/Errors.h>
 #include <utils/Trace.h>
@@ -26,6 +27,7 @@
 
 #include <ui/GraphicBuffer.h>
 #include <system/window.h>
+#include <hardware/camera3.h>
 
 using namespace android;
 
@@ -118,8 +120,9 @@
         return err;
     }
 
-    ALOGV("%s: Setting buffer count to %d", __FUNCTION__,
-          maxBufferSlack + 1 + minUndequeuedBuffers);
+    ALOGV("%s: Setting buffer count to %d, size to (%dx%d), fmt (0x%x)", __FUNCTION__,
+          maxBufferSlack + 1 + minUndequeuedBuffers,
+          width, height, pixelFmt);
     err = native_window_set_buffer_count(anw.get(), maxBufferSlack + 1 + minUndequeuedBuffers);
     if (err != NO_ERROR) {
         ALOGE("%s: Failed to set native window buffer count, error %s (%d).", __FUNCTION__,
@@ -148,11 +151,29 @@
                              int32_t width, // Width of the pixelBuffer
                              int32_t height, // Height of the pixelBuffer
                              int32_t pixelFmt, // Format of the pixelBuffer
-                             int64_t bufSize) {
+                             int32_t bufSize) {
     ATRACE_CALL();
     status_t err = NO_ERROR;
     ANativeWindowBuffer* anb;
-    ALOGV("%s: Dequeue buffer from %p",__FUNCTION__, anw.get());
+    ALOGV("%s: Dequeue buffer from %p %dx%d (fmt=%x, size=%x)",
+            __FUNCTION__, anw.get(), width, height, pixelFmt, bufSize);
+
+    if (anw == 0) {
+        ALOGE("%s: anw must not be NULL", __FUNCTION__);
+        return BAD_VALUE;
+    } else if (pixelBuffer == NULL) {
+        ALOGE("%s: pixelBuffer must not be NULL", __FUNCTION__);
+        return BAD_VALUE;
+    } else if (width < 0) {
+        ALOGE("%s: width must be non-negative", __FUNCTION__);
+        return BAD_VALUE;
+    } else if (height < 0) {
+        ALOGE("%s: height must be non-negative", __FUNCTION__);
+        return BAD_VALUE;
+    } else if (bufSize < 0) {
+        ALOGE("%s: bufSize must be non-negative", __FUNCTION__);
+        return BAD_VALUE;
+    }
 
     if (width < 0 || height < 0 || bufSize < 0) {
         ALOGE("%s: Illegal argument, negative dimension passed to produceFrame", __FUNCTION__);
@@ -163,6 +184,8 @@
     err = native_window_dequeue_buffer_and_wait(anw.get(), &anb);
     if (err != NO_ERROR) return err;
 
+    // TODO: check anb is large enough to store the results
+
     sp<GraphicBuffer> buf(new GraphicBuffer(anb, /*keepOwnership*/false));
 
     switch(pixelFmt) {
@@ -257,7 +280,12 @@
                         err);
                 return err;
             }
+            struct camera3_jpeg_blob footer = {
+                jpeg_blob_id: CAMERA3_JPEG_BLOB_ID,
+                jpeg_size: (uint32_t)width
+            };
             memcpy(img, pixelBuffer, width);
+            memcpy(img + anb->width - sizeof(footer), &footer, sizeof(footer));
             break;
         }
         default: {
diff --git a/core/jni/android_server_FingerprintManager.cpp b/core/jni/android_server_FingerprintManager.cpp
index ad36843..b174d1b 100644
--- a/core/jni/android_server_FingerprintManager.cpp
+++ b/core/jni/android_server_FingerprintManager.cpp
@@ -57,21 +57,11 @@
     fingerprint_device_t *device;
 } gContext;
 
-// TODO: remove after driver update to use new HAL
-fingerprint_msg_type_t hackTilFpDriverUpdate(fingerprint_msg_type_t t) {
-    switch(static_cast<int>(t)) {
-        case 1: return FINGERPRINT_PROCESSED;
-        case 2: return FINGERPRINT_TEMPLATE_ENROLLING;
-        default: return t;
-    }
-}
-
 // Called by the HAL to notify us of fingerprint events
 static void hal_notify_callback(fingerprint_msg_t msg) {
     uint32_t arg1 = 0;
     uint32_t arg2 = 0;
     uint32_t arg3 = 0; // TODO
-    msg.type = hackTilFpDriverUpdate(msg.type);
     switch (msg.type) {
         case FINGERPRINT_ERROR:
             arg1 = msg.data.error;
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 01f4d3a..a6b65cc 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -45,6 +45,8 @@
 #define POLICY_DEBUG 0
 #define GUARD_THREAD_PRIORITY 0
 
+#define DEBUG_PROC(x) //x
+
 using namespace android;
 
 #if GUARD_THREAD_PRIORITY
@@ -725,6 +727,7 @@
         const char term = (char)(mode&PROC_TERM_MASK);
         const jsize start = i;
         if (i >= endIndex) {
+            DEBUG_PROC(ALOGW("Ran off end of data @%d", i));
             res = JNI_FALSE;
             break;
         }
@@ -822,19 +825,20 @@
         return JNI_FALSE;
     }
     int fd = open(file8, O_RDONLY);
-    env->ReleaseStringUTFChars(file, file8);
 
     if (fd < 0) {
-        //ALOGW("Unable to open process file: %s\n", file8);
+        DEBUG_PROC(ALOGW("Unable to open process file: %s\n", file8));
+        env->ReleaseStringUTFChars(file, file8);
         return JNI_FALSE;
     }
+    env->ReleaseStringUTFChars(file, file8);
 
     char buffer[256];
     const int len = read(fd, buffer, sizeof(buffer)-1);
     close(fd);
 
     if (len < 0) {
-        //ALOGW("Unable to open process file: %s fd=%d\n", file8, fd);
+        DEBUG_PROC(ALOGW("Unable to open process file: %s fd=%d\n", file8, fd));
         return JNI_FALSE;
     }
     buffer[len] = 0;
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 4362018..2a1fd1b 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -20,15 +20,10 @@
 #include "GraphicsJNI.h"
 #include <nativehelper/JNIHelp.h>
 
-#include "android_view_GraphicBuffer.h"
-
 #include <android_runtime/AndroidRuntime.h>
-#include <android_runtime/android_graphics_SurfaceTexture.h>
 
 #include <androidfw/ResourceTypes.h>
 
-#include <gui/GLConsumer.h>
-
 #include <private/hwui/DrawGlInfo.h>
 
 #include <cutils/properties.h>
@@ -37,15 +32,13 @@
 #include <SkCanvas.h>
 #include <SkMatrix.h>
 #include <SkPaint.h>
+#include <SkPorterDuff.h>
 #include <SkRegion.h>
 #include <SkScalerContext.h>
 #include <SkTemplates.h>
 #include <SkXfermode.h>
 
 #include <DisplayListRenderer.h>
-#include <LayerRenderer.h>
-#include <OpenGLRenderer.h>
-#include <Stencil.h>
 #include <Rect.h>
 #include <RenderNode.h>
 #include <CanvasProperty.h>
@@ -64,7 +57,7 @@
 using namespace uirenderer;
 
 /**
- * Note: OpenGLRenderer JNI layer is generated and compiled only on supported
+ * Note: DisplayListRenderer JNI layer is generated and compiled only on supported
  *       devices. This means all the logic must be compiled only when the
  *       preprocessor variable USE_OPENGL_RENDERER is defined.
  */
@@ -96,8 +89,8 @@
 
 static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject clazz,
         jlong rendererPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
-    RENDERER_LOGD("Destroy OpenGLRenderer");
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
+    RENDERER_LOGD("Destroy DisplayListRenderer");
     delete renderer;
 }
 
@@ -107,26 +100,26 @@
 
 static void android_view_GLES20Canvas_setViewport(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jint width, jint height) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     renderer->setViewport(width, height);
 }
 
 static int android_view_GLES20Canvas_prepare(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jboolean opaque) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     return renderer->prepare(opaque);
 }
 
 static int android_view_GLES20Canvas_prepareDirty(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jint left, jint top, jint right, jint bottom,
         jboolean opaque) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     return renderer->prepareDirty(left, top, right, bottom, opaque);
 }
 
 static void android_view_GLES20Canvas_finish(JNIEnv* env, jobject clazz,
         jlong rendererPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     renderer->finish();
 }
 
@@ -154,7 +147,7 @@
 
 static jint android_view_GLES20Canvas_callDrawGLFunction(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jlong functorPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     Functor* functor = reinterpret_cast<Functor*>(functorPtr);
     android::uirenderer::Rect dirty;
     return renderer->callDrawGLFunction(functor, dirty);
@@ -178,25 +171,25 @@
 
 static jint android_view_GLES20Canvas_save(JNIEnv* env, jobject clazz, jlong rendererPtr,
         jint flags) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     return renderer->save(flags);
 }
 
 static jint android_view_GLES20Canvas_getSaveCount(JNIEnv* env, jobject clazz,
         jlong rendererPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     return renderer->getSaveCount();
 }
 
 static void android_view_GLES20Canvas_restore(JNIEnv* env, jobject clazz,
         jlong rendererPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     renderer->restore();
 }
 
 static void android_view_GLES20Canvas_restoreToCount(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jint saveCount) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     renderer->restoreToCount(saveCount);
 }
 
@@ -207,14 +200,14 @@
 static jint android_view_GLES20Canvas_saveLayer(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
         jlong paintPtr, jint saveFlags) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     return renderer->saveLayer(left, top, right, bottom, paint, saveFlags);
 }
 
 static jint android_view_GLES20Canvas_saveLayerClip(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jlong paintPtr, jint saveFlags) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
     return renderer->saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom,
@@ -224,13 +217,13 @@
 static jint android_view_GLES20Canvas_saveLayerAlpha(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
         jint alpha, jint saveFlags) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     return renderer->saveLayerAlpha(left, top, right, bottom, alpha, saveFlags);
 }
 
 static jint android_view_GLES20Canvas_saveLayerAlphaClip(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jint alpha, jint saveFlags) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
     return renderer->saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
             alpha, saveFlags);
@@ -242,7 +235,7 @@
 
 static jboolean android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     const bool result = renderer->quickRejectConservative(left, top, right, bottom);
     return result ? JNI_TRUE : JNI_FALSE;
 }
@@ -250,7 +243,7 @@
 static jboolean android_view_GLES20Canvas_clipRectF(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
         jint op) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     const bool result = renderer->clipRect(left, top, right, bottom,
                                            static_cast<SkRegion::Op>(op));
     return result ? JNI_TRUE : JNI_FALSE;
@@ -259,7 +252,7 @@
 static jboolean android_view_GLES20Canvas_clipRect(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jint left, jint top, jint right, jint bottom,
         jint op) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     const bool result = renderer->clipRect(float(left), float(top), float(right),
                                            float(bottom),
                                            static_cast<SkRegion::Op>(op));
@@ -268,7 +261,7 @@
 
 static jboolean android_view_GLES20Canvas_clipPath(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jlong pathPtr, jint op) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
     const bool result = renderer->clipPath(path, static_cast<SkRegion::Op>(op));
     return result ? JNI_TRUE : JNI_FALSE;
@@ -276,7 +269,7 @@
 
 static jboolean android_view_GLES20Canvas_clipRegion(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jlong regionPtr, jint op) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     SkRegion* region = reinterpret_cast<SkRegion*>(regionPtr);
     const bool result = renderer->clipRegion(region, static_cast<SkRegion::Op>(op));
     return result ? JNI_TRUE : JNI_FALSE;
@@ -284,7 +277,7 @@
 
 static jboolean android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jobject rect) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
 
     env->CallVoidMethod(rect, gRectClassInfo.set,
@@ -299,45 +292,45 @@
 
 static void android_view_GLES20Canvas_translate(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jfloat dx, jfloat dy) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     renderer->translate(dx, dy);
 }
 
 static void android_view_GLES20Canvas_rotate(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jfloat degrees) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     renderer->rotate(degrees);
 }
 
 static void android_view_GLES20Canvas_scale(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jfloat sx, jfloat sy) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     renderer->scale(sx, sy);
 }
 
 static void android_view_GLES20Canvas_skew(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jfloat sx, jfloat sy) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     renderer->skew(sx, sy);
 }
 
 static void android_view_GLES20Canvas_setMatrix(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jlong matrixPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
     renderer->setMatrix(matrix ? *matrix : SkMatrix::I());
 }
 
 static void android_view_GLES20Canvas_getMatrix(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jlong matrixPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
     renderer->getMatrix(matrix);
 }
 
 static void android_view_GLES20Canvas_concatMatrix(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jlong matrixPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
     renderer->concatMatrix(*matrix);
 }
@@ -353,7 +346,7 @@
     // This object allows the renderer to allocate a global JNI ref to the buffer object.
     JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
 
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     renderer->drawBitmap(bitmap, left, top, paint);
 }
@@ -366,7 +359,7 @@
     // This object allows the renderer to allocate a global JNI ref to the buffer object.
     JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
 
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     renderer->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
             dstLeft, dstTop, dstRight, dstBottom, paint);
@@ -379,7 +372,7 @@
     // This object allows the renderer to allocate a global JNI ref to the buffer object.
     JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
 
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     renderer->drawBitmap(bitmap, *matrix, paint);
@@ -402,7 +395,7 @@
         return;
     }
 
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     renderer->drawBitmapData(bitmap, left, top, paint);
 
@@ -423,7 +416,7 @@
     jfloat* verticesArray = vertices ? env->GetFloatArrayElements(vertices, NULL) + offset : NULL;
     jint* colorsArray = colors ? env->GetIntArrayElements(colors, NULL) + colorOffset : NULL;
 
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     renderer->drawBitmapMesh(bitmap, meshWidth, meshHeight, verticesArray, colorsArray, paint);
 
@@ -438,22 +431,23 @@
     // This object allows the renderer to allocate a global JNI ref to the buffer object.
     JavaHeapBitmapRef bitmapRef(env, bitmap, buffer);
 
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     Res_png_9patch* patch = reinterpret_cast<Res_png_9patch*>(patchPtr);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     renderer->drawPatch(bitmap, patch, left, top, right, bottom, paint);
 }
 
 static void android_view_GLES20Canvas_drawColor(JNIEnv* env, jobject clazz,
-        jlong rendererPtr, jint color, jint mode) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
-    renderer->drawColor(color, static_cast<SkXfermode::Mode>(mode));
+        jlong rendererPtr, jint color, jint modeHandle) {
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
+    SkPorterDuff::Mode mode = static_cast<SkPorterDuff::Mode>(modeHandle);
+    renderer->drawColor(color, SkPorterDuff::ToXfermodeMode(mode));
 }
 
 static void android_view_GLES20Canvas_drawRect(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
         jlong paintPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     renderer->drawRect(left, top, right, bottom, paint);
 }
@@ -461,21 +455,21 @@
 static void android_view_GLES20Canvas_drawRoundRect(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
         jfloat rx, jfloat ry, jlong paintPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     renderer->drawRoundRect(left, top, right, bottom, rx, ry, paint);
 }
 
 static void android_view_GLES20Canvas_drawCircle(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jfloat x, jfloat y, jfloat radius, jlong paintPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     renderer->drawCircle(x, y, radius, paint);
 }
 
 static void android_view_GLES20Canvas_drawCircleProps(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jlong xPropPtr, jlong yPropPtr, jlong radiusPropPtr, jlong paintPropPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr);
     CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr);
     CanvasPropertyPrimitive* radiusProp = reinterpret_cast<CanvasPropertyPrimitive*>(radiusPropPtr);
@@ -486,7 +480,7 @@
 static void android_view_GLES20Canvas_drawOval(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
         jlong paintPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     renderer->drawOval(left, top, right, bottom, paint);
 }
@@ -494,14 +488,14 @@
 static void android_view_GLES20Canvas_drawArc(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom,
         jfloat startAngle, jfloat sweepAngle, jboolean useCenter, jlong paintPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     renderer->drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);
 }
 
 static void android_view_GLES20Canvas_drawRegionAsRects(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jlong regionPtr, jlong paintPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     SkRegion* region = reinterpret_cast<SkRegion*>(regionPtr);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     if (paint->getStyle() != SkPaint::kFill_Style ||
@@ -531,7 +525,7 @@
 
 static void android_view_GLES20Canvas_drawPoints(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jfloatArray points, jint offset, jint count, jlong paintPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     jfloat* storage = env->GetFloatArrayElements(points, NULL);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     renderer->drawPoints(storage + offset, count, paint);
@@ -540,7 +534,7 @@
 
 static void android_view_GLES20Canvas_drawPath(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jlong pathPtr, jlong paintPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     renderer->drawPath(path, paint);
@@ -548,7 +542,7 @@
 
 static void android_view_GLES20Canvas_drawLines(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jfloatArray points, jint offset, jint count, jlong paintPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     jfloat* storage = env->GetFloatArrayElements(points, NULL);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     renderer->drawLines(storage + offset, count, paint);
@@ -561,13 +555,13 @@
 
 static void android_view_GLES20Canvas_setupPaintFilter(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jint clearBits, jint setBits) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     renderer->setupPaintFilter(clearBits, setBits);
 }
 
 static void android_view_GLES20Canvas_resetPaintFilter(JNIEnv* env, jobject clazz,
         jlong rendererPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     renderer->resetPaintFilter();
 }
 
@@ -594,7 +588,7 @@
 
 class RenderTextFunctor {
 public:
-    RenderTextFunctor(const Layout& layout, OpenGLRenderer* renderer, jfloat x, jfloat y,
+    RenderTextFunctor(const Layout& layout, DisplayListRenderer* renderer, jfloat x, jfloat y,
                 SkPaint* paint, uint16_t* glyphs, float* pos, float totalAdvance,
                 uirenderer::Rect& bounds)
             : layout(layout), renderer(renderer), x(x), y(y), paint(paint), glyphs(glyphs),
@@ -612,7 +606,7 @@
     }
 private:
     const Layout& layout;
-    OpenGLRenderer* renderer;
+    DisplayListRenderer* renderer;
     jfloat x;
     jfloat y;
     SkPaint* paint;
@@ -622,7 +616,7 @@
     uirenderer::Rect& bounds;
 };
 
-static void renderTextLayout(OpenGLRenderer* renderer, Layout* layout,
+static void renderTextLayout(DisplayListRenderer* renderer, Layout* layout,
     jfloat x, jfloat y, SkPaint* paint) {
     size_t nGlyphs = layout->nGlyphs();
     float* pos = new float[nGlyphs * 2];
@@ -640,7 +634,7 @@
 }
 #endif
 
-static void renderText(OpenGLRenderer* renderer, const jchar* text, int count,
+static void renderText(DisplayListRenderer* renderer, const jchar* text, int count,
         jfloat x, jfloat y, int bidiFlags, SkPaint* paint, TypefaceImpl* typeface) {
 #ifdef USE_MINIKIN
     Layout layout;
@@ -672,7 +666,7 @@
 #ifdef USE_MINIKIN
 class RenderTextOnPathFunctor {
 public:
-    RenderTextOnPathFunctor(const Layout& layout, OpenGLRenderer* renderer, float hOffset,
+    RenderTextOnPathFunctor(const Layout& layout, DisplayListRenderer* renderer, float hOffset,
                 float vOffset, SkPaint* paint, SkPath* path)
             : layout(layout), renderer(renderer), hOffset(hOffset), vOffset(vOffset),
                 paint(paint), path(path) {
@@ -688,7 +682,7 @@
     }
 private:
     const Layout& layout;
-    OpenGLRenderer* renderer;
+    DisplayListRenderer* renderer;
     float hOffset;
     float vOffset;
     SkPaint* paint;
@@ -696,7 +690,7 @@
 };
 #endif
 
-static void renderTextOnPath(OpenGLRenderer* renderer, const jchar* text, int count,
+static void renderTextOnPath(DisplayListRenderer* renderer, const jchar* text, int count,
         SkPath* path, jfloat hOffset, jfloat vOffset, int bidiFlags, SkPaint* paint,
         TypefaceImpl* typeface) {
 #ifdef USE_MINIKIN
@@ -724,7 +718,7 @@
 #endif
 }
 
-static void renderTextRun(OpenGLRenderer* renderer, const jchar* text,
+static void renderTextRun(DisplayListRenderer* renderer, const jchar* text,
         jint start, jint count, jint contextCount, jfloat x, jfloat y,
         int bidiFlags, SkPaint* paint, TypefaceImpl* typeface) {
 #ifdef USE_MINIKIN
@@ -757,7 +751,7 @@
 static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jcharArray text, jint index, jint count,
         jfloat x, jfloat y, jint bidiFlags, jlong paintPtr, jlong typefacePtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     jchar* textArray = env->GetCharArrayElements(text, NULL);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
@@ -769,7 +763,7 @@
 static void android_view_GLES20Canvas_drawText(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jstring text, jint start, jint end,
         jfloat x, jfloat y, jint bidiFlags, jlong paintPtr, jlong typefacePtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     const jchar* textArray = env->GetStringChars(text, NULL);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
@@ -782,7 +776,7 @@
         jlong rendererPtr, jcharArray text, jint index, jint count,
         jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr,
         jlong typefacePtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     jchar* textArray = env->GetCharArrayElements(text, NULL);
     SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
@@ -797,7 +791,7 @@
         jlong rendererPtr, jstring text, jint start, jint end,
         jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr,
         jlong typefacePtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     const jchar* textArray = env->GetStringChars(text, NULL);
     SkPath* path = reinterpret_cast<SkPath*>(pathPtr);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
@@ -812,7 +806,7 @@
         jlong rendererPtr, jcharArray text, jint index, jint count,
         jint contextIndex, jint contextCount, jfloat x, jfloat y, jboolean isRtl,
         jlong paintPtr, jlong typefacePtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     jchar* textArray = env->GetCharArrayElements(text, NULL);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
     TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr);
@@ -827,7 +821,7 @@
         jlong rendererPtr, jstring text, jint start, jint end,
         jint contextStart, int contextEnd, jfloat x, jfloat y, jboolean isRtl,
         jlong paintPtr, jlong typefacePtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     const jchar* textArray = env->GetStringChars(text, NULL);
     jint count = end - start;
     jint contextCount = contextEnd - contextStart;
@@ -854,13 +848,13 @@
     return reinterpret_cast<jlong>(new DisplayListRenderer);
 }
 
-static jint android_view_GLES20Canvas_drawDisplayList(JNIEnv* env,
-        jobject clazz, jlong rendererPtr, jlong displayListPtr,
+static jint android_view_GLES20Canvas_drawRenderNode(JNIEnv* env,
+        jobject clazz, jlong rendererPtr, jlong renderNodePtr,
         jobject dirty, jint flags) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     android::uirenderer::Rect bounds;
-    status_t status = renderer->drawDisplayList(displayList, bounds, flags);
+    status_t status = renderer->drawRenderNode(renderNode, bounds, flags);
     if (status != DrawGlInfo::kStatusDone && dirty != NULL) {
         env->CallVoidMethod(dirty, gRectClassInfo.set,
                 int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
@@ -874,7 +868,7 @@
 
 static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jlong layerPtr, jfloat x, jfloat y) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
+    DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr);
     Layer* layer = reinterpret_cast<Layer*>(layerPtr);
     renderer->drawLayer(layer, x, y);
 }
@@ -996,12 +990,10 @@
     { "nDrawTextRun",       "(JLjava/lang/String;IIIIFFZJJ)V",
             (void*) android_view_GLES20Canvas_drawTextRun },
 
-    { "nGetClipBounds",     "(JLandroid/graphics/Rect;)Z",
-            (void*) android_view_GLES20Canvas_getClipBounds },
+    { "nGetClipBounds",     "(JLandroid/graphics/Rect;)Z", (void*) android_view_GLES20Canvas_getClipBounds },
 
-    { "nFinishRecording",        "(J)J",      (void*) android_view_GLES20Canvas_finishRecording },
-    { "nDrawDisplayList",        "(JJLandroid/graphics/Rect;I)I",
-            (void*) android_view_GLES20Canvas_drawDisplayList },
+    { "nFinishRecording",   "(J)J",      (void*) android_view_GLES20Canvas_finishRecording },
+    { "nDrawRenderNode",    "(JJLandroid/graphics/Rect;I)I", (void*) android_view_GLES20Canvas_drawRenderNode },
 
     { "nCreateDisplayListRenderer", "()J",     (void*) android_view_GLES20Canvas_createDisplayListRenderer },
 
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 2b94b65..3e62d0b 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -76,26 +76,6 @@
     jobject mRunnable;
 };
 
-class SetAtlasTask : public RenderTask {
-public:
-    SetAtlasTask(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size)
-            : mBuffer(buffer)
-            , mMap(map)
-            , mMapSize(size) {
-    }
-
-    virtual void run() {
-        CanvasContext::setTextureAtlas(mBuffer, mMap, mMapSize);
-        mMap = 0;
-        delete this;
-    }
-
-private:
-    sp<GraphicBuffer> mBuffer;
-    int64_t* mMap;
-    size_t mMapSize;
-};
-
 class OnFinishedEvent {
 public:
     OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener)
@@ -193,7 +173,7 @@
 };
 
 static void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz,
-        jobject graphicBuffer, jlongArray atlasMapArray) {
+        jlong proxyPtr, jobject graphicBuffer, jlongArray atlasMapArray) {
     sp<GraphicBuffer> buffer = graphicBufferForJavaObject(env, graphicBuffer);
     jsize len = env->GetArrayLength(atlasMapArray);
     if (len <= 0) {
@@ -203,8 +183,8 @@
     int64_t* map = new int64_t[len];
     env->GetLongArrayRegion(atlasMapArray, 0, len, map);
 
-    SetAtlasTask* task = new SetAtlasTask(buffer, map, len);
-    RenderThread::getInstance().queue(task);
+    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+    proxy->setTextureAtlas(buffer, map, len);
 }
 
 static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
@@ -291,10 +271,9 @@
 }
 
 static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jlong functorPtr, jboolean waitForCompletion) {
-    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
+        jlong functorPtr, jboolean waitForCompletion) {
     Functor* functor = reinterpret_cast<Functor*>(functorPtr);
-    proxy->invokeFunctor(functor, waitForCompletion);
+    RenderProxy::invokeFunctor(functor, waitForCompletion);
 }
 
 static void android_view_ThreadedRenderer_runWithGlContext(JNIEnv* env, jobject clazz,
@@ -387,7 +366,7 @@
 
 static JNINativeMethod gMethods[] = {
 #ifdef USE_OPENGL_RENDERER
-    { "nSetAtlas", "(Landroid/view/GraphicBuffer;[J)V",   (void*) android_view_ThreadedRenderer_setAtlas },
+    { "nSetAtlas", "(JLandroid/view/GraphicBuffer;[J)V",   (void*) android_view_ThreadedRenderer_setAtlas },
     { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
     { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
     { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
@@ -400,7 +379,7 @@
     { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque },
     { "nSyncAndDrawFrame", "(JJJF)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
     { "nDestroyCanvasAndSurface", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvasAndSurface },
-    { "nInvokeFunctor", "(JJZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
+    { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
     { "nRunWithGlContext", "(JLjava/lang/Runnable;)V", (void*) android_view_ThreadedRenderer_runWithGlContext },
     { "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer },
     { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer },
diff --git a/core/res/res/layout/alert_dialog_leanback.xml b/core/res/res/layout/alert_dialog_leanback.xml
index 8655aea..848015c 100644
--- a/core/res/res/layout/alert_dialog_leanback.xml
+++ b/core/res/res/layout/alert_dialog_leanback.xml
@@ -1,20 +1,18 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-/*
-** Copyright 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) 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.
 -->
 
 <LinearLayout
@@ -22,11 +20,13 @@
     android:id="@+id/parentPanel"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:background="@drawable/dialog_background_material"
+    android:translationZ="@dimen/floating_window_z"
     android:layout_marginLeft="@dimen/leanback_alert_dialog_horizontal_margin"
-    android:layout_marginRight="@dimen/leanback_alert_dialog_horizontal_margin"
     android:layout_marginTop="@dimen/leanback_alert_dialog_vertical_margin"
-    android:layout_marginBottom="@dimen/leanback_alert_dialog_vertical_margin"
-    android:orientation="vertical">
+    android:layout_marginRight="@dimen/leanback_alert_dialog_horizontal_margin"
+    android:layout_marginBottom="@dimen/leanback_alert_dialog_vertical_margin">
 
     <LinearLayout android:id="@+id/topPanel"
         android:layout_width="match_parent"
@@ -37,16 +37,17 @@
             android:layout_height="wrap_content"
             android:orientation="horizontal"
             android:gravity="center_vertical|start"
-            android:minHeight="@dimen/alert_dialog_title_height"
-            android:layout_marginStart="16dip"
-            android:layout_marginEnd="16dip">
+            android:paddingStart="16dip"
+            android:paddingEnd="16dip"
+            android:paddingTop="16dip">
             <ImageView android:id="@+id/icon"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:paddingEnd="8dip"
+                android:layout_width="32dip"
+                android:layout_height="32dip"
+                android:layout_marginEnd="8dip"
+                android:scaleType="fitCenter"
                 android:src="@null" />
-            <com.android.internal.widget.DialogTitle android:id="@+id/alertTitle"
-                style="?android:attr/windowTitleStyle"
+            <TextView android:id="@+id/alertTitle"
+                style="?attr/windowTitleStyle"
                 android:singleLine="true"
                 android:ellipsize="end"
                 android:layout_width="match_parent"
@@ -67,13 +68,12 @@
             android:layout_height="wrap_content"
             android:clipToPadding="false">
             <TextView android:id="@+id/message"
-                style="?android:attr/textAppearanceMedium"
+                style="?attr/textAppearanceMedium"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:paddingStart="16dip"
                 android:paddingEnd="16dip"
-                android:paddingTop="8dip"
-                android:paddingBottom="8dip"/>
+                android:paddingTop="16dip" />
         </ScrollView>
     </LinearLayout>
 
@@ -91,41 +91,32 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:minHeight="@dimen/alert_dialog_button_bar_height"
-        android:orientation="vertical">
+        android:orientation="vertical"
+        android:gravity="end"
+        android:padding="16dip">
         <LinearLayout
-            style="?android:attr/buttonBarStyle"
-            android:layout_width="match_parent"
+            style="?attr/buttonBarStyle"
+            android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:orientation="horizontal"
-            android:layoutDirection="locale"
-            android:measureWithLargestChild="true">
-            <Button android:id="@+id/button2"
-                android:layout_width="wrap_content"
-                android:layout_gravity="start"
-                android:layout_weight="1"
-                android:maxLines="2"
-                style="?android:attr/buttonBarButtonStyle"
-                android:textSize="14sp"
-                android:minHeight="@dimen/alert_dialog_button_bar_height"
-                android:layout_height="wrap_content" />
+            android:layoutDirection="locale">
             <Button android:id="@+id/button3"
+                style="?attr/buttonBarButtonStyle"
                 android:layout_width="wrap_content"
-                android:layout_gravity="center_horizontal"
-                android:layout_weight="1"
+                android:layout_height="wrap_content"
                 android:maxLines="2"
-                style="?android:attr/buttonBarButtonStyle"
-                android:textSize="14sp"
-                android:minHeight="@dimen/alert_dialog_button_bar_height"
-                android:layout_height="wrap_content" />
+                android:minHeight="@dimen/alert_dialog_button_bar_height" />
+            <Button android:id="@+id/button2"
+                style="?attr/buttonBarButtonStyle"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:maxLines="2"
+                android:minHeight="@dimen/alert_dialog_button_bar_height" />
             <Button android:id="@+id/button1"
+                style="?attr/buttonBarButtonStyle"
                 android:layout_width="wrap_content"
-                android:layout_gravity="end"
-                android:layout_weight="1"
+                android:layout_height="wrap_content"
                 android:maxLines="2"
-                android:minHeight="@dimen/alert_dialog_button_bar_height"
-                style="?android:attr/buttonBarButtonStyle"
-                android:textSize="14sp"
-                android:layout_height="wrap_content" />
+                android:minHeight="@dimen/alert_dialog_button_bar_height" />
         </LinearLayout>
      </LinearLayout>
 </LinearLayout>
diff --git a/core/res/res/layout/alert_dialog_leanback_button_panel_right.xml b/core/res/res/layout/alert_dialog_leanback_button_panel_right.xml
index 096b015..829d5aa 100644
--- a/core/res/res/layout/alert_dialog_leanback_button_panel_right.xml
+++ b/core/res/res/layout/alert_dialog_leanback_button_panel_right.xml
@@ -1,20 +1,18 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-/*
-** Copyright 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) 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.
 -->
 
 <LinearLayout
@@ -22,18 +20,20 @@
     android:id="@+id/parentPanel"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
+    android:orientation="horizontal"
+    android:background="@drawable/dialog_background_material"
+    android:translationZ="@dimen/floating_window_z"
     android:layout_marginLeft="@dimen/leanback_alert_dialog_horizontal_margin"
-    android:layout_marginRight="@dimen/leanback_alert_dialog_horizontal_margin"
     android:layout_marginTop="@dimen/leanback_alert_dialog_vertical_margin"
-    android:layout_marginBottom="@dimen/leanback_alert_dialog_vertical_margin"
-    android:orientation="horizontal">
+    android:layout_marginRight="@dimen/leanback_alert_dialog_horizontal_margin"
+    android:layout_marginBottom="@dimen/leanback_alert_dialog_vertical_margin">
 
-  <LinearLayout
-      android:id="@+id/leftPanel"
-      android:layout_width="0dp"
-      android:layout_weight="0.66"
-      android:layout_height="wrap_content"
-      android:orientation="vertical">
+   <LinearLayout
+       android:id="@+id/leftPanel"
+       android:layout_width="0dp"
+       android:layout_weight="1"
+       android:layout_height="wrap_content"
+       android:orientation="vertical">
 
     <LinearLayout android:id="@+id/topPanel"
         android:layout_width="match_parent"
@@ -44,16 +44,17 @@
             android:layout_height="wrap_content"
             android:orientation="horizontal"
             android:gravity="center_vertical|start"
-            android:minHeight="@dimen/alert_dialog_title_height"
-            android:layout_marginStart="16dip"
-            android:layout_marginEnd="16dip">
+            android:paddingStart="16dip"
+            android:paddingEnd="16dip"
+            android:paddingTop="16dip">
             <ImageView android:id="@+id/icon"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:paddingEnd="8dip"
+                android:layout_width="32dip"
+                android:layout_height="32dip"
+                android:layout_marginEnd="8dip"
+                android:scaleType="fitCenter"
                 android:src="@null" />
-            <com.android.internal.widget.DialogTitle android:id="@+id/alertTitle"
-                style="?android:attr/windowTitleStyle"
+            <TextView android:id="@+id/alertTitle"
+                style="?attr/windowTitleStyle"
                 android:singleLine="true"
                 android:ellipsize="end"
                 android:layout_width="match_parent"
@@ -66,6 +67,7 @@
     <LinearLayout android:id="@+id/contentPanel"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
+        android:layout_weight="1"
         android:orientation="vertical"
         android:minHeight="64dp">
         <ScrollView android:id="@+id/scrollView"
@@ -73,13 +75,13 @@
             android:layout_height="wrap_content"
             android:clipToPadding="false">
             <TextView android:id="@+id/message"
-                style="?android:attr/textAppearanceMedium"
+                style="?attr/textAppearanceMedium"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:paddingStart="16dip"
                 android:paddingEnd="16dip"
-                android:paddingTop="8dip"
-                android:paddingBottom="8dip"/>
+                android:paddingTop="16dip"
+		android:paddingBottom="16dip" />
         </ScrollView>
     </LinearLayout>
 
@@ -92,51 +94,41 @@
             android:layout_width="match_parent"
             android:layout_height="wrap_content" />
     </FrameLayout>
-  </LinearLayout>
+    </LinearLayout>
 
     <LinearLayout android:id="@+id/buttonPanel"
-        android:layout_width="0dp"
-	android:layout_weight="0.33"
-        android:layout_height="match_parent"
+        android:layout_width="wrap_content"
+android:background="#ffffff"
+        android:layout_height="wrap_content"
+	android:layout_gravity="center_vertical"
         android:minHeight="@dimen/alert_dialog_button_bar_height"
-	android:paddingLeft="32dp"
-	android:paddingRight="32dp"
-        android:orientation="horizontal">
+        android:orientation="vertical"
+        android:gravity="end"
+        android:padding="16dip">
         <LinearLayout
-            style="?android:attr/buttonBarStyle"
-            android:layout_width="match_parent"
+            style="?attr/buttonBarStyle"
+            android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-	    android:layout_gravity="center_vertical"
-            android:orientation="vertical"
             android:layoutDirection="locale"
-            android:measureWithLargestChild="true">
-            <Button android:id="@+id/button1"
-                android:layout_width="match_parent"
-                android:gravity="center_vertical"
-                android:layout_weight="1"
-                android:maxLines="2"
-                style="?android:attr/buttonBarButtonStyle"
-                android:textSize="14sp"
-                android:minHeight="@dimen/alert_dialog_button_bar_height"
-                android:layout_height="wrap_content" />
+	    android:orientation="vertical">
             <Button android:id="@+id/button3"
+                style="?attr/buttonBarButtonStyle"
                 android:layout_width="match_parent"
-                android:gravity="center_vertical"
-                android:layout_weight="1"
+                android:layout_height="wrap_content"
                 android:maxLines="2"
-                style="?android:attr/buttonBarButtonStyle"
-                android:textSize="14sp"
-                android:minHeight="@dimen/alert_dialog_button_bar_height"
-                android:layout_height="wrap_content" />
+                android:minHeight="@dimen/alert_dialog_button_bar_height" />
             <Button android:id="@+id/button2"
+                style="?attr/buttonBarButtonStyle"
                 android:layout_width="match_parent"
-                android:gravity="center_vertical"
-                android:layout_weight="1"
+                android:layout_height="wrap_content"
                 android:maxLines="2"
-                android:minHeight="@dimen/alert_dialog_button_bar_height"
-                style="?android:attr/buttonBarButtonStyle"
-                android:textSize="14sp"
-                android:layout_height="wrap_content" />
+                android:minHeight="@dimen/alert_dialog_button_bar_height" />
+            <Button android:id="@+id/button1"
+                style="?attr/buttonBarButtonStyle"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:maxLines="2"
+                android:minHeight="@dimen/alert_dialog_button_bar_height" />
         </LinearLayout>
      </LinearLayout>
 </LinearLayout>
diff --git a/core/res/res/layout/progress_dialog_leanback.xml b/core/res/res/layout/progress_dialog_leanback.xml
deleted file mode 100644
index 6bcad7a..0000000
--- a/core/res/res/layout/progress_dialog_leanback.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 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.
-*/
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:orientation="vertical">
-
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="2dip"
-        android:background="@android:color/leanback_dark_gray" />
-    <LinearLayout android:id="@+id/body"
-        android:orientation="horizontal"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:baselineAligned="false"
-        android:padding="16dip">
-
-        <ProgressBar android:id="@android:id/progress"
-            style="?android:attr/progressBarStyle"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:max="10000"
-            android:layout_marginEnd="16dip" />
-
-        <TextView android:id="@+id/message"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_gravity="center_vertical" />
-    </LinearLayout>
-</LinearLayout>
diff --git a/core/res/res/layout/screen_action_bar.xml b/core/res/res/layout/screen_action_bar.xml
index 8bf8416..5acb588 100644
--- a/core/res/res/layout/screen_action_bar.xml
+++ b/core/res/res/layout/screen_action_bar.xml
@@ -34,7 +34,7 @@
         android:layout_height="wrap_content"
         android:layout_alignParentTop="true"
         style="?attr/actionBarStyle"
-        android:viewName="android:action_bar"
+        android:transitionName="android:action_bar"
         android:gravity="top">
         <com.android.internal.widget.ActionBarView
             android:id="@+id/action_bar"
diff --git a/core/res/res/layout/screen_custom_title.xml b/core/res/res/layout/screen_custom_title.xml
index c8952bf..b385bed 100644
--- a/core/res/res/layout/screen_custom_title.xml
+++ b/core/res/res/layout/screen_custom_title.xml
@@ -31,7 +31,7 @@
     <FrameLayout android:id="@android:id/title_container" 
         android:layout_width="match_parent" 
         android:layout_height="?android:attr/windowTitleSize"
-        android:viewName="android:title"
+        android:transitionName="android:title"
         style="?android:attr/windowTitleBackgroundStyle">
     </FrameLayout>
     <FrameLayout android:id="@android:id/content"
diff --git a/core/res/res/layout/screen_toolbar.xml b/core/res/res/layout/screen_toolbar.xml
index 290c7da..56815f8 100644
--- a/core/res/res/layout/screen_toolbar.xml
+++ b/core/res/res/layout/screen_toolbar.xml
@@ -34,7 +34,7 @@
         android:layout_height="wrap_content"
         android:layout_alignParentTop="true"
         style="?attr/actionBarStyle"
-        android:viewName="android:action_bar"
+        android:transitionName="android:action_bar"
         android:gravity="top">
         <Toolbar
             android:id="@+id/action_bar"
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index cb93530..60fa084 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -189,7 +189,7 @@
     <string name="safeMode" msgid="2788228061547930246">"Veiligmodus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-stelsel"</string>
     <string name="user_owner_label" msgid="6465364741001216388">"Persoonlike programme"</string>
-    <string name="managed_profile_label" msgid="4287077106125758391">"Android Werk"</string>
+    <string name="managed_profile_label" msgid="4287077106125758391">"Android-werk"</string>
     <string name="permgrouplab_costMoney" msgid="5429808217861460401">"Dienste wat jou geld kos"</string>
     <string name="permgroupdesc_costMoney" msgid="3293301903409869495">"Doen dinge wat jou geld kan kos."</string>
     <string name="permgrouplab_messages" msgid="7521249148445456662">"Jou boodskappe"</string>
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Kies jaar"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> gekies"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> uitgevee"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"Werk-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Gebruik Sluit-na-program?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Sluit-na-program sluit die skerm in \'n enkele program.\n\nOm uit te gaan, druk en hou die knoppie vir onlangse programme $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"NEE"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"BEGIN"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Begin Sluit-na-program"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Gaan uit Sluit-na-program"</string>
 </resources>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 66faf61..7a08236 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1725,4 +1725,17 @@
     <string name="select_year" msgid="7952052866994196170">"ዓመት ይምረጡ"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> ተመርጧል"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ተሰርዟል"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"ስራ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for lock_to_app_title (5895142291937470019) -->
+    <skip />
+    <!-- no translation found for lock_to_app_description (8597199033462406175) -->
+    <skip />
+    <!-- no translation found for lock_to_app_negative (8522854387366288195) -->
+    <skip />
+    <!-- no translation found for lock_to_app_positive (7085139175671313864) -->
+    <skip />
+    <!-- no translation found for lock_to_app_start (8889002974248178076) -->
+    <skip />
+    <!-- no translation found for lock_to_app_exit (7033017307788432861) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 7d1117b..d53daba 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"تحديد العام"</string>
     <string name="item_is_selected" msgid="949687401682476608">"تم تحديد <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"تم حذف <xliff:g id="KEY">%1$s</xliff:g>"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> المخصص للعمل"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"هل تريد استخدام قفل تشغيل الجهاز على تطبيق؟"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"تتيح ميزة \"قفل تشغيل الجهاز على تطبيق\" تأمين الشاشة وقصر استخدامها على تطبيق واحد.\n\nللخروج اضغط مع الاستمرار على زر التطبيقات الحديثة $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"لا"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"بدء"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"بدء قفل تشغيل الجهاز على تطبيق"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"خروج من قفل تشغيل الجهاز على تطبيق"</string>
 </resources>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index b9c4f46..d77971c 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1001,10 +1001,8 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Разрешава на приложението да навие инсталирано приложение будилник. Някои будилници може да не изпълнят тази функция."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"добавяне на гласова поща"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Разрешава на приложението да добавя съобщения към входящата ви гласова поща."</string>
-    <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) -->
-    <skip />
-    <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) -->
-    <skip />
+    <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"четене на цялата гласова поща"</string>
+    <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Разрешава на приложението да чете цялата ви гласова поща."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"промяна на разрешенията за местоположение в браузъра"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Разрешава на приложението да променя разрешенията на браузъра за местоположение. Злонамерените приложения могат да използват това, за да изпращат информация за местоположението до произволни уебсайтове."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"проверка на пакетите"</string>
@@ -1727,4 +1725,17 @@
     <string name="select_year" msgid="7952052866994196170">"Избиране на година"</string>
     <string name="item_is_selected" msgid="949687401682476608">"Избрахте <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"Изтрихте <xliff:g id="KEY">%1$s</xliff:g>"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> за работа"</string>
+    <!-- no translation found for lock_to_app_title (5895142291937470019) -->
+    <skip />
+    <!-- no translation found for lock_to_app_description (8597199033462406175) -->
+    <skip />
+    <!-- no translation found for lock_to_app_negative (8522854387366288195) -->
+    <skip />
+    <!-- no translation found for lock_to_app_positive (7085139175671313864) -->
+    <skip />
+    <!-- no translation found for lock_to_app_start (8889002974248178076) -->
+    <skip />
+    <!-- no translation found for lock_to_app_exit (7033017307788432861) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 18389b6..46eeae8 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Selecciona un any"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> seleccionat"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> suprimit"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de la feina"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Vols fer servir la funció Bloqueja una aplicació?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"La funció Bloqueja una aplicació bloqueja la visualització a una sola aplicació.\n\nPer sortir, mantén premut el botó d\'aplicacions recents $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"NO"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"INICI"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Inicia la funció Bloqueja una aplicació"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Surt de la funció Bloqueja una aplicació"</string>
 </resources>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index aeb19d0..eb28a23 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Vyberte rok"</string>
     <string name="item_is_selected" msgid="949687401682476608">"Vybrána položka <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"Číslice <xliff:g id="KEY">%1$s</xliff:g> byla smazána"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"Pracovní <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Použít Uzamčení v aplikaci?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Funkce Uzamčení v aplikaci uzamkne obrazovku na jedinou aplikaci.\n\nChcete-li tento režim opustit, stiskněte a podržte tlačítko posledních aplikací $."</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"NE"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"SPUSTIT"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Spustit Uzamčení v aplikaci"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Opustit Uzamčení v aplikaci"</string>
 </resources>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 2996f75..9ddbf87 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1280,7 +1280,7 @@
     <string name="time_picker_dialog_title" msgid="8349362623068819295">"Angiv tidspunkt"</string>
     <string name="date_picker_dialog_title" msgid="5879450659453782278">"Angiv dato"</string>
     <string name="date_time_set" msgid="5777075614321087758">"Angiv"</string>
-    <string name="date_time_done" msgid="2507683751759308828">"Udført"</string>
+    <string name="date_time_done" msgid="2507683751759308828">"Udfør"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"NY: "</font></string>
     <string name="perms_description_app" msgid="5139836143293299417">"Leveret af <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
     <string name="no_permissions" msgid="7283357728219338112">"Der kræves ingen tilladelser"</string>
@@ -1424,7 +1424,7 @@
     <item quantity="one" msgid="8167147081136579439">"1 match"</item>
     <item quantity="other" msgid="4641872797067609177">"<xliff:g id="INDEX">%d</xliff:g> af <xliff:g id="TOTAL">%d</xliff:g>"</item>
   </plurals>
-    <string name="action_mode_done" msgid="7217581640461922289">"Udført"</string>
+    <string name="action_mode_done" msgid="7217581640461922289">"Udfør"</string>
     <string name="progress_unmounting" product="nosdcard" msgid="3923810448507612746">"Demonterer USB-lageret..."</string>
     <string name="progress_unmounting" product="default" msgid="1327894998409537190">"Demonterer SD-kortet..."</string>
     <string name="progress_erasing" product="nosdcard" msgid="4521573321524340058">"Sletter USB-lageret..."</string>
@@ -1475,7 +1475,7 @@
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Annuller"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Slet"</string>
-    <string name="keyboardview_keycode_done" msgid="1992571118466679775">"Udført"</string>
+    <string name="keyboardview_keycode_done" msgid="1992571118466679775">"Udfør"</string>
     <string name="keyboardview_keycode_mode_change" msgid="4547387741906537519">"Ændring af tilstand"</string>
     <string name="keyboardview_keycode_shift" msgid="2270748814315147690">"Shift"</string>
     <string name="keyboardview_keycode_enter" msgid="2985864015076059467">"Angiv"</string>
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Vælg år"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> er valgt"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> er slettet"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> – arbejde"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Vil du bruge Lås-til-app?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Med Lås-til-app låses skærmen, så den kun viser én app.\n\nHvis du vil afslutte denne tilstand, skal du trykke på knappen for seneste apps og holde fingeren nede $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"NEJ"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"START"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Start Lås-til-app"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Afslut Lås-til-app"</string>
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index fe5c139..6f08ba2 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Jahr auswählen"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> ausgewählt"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> gelöscht"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (geschäftlich)"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"\"Auf App einschränken\" verwenden?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Mit \"Auf App einschränken\" wird das Display in einer einzelnen App gesperrt.\n\nZum Beenden der Sperre berühren und halten Sie die Schaltfläche für die letzten Apps $."</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"Nein"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"Starten"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"\"Auf App einschränken\" starten"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"\"Auf App einschränken\" beenden"</string>
 </resources>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 1a70d19..0539bc9 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Επιλογή έτους"</string>
     <string name="item_is_selected" msgid="949687401682476608">"Επιλέχτηκε το στοιχείο <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> διαγράφηκε"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"Εργασία <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Χρήση λειτουργίας lock-to-app;"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Η λειτουργία Lock-to-app κλειδώνει την οθόνη σε μία μόνο εφαρμογή.\n\nΓια έξοδο πατήστε παρατεταμένα το κουμπί των πρόσφατων εφαρμογών $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"ΟΧΙ"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"ΕΝΑΡΞΗ"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Έναρξη Lock-to-app"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Έξοδος από Lock-to-app"</string>
 </resources>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index c659999..18e11df 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Select year"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> selected"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> deleted"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Use lock-to-app?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Lock-to-app locks the display in a single app.\n\nTo exit press and hold the recent apps button $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"NO"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"START"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Start Lock-to-app"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Exit Lock-to-app"</string>
 </resources>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index c659999..18e11df 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Select year"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> selected"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> deleted"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"Work <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Use lock-to-app?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Lock-to-app locks the display in a single app.\n\nTo exit press and hold the recent apps button $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"NO"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"START"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Start Lock-to-app"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Exit Lock-to-app"</string>
 </resources>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index b1108bf..2451d62 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1001,10 +1001,8 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Permite que la aplicación establezca una alarma en una aplicación de alarma instalada. Es posible que algunas aplicaciones de alarma no incluyan esta función."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"agregar correo de voz"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permite que la aplicación agregue mensajes a la bandeja de entrada de tu buzón de voz."</string>
-    <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) -->
-    <skip />
-    <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) -->
-    <skip />
+    <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"Consultar todos los mensajes del buzón de voz"</string>
+    <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Permite que la aplicación consulte todos los mensajes del buzón de voz."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Modificar los permisos de ubicación geográfica del navegador"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permite que la aplicación modifique los permisos de ubicación geográfica del navegador. Las aplicaciones maliciosas pueden utilizar esto para permitir el envío de información de ubicación a sitios web arbitrarios."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"Verificar paquetes"</string>
@@ -1727,4 +1725,17 @@
     <string name="select_year" msgid="7952052866994196170">"Seleccionar año"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> seleccionado"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> borrado"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo"</string>
+    <!-- no translation found for lock_to_app_title (5895142291937470019) -->
+    <skip />
+    <!-- no translation found for lock_to_app_description (8597199033462406175) -->
+    <skip />
+    <!-- no translation found for lock_to_app_negative (8522854387366288195) -->
+    <skip />
+    <!-- no translation found for lock_to_app_positive (7085139175671313864) -->
+    <skip />
+    <!-- no translation found for lock_to_app_start (8889002974248178076) -->
+    <skip />
+    <!-- no translation found for lock_to_app_exit (7033017307788432861) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index f47f5c0..0bc3a92 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Seleccionar año"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> seleccionado"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> eliminado"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de trabajo"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"¿Usar bloqueo de aplicación?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"El bloqueo de aplicación bloquea la pantalla en una sola aplicación.\n\nPara salir, mantén pulsado el botón de aplicaciones recientes $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"NO"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"INICIAR"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Iniciar bloqueo de aplicación"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Salir de bloqueo de aplicación"</string>
 </resources>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 0df3aca..4012f09 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -1725,4 +1725,12 @@
     <string name="select_year" msgid="7952052866994196170">"Aasta valimine"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> on valitud"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> on kustutatud"</string>
+    <!-- no translation found for managed_profile_label_badge (2355652472854327647) -->
+    <skip />
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Kas soovite kasutada rakendusele lukustamist?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Rakendusele lukustamise funktsioon lukustab kuva ühele rakendusele.\n\nVäljumiseks hoidke hiljutiste rakenduste nuppu $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"EI"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"KÄIVITA"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Käivita rakendusele lukustamine"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Välju rakendusele lukustamisest"</string>
 </resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index d652544..30136e76 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"انتخاب سال"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> انتخاب شد"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> حذف شد"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> محل کار"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"از «قفل برنامه» استفاده شود؟"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"«قفل برنامه» نمایشگر را در یک برنامه قفل می‌کند.\n\nبرای خروج، دکمه برنامه‌های جدید $ را فشار داده و نگه‌دارید"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"خیر"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"شروع"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"راه‌اندازی «قفل برنامه»"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"خروج از «قفل برنامه»"</string>
 </resources>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 802fb24..f833733 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -1001,10 +1001,8 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Antaa sovelluksen asettaa hälytyksen sisäiseen herätyskellosovellukseen. Jotkin herätyskellosovellukset eivät välttämättä käytä tätä ominaisuutta."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"lisää vastaajaviesti"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Antaa sovelluksen lisätä viestejä saapuneisiin vastaajaviesteihin."</string>
-    <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) -->
-    <skip />
-    <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) -->
-    <skip />
+    <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"kaikkien vastaajaviestien luku"</string>
+    <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Antaa sovelluksen lukea kaikki vastaajaviestisi."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"selaimen maantieteellisen sijainnin lupien muokkaaminen"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Antaa sovelluksen muokata Selaimen maantieteellisen sijainnin lupia. Haitalliset sovellukset voivat sallia tällä sijaintitietojen lähettämisen mielivaltaisiin sivustoihin."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"vahvista paketteja"</string>
@@ -1727,4 +1725,17 @@
     <string name="select_year" msgid="7952052866994196170">"Valitse vuosi"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> on valittu"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> poistettiin"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (työ)"</string>
+    <!-- no translation found for lock_to_app_title (5895142291937470019) -->
+    <skip />
+    <!-- no translation found for lock_to_app_description (8597199033462406175) -->
+    <skip />
+    <!-- no translation found for lock_to_app_negative (8522854387366288195) -->
+    <skip />
+    <!-- no translation found for lock_to_app_positive (7085139175671313864) -->
+    <skip />
+    <!-- no translation found for lock_to_app_start (8889002974248178076) -->
+    <skip />
+    <!-- no translation found for lock_to_app_exit (7033017307788432861) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index ec4c2d6..5ffa2e7 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1001,10 +1001,8 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Permet à l\'application de régler la sonnerie d\'une fonction de réveil installée sur votre appareil. Cette fonctionnalité n\'est pas compatible avec toutes les applications de réveils."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"ajouter des messages vocaux"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permet à l\'application d\'ajouter des messages à votre messagerie vocale."</string>
-    <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) -->
-    <skip />
-    <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) -->
-    <skip />
+    <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"accéder à tous les messages vocaux"</string>
+    <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Permet à l\'application d\'accéder à tous vos messages vocaux."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"modifier les autorisations de géolocalisation du navigateur"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permet à l\'application de modifier les autorisations de géolocalisation du navigateur. Des applications malveillantes peuvent exploiter cette fonctionnalité pour permettre l\'envoi de données de localisation à des sites Web arbitraires."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"vérifier les paquets"</string>
@@ -1727,4 +1725,17 @@
     <string name="select_year" msgid="7952052866994196170">"Sélectionnez une année"</string>
     <string name="item_is_selected" msgid="949687401682476608">"« <xliff:g id="ITEM">%1$s</xliff:g> » a été sélectionné"</string>
     <string name="deleted_key" msgid="7659477886625566590">"« <xliff:g id="KEY">%1$s</xliff:g> » a été supprimé"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (travail)"</string>
+    <!-- no translation found for lock_to_app_title (5895142291937470019) -->
+    <skip />
+    <!-- no translation found for lock_to_app_description (8597199033462406175) -->
+    <skip />
+    <!-- no translation found for lock_to_app_negative (8522854387366288195) -->
+    <skip />
+    <!-- no translation found for lock_to_app_positive (7085139175671313864) -->
+    <skip />
+    <!-- no translation found for lock_to_app_start (8889002974248178076) -->
+    <skip />
+    <!-- no translation found for lock_to_app_exit (7033017307788432861) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 57ee762..e2c7196 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -1725,4 +1725,17 @@
     <string name="select_year" msgid="7952052866994196170">"Sélectionner une année"</string>
     <string name="item_is_selected" msgid="949687401682476608">"\"<xliff:g id="ITEM">%1$s</xliff:g>\" sélectionné"</string>
     <string name="deleted_key" msgid="7659477886625566590">"\"<xliff:g id="KEY">%1$s</xliff:g>\" supprimé"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (travail)"</string>
+    <!-- no translation found for lock_to_app_title (5895142291937470019) -->
+    <skip />
+    <!-- no translation found for lock_to_app_description (8597199033462406175) -->
+    <skip />
+    <!-- no translation found for lock_to_app_negative (8522854387366288195) -->
+    <skip />
+    <!-- no translation found for lock_to_app_positive (7085139175671313864) -->
+    <skip />
+    <!-- no translation found for lock_to_app_start (8889002974248178076) -->
+    <skip />
+    <!-- no translation found for lock_to_app_exit (7033017307788432861) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 8c2c025..8cbb095 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1001,10 +1001,8 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"ऐप्स को इंस्‍टॉल किए गए अलार्म घड़ी ऐप्स में अलार्म सेट करने देता है. हो सकता है कुछ अलार्म घड़ी ऐप्स में यह सुविधा न हो."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"ध्‍वनिमेल जोड़ें"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"ऐप्स  को आपके ध्‍वनिमेल इनबॉक्‍स में संदेश जोड़ने देता है."</string>
-    <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) -->
-    <skip />
-    <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) -->
-    <skip />
+    <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"सभी ध्वनिमेल पढ़ें"</string>
+    <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"ऐप्स को आपके सभी ध्वनिमेल पढ़ने देती है."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"ब्राउज़र भौगोलिक-स्थान अनुमतियों को बदलें"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"ऐप्स को ब्राउज़र के भौगोलिक-स्‍थान की अनुमतियां संशोधित करने देता है. दुर्भावनापूर्ण ऐप्स इसका उपयोग एकपक्षीय वेबसाइट को स्‍थान जानकारी भेजने में कर सकते हैं."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"पैकेज सत्‍यापि‍त करें"</string>
@@ -1727,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"वर्ष चुनें"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> चयनित"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> को हटा दिया गया"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"कार्यस्थल का <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"ऐप्स-पर-लॉक करें का उपयोग करें?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"ऐप्स-पर-लॉक करें, डिस्प्ले को किसी एकल ऐप्स में लॉक कर देता है.\n\nबाहर निकलने के लिए हाल ही के ऐप्स बटन $ को दबाए रखें"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"नहीं"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"प्रारंभ करें"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"ऐप्स-पर-लॉक करें प्रारंभ करें"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"ऐप्स-पर-लॉक करें से बाहर निकलें"</string>
 </resources>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 65e64ec..a427eb3 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1364,8 +1364,8 @@
     <string name="permdesc_trust_listener" msgid="8233895334214716864">"Omogućuje aplikaciji praćenje promjena pouzdanog stanja."</string>
     <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Pružanje agenta za pouzdanost."</string>
     <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Omogućuje aplikaciji pružanje agenta za pouzdanost."</string>
-    <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"Pokretanje izbornika postavki pouzdanog agenta."</string>
-    <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"Aplikaciji omogućuje pokretanje aktivnosti koja mijenja ponašanje pouzdanog agenta."</string>
+    <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"Pokretanje izbornika postavki agenta za pouzdanost."</string>
+    <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"Aplikaciji omogućuje pokretanje aktivnosti koja mijenja ponašanje agenta za pouzdanost."</string>
     <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Povezivanje s uslugom pouzdanog predstavnika"</string>
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Omogućuje aplikaciji povezivanje s uslugom pouzdanog predstavnika."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Interakcija s ažuriranjem i sustavom za oporavak"</string>
@@ -1725,4 +1725,17 @@
     <string name="select_year" msgid="7952052866994196170">"Odaberite godinu"</string>
     <string name="item_is_selected" msgid="949687401682476608">"Odabrana je stavka <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"Izbrisan je broj <xliff:g id="KEY">%1$s</xliff:g>"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> za posao"</string>
+    <!-- no translation found for lock_to_app_title (5895142291937470019) -->
+    <skip />
+    <!-- no translation found for lock_to_app_description (8597199033462406175) -->
+    <skip />
+    <!-- no translation found for lock_to_app_negative (8522854387366288195) -->
+    <skip />
+    <!-- no translation found for lock_to_app_positive (7085139175671313864) -->
+    <skip />
+    <!-- no translation found for lock_to_app_start (8889002974248178076) -->
+    <skip />
+    <!-- no translation found for lock_to_app_exit (7033017307788432861) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 498e28a..1fbfdef 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Válassza ki az évet"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> kiválasztva"</string>
     <string name="deleted_key" msgid="7659477886625566590">"A(z) <xliff:g id="KEY">%1$s</xliff:g> érték törölve"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"Munkahelyi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Használni szeretné az alkalmazászárolást?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Az alkalmazászárolás lezárja a kijelzőt az adott alkalmazásban.\n\nA kilépéshez tartsa lenyomva a legutóbbi alkalmazások gombot ($)."</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"NEM"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"INDÍT"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Az alkalmazászárolás indítása"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Kilépés az alkalmazászárolásból"</string>
 </resources>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 97e9ffc1..27a65a3 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -1001,10 +1001,8 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Թույլ է տալիս հավելվածին սահմանել զարթուցիչի ծրագրում տեղադրված ազդանշանը: Զարթուցիչի որոշ հավելվածներ չեն կարող կիրառել այս հատկությունը:"</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"ավելացնել ձայնային փոստ"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Թույլ է տալիս հավելվածին ավելացնել հաղորդագրություններ ձեր ձայնային փոստի արկղում:"</string>
-    <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) -->
-    <skip />
-    <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) -->
-    <skip />
+    <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"կարդալ ձայնային հաղորդագրությունները"</string>
+    <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Թույլ է տալիս հավելվածին կարդալ ձեր բոլոր ձայնային հաղորդագրությունները:"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"փոփոխել դիտարկչի աշխարհագրական տեղանքի թույլտվությունները"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Թույլ է տալիս հավելվածին փոփոխել զննարկչի աշխարհագրական դիրքի թույլտվությունները: Վնասարար հավելվածները կարող են օգտագործել սա` թույլատրելու ուղարկել տեղադրության վերաբերյալ տեղեկությունները կամայական վեբ կայքերին:"</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"հաստատել փաթեթները"</string>
@@ -1727,4 +1725,17 @@
     <string name="select_year" msgid="7952052866994196170">"Ընտրեք տարին"</string>
     <string name="item_is_selected" msgid="949687401682476608">"Ընտրված է <xliff:g id="ITEM">%1$s</xliff:g> տարրը"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> թիվը ջնջված է"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"Աշխատանքային <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for lock_to_app_title (5895142291937470019) -->
+    <skip />
+    <!-- no translation found for lock_to_app_description (8597199033462406175) -->
+    <skip />
+    <!-- no translation found for lock_to_app_negative (8522854387366288195) -->
+    <skip />
+    <!-- no translation found for lock_to_app_positive (7085139175671313864) -->
+    <skip />
+    <!-- no translation found for lock_to_app_start (8889002974248178076) -->
+    <skip />
+    <!-- no translation found for lock_to_app_exit (7033017307788432861) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 1c80430..666d585 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Pilih tahun"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> dipilih"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> dihapus"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"Kantor <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Gunakan lock-to-app?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Lock-to-app mengunci layar dalam satu aplikasi tunggal.\n\nUntuk keluar, tekan lama tombol aplikasi terbaru $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"TIDAK"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"MULAI"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Mulai Lock-to-app"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Keluar dari Lock-to-app"</string>
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index d7b7748..3397834 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Seleziona anno"</string>
     <string name="item_is_selected" msgid="949687401682476608">"Elemento selezionato: <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> eliminato"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> lavoro"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Utilizzare Lock-to-app?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"La funzione Lock-to-app consente di bloccare la visualizzazione in un\'unica app.\n\nPer uscire, premi e tieni premuto il pulsante delle app recenti $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"NO"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"AVVIA"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Avvia Lock-to-app"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Esci da Lock-to-app"</string>
 </resources>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 8b33339..f67ae0c 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"בחר שנה"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> נבחר"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> נמחק"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"עבודה <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"האם להשתמש ב\'נעל באפליקציה\'?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"\'נעל באפליקציה\' נועל את המסך באפליקציה יחידה.\n\nכדי לצאת, לחץ על לחצן האפליקציות האחרונות $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"לא"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"הפעל"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"הפעל את \'נעל באפליקציה\'"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"צא מ\'נעל באפליקציה\'"</string>
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index a4b95a6..1bd8906 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1001,10 +1001,8 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"インストール済みアラームアプリのアラームを設定することをアプリに許可します。この機能が実装されていないアラームアプリもあります。"</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"ボイスメールの追加"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"ボイスメール受信トレイにメッセージを追加することをアプリに許可します。"</string>
-    <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) -->
-    <skip />
-    <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) -->
-    <skip />
+    <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"すべてのボイスメールの読み取り"</string>
+    <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"すべてのボイスメールの読み取りをアプリに許可します。"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"ブラウザの現在地情報に対する権限の変更"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"ブラウザの現在地情報に対する権限の変更をアプリに許可します。この許可を悪意のあるアプリに利用されると、任意のウェブサイトに現在地情報が送信される恐れがあります。"</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"パッケージのベリファイ"</string>
@@ -1727,4 +1725,17 @@
     <string name="select_year" msgid="7952052866994196170">"年を選択"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g>を選択しました"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g>を削除しました"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"仕事の<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for lock_to_app_title (5895142291937470019) -->
+    <skip />
+    <!-- no translation found for lock_to_app_description (8597199033462406175) -->
+    <skip />
+    <!-- no translation found for lock_to_app_negative (8522854387366288195) -->
+    <skip />
+    <!-- no translation found for lock_to_app_positive (7085139175671313864) -->
+    <skip />
+    <!-- no translation found for lock_to_app_start (8889002974248178076) -->
+    <skip />
+    <!-- no translation found for lock_to_app_exit (7033017307788432861) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 694e1c7..a7601d2 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -1001,10 +1001,8 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"აპს შეეძლება მაღვიძარას დაყენება დაინსტალირებული მაღვიძარას აპლიკაციაში. ამ ფუნქციას მაღვიძარას ზოგიერთი აპი არ იყენებს."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"ხმოვანი ფოსტის დამატება"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"აპს შეეძლება დაამატოს შეტყობინებები თქვენი ხმოვანი ფოსტის შემოსულებში."</string>
-    <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) -->
-    <skip />
-    <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) -->
-    <skip />
+    <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"მთელი ხმოვანი ფოსტის წაკითხვა"</string>
+    <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"აპს ეძლევა მთელი თქვენი ხმოვანი ფოსტების წაკითხვის უფლება."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"ბრაუზერის გეოლოკაციის უფლებების შეცვლა"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"აპს შეეძლება ბრაუზერის გეოლოკაციის უფლებების შეცვლა. მავნე აპებმა ეს შესაძლოა გამოიყენონ  ნებისმიერი ვებსაიტისთვის მდებარეობის შესახებ ინფორმაციის გასაგზავნად."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"პაკეტების გადამოწმება"</string>
@@ -1727,4 +1725,17 @@
     <string name="select_year" msgid="7952052866994196170">"აირჩიეთ წელი"</string>
     <string name="item_is_selected" msgid="949687401682476608">"არჩეულია <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> წაიშალა"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"სამსახური <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for lock_to_app_title (5895142291937470019) -->
+    <skip />
+    <!-- no translation found for lock_to_app_description (8597199033462406175) -->
+    <skip />
+    <!-- no translation found for lock_to_app_negative (8522854387366288195) -->
+    <skip />
+    <!-- no translation found for lock_to_app_positive (7085139175671313864) -->
+    <skip />
+    <!-- no translation found for lock_to_app_start (8889002974248178076) -->
+    <skip />
+    <!-- no translation found for lock_to_app_exit (7033017307788432861) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 421ff10..d8bf2ff 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -68,7 +68,7 @@
   </plurals>
     <string name="imei" msgid="2625429890869005782">"IMEI"</string>
     <string name="meid" msgid="4841221237681254195">"MEID"</string>
-    <string name="ClipMmi" msgid="6952821216480289285">"លេខ​សម្គាល់​អ្នក​ហៅ​​ចូល"</string>
+    <string name="ClipMmi" msgid="6952821216480289285">"លេខ​សម្គាល់​អ្នក​ហៅ​​ចូល​"</string>
     <string name="ClirMmi" msgid="7784673673446833091">"លេខ​សម្គាល់​អ្នក​ហៅ​ចេញ"</string>
     <string name="CfMmi" msgid="5123218989141573515">"បញ្ជូន​ការ​ហៅ​បន្ត"</string>
     <string name="CwMmi" msgid="9129678056795016867">"រង់ចាំ​ការ​ហៅ"</string>
@@ -125,7 +125,7 @@
     <string name="cfTemplateRegisteredTime" msgid="6781621964320635172">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> ៖ មិន​បាន​បញ្ជូន​បន្ត"</string>
     <string name="fcComplete" msgid="3118848230966886575">"កូដ​លក្ខណៈ​ពេញលេញ។"</string>
     <string name="fcError" msgid="3327560126588500777">"បញ្ហា​ការ​តភ្ជាប់​ ឬ​កូដ​លក្ខណៈ​​​មិន​ត្រឹមត្រូវ​។"</string>
-    <string name="httpErrorOk" msgid="1191919378083472204">"យល់​ព្រម"</string>
+    <string name="httpErrorOk" msgid="1191919378083472204">"យល់​ព្រម​"</string>
     <string name="httpError" msgid="7956392511146698522">"មាន​កំហុស​បណ្ដាញ។"</string>
     <string name="httpErrorLookup" msgid="4711687456111963163">"រក​មិន​ឃើញ URL ។"</string>
     <string name="httpErrorUnsupportedAuthScheme" msgid="6299980280442076799">"គ្រោងការណ៍​ផ្ទៀងផ្ទាត់​តំបន់បណ្ដាញ​មិន​ត្រូវ​បាន​គាំទ្រ។"</string>
@@ -183,7 +183,7 @@
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"បើក​សំឡេង"</string>
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"ពេល​ជិះ​យន្តហោះ"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"បាន​បើក​របៀប​ពេល​ជិះ​យន្ត​ហោះ"</string>
-    <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"បាន​បិទ​របៀបពេលជិះ​យន្តហោះ"</string>
+    <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"បាន​បិទ​របៀបពេលជិះ​យន្តហោះ​"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"ការ​កំណត់"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"របៀប​​​សុវត្ថិភាព"</string>
@@ -195,7 +195,7 @@
     <string name="permgrouplab_messages" msgid="7521249148445456662">"សារ​របស់​អ្នក"</string>
     <string name="permgroupdesc_messages" msgid="7821999071003699236">"អាន និង​សរសេរ​សារ SMS, អ៊ីមែល និង​សារ​ផ្សេងៗ​ទៀត​របស់​អ្នក។"</string>
     <string name="permgrouplab_personalInfo" msgid="3519163141070533474">"ព័ត៌មាន​ផ្ទាល់ខ្លួន​របស់​អ្នក"</string>
-    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"ចូល​ដំណើរការ​ព័ត៌មាន​ដោយ​ផ្ទាល់​អំពី​អ្នក​ ដែល​បា​ន​រក្សាទុក​ក្នុង​កាត​ទំនាក់ទំនង​របស់​អ្នក។"</string>
+    <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"ចូល​ដំណើរការ​ព័ត៌មាន​ដោយ​ផ្ទាល់​អំពី​អ្នក​ ដែល​បា​ន​រក្សាទុក​ក្នុង​កាត​ទំនាក់ទំនង​របស់​អ្នក។​"</string>
     <string name="permgrouplab_socialInfo" msgid="5799096623412043791">"ព័ត៌មាន​សង្គម​របស់​អ្នក"</string>
     <string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"ចូល​ដំណើរការ​ព័ត៌មាន​ដោយ​ផ្ទាល់​អំពី​ទំនាក់ទំនង និង​ការ​ភ្ជាប់​សង្គម​របស់​អ្នក។"</string>
     <string name="permgrouplab_location" msgid="635149742436692049">"ទីតាំង​របស់​អ្នក"</string>
@@ -384,7 +384,7 @@
     <string name="permdesc_readInputState" msgid="8387754901688728043">"ឲ្យ​កម្មវិធី​មើល​គ្រាប់​ចុច​ដែល​អ្នក​ចុច​ពេល​មាន​អន្តរកម្ម​ជា​មួយ​កម្មវិធី​ផ្សេង (ដូចជា បញ្ចូល​ពាក្យ​សម្ងាត់)។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_bindInputMethod" msgid="3360064620230515776">"ចង​ទៅ​វិធីសាស្ត្រ​បញ្ចូល"</string>
     <string name="permdesc_bindInputMethod" msgid="3250440322807286331">"ឲ្យ​ម្ចាស់​ចង​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​នៃ​វិធី​សាស្ត្រ​បញ្ចូល។ មិន​គួរ​​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
-    <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"ចង​សេវា​កម្ម​ភាព​មធ្យោបាយ​ងាយស្រួល"</string>
+    <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"ចង​សេវា​កម្ម​ភាព​មធ្យោបាយ​ងាយស្រួល​"</string>
     <string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"ឲ្យ​​ម្ចាស់​ចង​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​នៃ​សេវាកម្ម​ភាព​ងាយស្រួល។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_bindPrintService" msgid="8462815179572748761">"ចង​សេវាកម្ម​​បោះពុម្ព"</string>
     <string name="permdesc_bindPrintService" msgid="7960067623209111135">"ឲ្យ​ម្ចាស់​ចង​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​នៃ​សេវាកម្ម​ធាតុ​ក្រាហ្វិក។ មិន​គួរ​​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
@@ -404,7 +404,7 @@
     <string name="permdesc_manageVoiceKeyphrases" msgid="8476560722907530008">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​គ្រប់គ្រង​ឃ្លា​​សម្រាប់​​ការ​រក​ឃើញ​​​ពាក្យ​​ជា​សំឡេង។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"ភ្ជាប់​ទៅ​ការ​បង្ហាញ​ពី​ចម្ងាយ"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​ភ្ជាប់​​ទៅ​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​នៃ​ការ​បង្ហាញ​ពី​ចម្ងាយ។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
-    <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ចង​សេវា​កម្ម​ធាតុ​ក្រាហ្វិក"</string>
+    <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ចង​សេវា​កម្ម​ធាតុ​ក្រាហ្វិក​"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ឲ្យ​ម្ចាស់​ចង​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​នៃ​សេវាកម្ម​ធាតុ​ក្រាហ្វិក។ មិន​គួរ​​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"ភ្ជាប់​ទៅ​សេវាកម្ម​ក្រុមហ៊ុន​ផ្ដល់​ច្រក"</string>
     <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​ភ្ជាប់​ទៅ​ក្រុមហ៊ុន​ផ្ដល់​​ច្រក​ដែល​បាន​ចុះ​ឈ្មោះ។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
@@ -412,7 +412,7 @@
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"ឲ្យ​ម្ចាស់​ផ្ញើ​គោលបំណង​​ទៅ​អ្នក​គ្រប់គ្រង​ឧបករណ៍។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_bindTvInput" msgid="5601264742478168987">"ភ្ជាប់​ទៅ​ការ​បញ្ចូល​ទូរទស្សន៍"</string>
     <string name="permdesc_bindTvInput" msgid="2371008331852001924">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​ភ្ជាប់​ទៅ​ចំណុចប្រទាក់​កម្រិត​ខ្ពស់​នៃ​ការ​បញ្ចូល​ទូរទស្សន៍។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
-    <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"បន្ថែម​ ឬ​លុប​កម្មវិធី​គ្រប់គ្រង​​​ឧបករណ៍"</string>
+    <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"បន្ថែម​ ឬ​លុប​កម្មវិធី​គ្រប់គ្រង​​​ឧបករណ៍​​"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"អនុញ្ញាត​​​ឲ្យ​ម្ចាស់​​​បន្ថែម​ ឬ​លុប​កម្មវិធី​គ្រប់គ្រង​ឧបករណ៍​សកម្ម​ចេញ​។ មិន​គួរ​ប្រើ​សម្រាប់​កម្មវិធី​​ធម្មតា​ទេ​។"</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"ប្ដូរ​ទិស​អេក្រង់"</string>
     <string name="permdesc_setOrientation" msgid="3046126619316671476">"ឲ្យ​កម្មវិធី​ប្ដូរ​ការ​បង្វិល​អេក្រង់​នៅ​ពេល​ណា​មួយ។ មិន​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
@@ -424,9 +424,9 @@
     <string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"ឲ្យ​កម្មវិធី​ស្នើ​​សញ្ញា​ដែល​បាន​ផ្ដល់​ត្រូវ​ផ្ញើ​ទៅ​ដំណើរការ​ស្ថិតស្ថេរ​​ទាំង​អស់។"</string>
     <string name="permlab_persistentActivity" msgid="8841113627955563938">"ធ្វើ​ឲ្យ​កម្មវិធី​ដំណើរការ​ជា​និច្ច"</string>
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"ឲ្យ​កម្មវិធី​ធ្វើជា​ផ្នែក​​ស្ថិតស្ថេរ​ដោយ​ខ្លួន​ឯង​ក្នុង​អង្គ​ចងចាំ។ វា​អាច​កំណត់​អង្គ​ចងចាំ​ដែល​អាច​ប្រើ​បាន​ចំពោះ​កម្មវិធី​ផ្សេងៗ​ ដោយ​ធ្វើឲ្យ​កុំព្យូទ័រ​បន្ទះ​យឺត។"</string>
-    <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"ឲ្យ​កម្មវិធី ធ្វើជា​ផ្នែក​អចិន្ត្រៃយ៍​នៃ​ខ្លួន​ក្នុង​អង្គ​ចងចាំ។ វា​អាច​កម្រិត​អង្គ​ចងចាំ​អាច​ប្រើ​បាន​ ដើម្បី​ធ្វើ​ឲ្យ​កម្មវិធី​ផ្សេង​ធ្វើ​ឲ្យ​ទូរស័ព្ទ​របស់​អ្នក​យឺត។"</string>
+    <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"ឲ្យ​កម្មវិធី ធ្វើជា​ផ្នែក​អចិន្ត្រៃយ៍​នៃ​ខ្លួន​ក្នុង​អង្គ​ចងចាំ។ វា​អាច​កម្រិត​អង្គ​ចងចាំ​អាច​ប្រើ​បាន​ ដើម្បី​ធ្វើ​ឲ្យ​កម្មវិធី​ផ្សេង​ធ្វើ​ឲ្យ​ទូរស័ព្ទ​របស់​អ្នក​យឺត។​"</string>
     <string name="permlab_deletePackages" msgid="184385129537705938">"លុប​កម្មវិធី"</string>
-    <string name="permdesc_deletePackages" msgid="7411480275167205081">"ឲ្យ​កម្មវិធី​លុប​កញ្ចប់ Android ។ កម្មវិធី​ព្យាបាទ​អាច​ប្រើ​វា ដើម្បី​លុប​កម្មវិធី​សំខាន់​ៗ។"</string>
+    <string name="permdesc_deletePackages" msgid="7411480275167205081">"ឲ្យ​កម្មវិធី​លុប​កញ្ចប់ Android ។ កម្មវិធី​ព្យាបាទ​អាច​ប្រើ​វា ដើម្បី​លុប​កម្មវិធី​សំខាន់​ៗ។ ​"</string>
     <string name="permlab_clearAppUserData" msgid="274109191845842756">"លុប​ទិន្នន័យ​របស់​​កម្មវិធី​ផ្សេង"</string>
     <string name="permdesc_clearAppUserData" msgid="4625323684125459488">"ឲ្យ​កម្មវិធី​សម្អាត​ទិន្នន័យ​អ្នក​ប្រើ។"</string>
     <string name="permlab_deleteCacheFiles" msgid="3128665571837408675">"លុប​ឃ្លាំង​សម្ងាត់​កម្មវិធី​ផ្សេងៗ"</string>
@@ -477,7 +477,7 @@
     <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"ឲ្យ​កម្មវិធី​កែ​ទិន្នន័យ​អំពី​ទំនាក់ទំនង​របស់​អ្នក​ដែល​បាន​រក្សាទុក​ក្នុង​កុំព្យូទ័រ​បន្ទះ រួមមាន​ប្រេកង់​​ដែល​អ្នក​បាន​ហៅ អ៊ីមែល ឬ​ទាក់ទង​តាម​វិធី​ផ្សេងៗ​ជា​មួយ​ទំនាក់ទំនង​ជាក់លាក់។ សិទ្ធិ​​នេះ​អនុញ្ញាត​ឲ្យ​​​កម្មវិធី​លុប​ទិន្នន័យ​ទំនាក់ទំនង​របស់​អ្នក។"</string>
     <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"ឲ្យ​កម្មវិធី​កែ​ទិន្នន័យ​អំពី​ទំនាក់ទំនង​របស់​អ្នក​ដែល​បាន​រក្សាទុក​ក្នុង​ទូរស័ព្ទ​របស់​អ្នក រួមមាន​ប្រេកង់​ដែល​អ្នក​បាន​ហៅ អ៊ីមែល ឬ​បាន​ទាក់ទង​​តាម​វិធី​ផ្សេងៗ​ជា​មួយ​ទំនាក់​ទំនាក់​ជាក់លាក់។ សិទ្ធិ​នេះ​ឲ្យ​កម្មវិធី​លុប​ទិន្នន័យ​ទំនាក់ទំនង។"</string>
     <string name="permlab_readCallLog" msgid="3478133184624102739">"អាន​​កំណត់​ហេតុ​​​ហៅ"</string>
-    <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"ឲ្យ​កម្មវិធី​អាន​បញ្ជី​ហៅ​កុំព្យូទ័រ​បន្ទះ​របស់​អ្នក រួមមាន​ទិន្នន័យ​អំពី​ការ​ហៅ​ចូល និង​ចេញ។ សិទ្ធិ​នេះ​អនុញ្ញាត​ឲ្យ​កម្មវិធី​រក្សាទុក​ទិន្នន័យ​បញ្ជី​ហៅ​របស់​អ្នក ហើយ​កម្មវិធី​ព្យាបាទ​អាច​ចែករំលែក​ទិន្នន័យ​បញ្ជី​ហៅ​ដោយ​មិន​ឲ្យ​អ្នក​ដឹង។"</string>
+    <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"ឲ្យ​កម្មវិធី​អាន​បញ្ជី​ហៅ​កុំព្យូទ័រ​បន្ទះ​របស់​អ្នក រួមមាន​ទិន្នន័យ​អំពី​ការ​ហៅ​ចូល និង​ចេញ។ សិទ្ធិ​នេះ​អនុញ្ញាត​ឲ្យ​កម្មវិធី​រក្សាទុក​ទិន្នន័យ​បញ្ជី​ហៅ​របស់​អ្នក ហើយ​កម្មវិធី​ព្យាបាទ​អាច​ចែករំលែក​ទិន្នន័យ​បញ្ជី​ហៅ​ដោយ​មិន​ឲ្យ​អ្នក​ដឹង។​"</string>
     <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"ឲ្យ​កម្មវិធី​អាន​​​បញ្ជី​ហៅ​ទូរស័ព្ទ​របស់​អ្នក រួមមាន​ទិន្នន័យ​អំពី​ការ​ហៅ​ចូល និង​ចេញ។ សិទ្ធិ​នេះ​អនុញ្ញាត​ឲ្យ​កម្មវិធី​រក្សាទុក​ទិន្នន័យ​បញ្ជី​ហៅ​របស់​អ្នក ហើយ​កម្មវិធី​ព្យាបាទ​អាច​ចែករំលែក​ទិន្នន័យ​បញ្ជី​ហៅ​ដោយ​មិន​ឲ្យ​អ្នកដឹង។"</string>
     <string name="permlab_writeCallLog" msgid="8552045664743499354">"សរសេរ​បញ្ជី​ហៅ"</string>
     <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"ឲ្យ​កម្មវិធី​កែ​បញ្ជី​ហៅ​កុំព្យូទ័រ​បន្ទះ​របស់​អ្នក​រួមមាន​ទិន្នន័យ​អំពី​ការ​ហៅ​ចូល និង​ចេញ។​កម្មវិធី​ព្យាបាទ​អាច​ប្រើ​វា ដើម្បី​លុប ឬ​កែ​បញ្ជី​ហៅ​របស់​អ្នក។"</string>
@@ -613,7 +613,7 @@
     <string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"ឲ្យ​កម្មវិធី​កំណត់​ជំនួយ​ទំហំ​ផ្ទាំង​រូបភាព​ប្រព័ន្ធ។"</string>
     <string name="permlab_masterClear" msgid="2315750423139697397">"កំណត់​ប្រព័ន្ធ​ទៅ​លំនាំដើម​រោងចក្រ​ឡើងវិញ"</string>
     <string name="permdesc_masterClear" msgid="3665380492633910226">"ឲ្យ​កម្មវិធី​កំណត់​ប្រព័ន្ធ​​ដូច​ការ​កំណត់​ចេញ​ពី​រោងចក្រ​ឡើងវិញ​ពេញលេញ ដោយ​លុប​ទិន្នន័យ ការ​កំណត់​រចនាសម្ព័ន្ធ និង​កម្មវិធី​បាន​ដំឡើង។"</string>
-    <string name="permlab_setTime" msgid="2021614829591775646">"កំណត់​​ម៉ោង"</string>
+    <string name="permlab_setTime" msgid="2021614829591775646">"កំណត់​​ម៉ោង​"</string>
     <string name="permdesc_setTime" product="tablet" msgid="1896341438151152881">"ឲ្យ​កម្មវិធី​ប្ដូរ​ម៉ោង​កុំព្យូទ័រ​បន្ទះ។"</string>
     <string name="permdesc_setTime" product="default" msgid="1855702730738020">"ឲ្យ​កម្មវិធី​ប្ដូរ​ម៉ោង​ទូរស័ព្ទ។"</string>
     <string name="permlab_setTimeZone" msgid="2945079801013077340">"កំណត់​តំបន់​ពេលវេលា"</string>
@@ -779,7 +779,7 @@
   <string-array name="organizationTypes">
     <item msgid="7546335612189115615">"កន្លែង​ធ្វើការ"</item>
     <item msgid="4378074129049520373">"ផ្សេងៗ"</item>
-    <item msgid="3455047468583965104">"តាម​តម្រូវ​ការ"</item>
+    <item msgid="3455047468583965104">"តាម​តម្រូវ​ការ​"</item>
   </string-array>
   <string-array name="imProtocols">
     <item msgid="8595261363518459565">"AIM"</item>
@@ -795,7 +795,7 @@
     <string name="phoneTypeHome" msgid="2570923463033985887">"ផ្ទះ"</string>
     <string name="phoneTypeMobile" msgid="6501463557754751037">"​ចល័ត"</string>
     <string name="phoneTypeWork" msgid="8863939667059911633">"កន្លែង​ធ្វើការ"</string>
-    <string name="phoneTypeFaxWork" msgid="3517792160008890912">"ទូរសារ​កន្លែង​ធ្វើការ"</string>
+    <string name="phoneTypeFaxWork" msgid="3517792160008890912">"ទូរសារ​កន្លែង​ធ្វើការ​"</string>
     <string name="phoneTypeFaxHome" msgid="2067265972322971467">"ទូរសារ​ផ្ទះ"</string>
     <string name="phoneTypePager" msgid="7582359955394921732">"ភេយ័រ"</string>
     <string name="phoneTypeOther" msgid="1544425847868765990">"ផ្សេងៗ"</string>
@@ -920,7 +920,7 @@
     <string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"ព្យាយាម​លំនាំ​ច្រើន​ពេក"</string>
     <string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"ដើម្បី​ដោះ​សោ ចូល​គណនី Google របស់​អ្នក។"</string>
     <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"ឈ្មោះ​អ្នក​ប្រើ (អ៊ីមែល​)"</string>
-    <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"ពាក្យសម្ងាត់"</string>
+    <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"ពាក្យសម្ងាត់​"</string>
     <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"ចូល"</string>
     <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"ឈ្មោះ​អ្នកប្រើ ឬ​ពាក្យ​សម្ងាត់​មិន​ត្រឹមត្រូវ។"</string>
     <string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"ភ្លេច​ឈ្មោះ​អ្នក​ប្រើ ឬ​ពាក្យ​សម្ងាត់​របស់​អ្នក?\nមើល "<b>"google.com/accounts/recovery"</b>" ។"</string>
@@ -965,7 +965,7 @@
     <string name="factorytest_failed" msgid="5410270329114212041">"បាន​បរាជ័យ​ក្នុង​ការ​សាកល្បង​រោងចក្រ"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"សកម្មភាព FACTORY_TEST ត្រូវ​បាន​គាំទ្រ​សម្រាប់​តែ​កញ្ចប់​បាន​ដំឡើង​ក្នុង /system/app."</string>
     <string name="factorytest_no_action" msgid="872991874799998561">"រក​មិន​ឃើញ​កញ្ចប់​ដែល​ផ្ដល់​សកម្មភាព FACTORY_TEST ។"</string>
-    <string name="factorytest_reboot" msgid="6320168203050791643">"ចាប់​ផ្ដើម​ឡើង​វិញ"</string>
+    <string name="factorytest_reboot" msgid="6320168203050791643">"ចាប់​ផ្ដើម​ឡើង​វិញ​"</string>
     <string name="js_dialog_title" msgid="1987483977834603872">"ទំព័រ​មាន​ចំណងជើង \"<xliff:g id="TITLE">%s</xliff:g>\" សរសេរ៖"</string>
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
     <string name="js_dialog_before_unload_title" msgid="2619376555525116593">"បញ្ជាក់​ការ​រុករក"</string>
@@ -1001,10 +1001,8 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"ឲ្យ​កម្មវិធី​កំណត់​​សំឡេង​រោទ៍​ក្នុង​កម្មវិធី​នាឡិកា​រោទ៍​បាន​ដំឡើង។​ កម្មវិធី​នាឡិកា​រោទ៍​មួយ​ចំនួន​អាច​មិន​អនុវត្ត​លក្ខណៈ​នេះ។"</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"បន្ថែម​សារ​ជា​សំឡេង"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"ឲ្យ​កម្មវិធី​បន្ថែម​សារ​ទៅ​ប្រអប់​ទទួល​សារ​ជា​សំឡេង​របស់​អ្នក។"</string>
-    <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) -->
-    <skip />
-    <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) -->
-    <skip />
+    <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"អាន​សារ​ជា​សំឡេង​ទាំងអស់"</string>
+    <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"ឲ្យ​កម្មវិធី​អាន​​សារ​ជា​សំឡេង​របស់​អ្នក​ទាំងអស់។"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"កែ​សិទ្ធិ​ទីតាំង​ភូមិសាស្ត្រ​របស់​​កម្មវិធី​អ៊ីនធឺណិត"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"ឲ្យ​កម្មវិធី​កែ​​សិទ្ធិ​ទី​តាំង​ភូមិសាស្ត្រ​របស់​កម្មវិធី​អ៊ីនធឺណិត។ កម្មវិធី​ព្យាបាទ​អាច​ប្រើ​វា ដើម្បី​ឲ្យ​ផ្ញើ​ព័ត៌មាន​ទីតាំង​ទៅ​តំបន់បណ្ដាញ​ដោយ​បំពាន។"</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"ផ្ទៀងផ្ទាត់​កញ្ចប់"</string>
@@ -1027,7 +1025,7 @@
     <string name="prepend_shortcut_label" msgid="2572214461676015642">"ម៉ឺនុយ +"</string>
     <string name="menu_space_shortcut_label" msgid="2410328639272162537">"ដកឃ្លា"</string>
     <string name="menu_enter_shortcut_label" msgid="2743362785111309668">"enter"</string>
-    <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"លុប"</string>
+    <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"លុប​"</string>
     <string name="search_go" msgid="8298016669822141719">"ស្វែងរក"</string>
     <string name="searchview_description_search" msgid="6749826639098512120">"ស្វែងរក"</string>
     <string name="searchview_description_query" msgid="5911778593125355124">"ស្វែងរក​សំណួរ"</string>
@@ -1111,18 +1109,18 @@
     <string name="preposition_for_date" msgid="9093949757757445117">"នៅ <xliff:g id="DATE">%s</xliff:g>"</string>
     <string name="preposition_for_time" msgid="5506831244263083793">"នៅ​ម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="preposition_for_year" msgid="5040395640711867177">"ក្នុង​ឆ្នាំ <xliff:g id="YEAR">%s</xliff:g>"</string>
-    <string name="day" msgid="8144195776058119424">"ថ្ងៃ"</string>
+    <string name="day" msgid="8144195776058119424">"ថ្ងៃ​"</string>
     <string name="days" msgid="4774547661021344602">"​ថ្ងៃ"</string>
     <string name="hour" msgid="2126771916426189481">"ម៉ោង"</string>
     <string name="hours" msgid="894424005266852993">"ម៉ោង"</string>
-    <string name="minute" msgid="9148878657703769868">"នាទី"</string>
+    <string name="minute" msgid="9148878657703769868">"នាទី​"</string>
     <string name="minutes" msgid="5646001005827034509">"នាទី"</string>
-    <string name="second" msgid="3184235808021478">"វិនាទី"</string>
+    <string name="second" msgid="3184235808021478">"វិនាទី​"</string>
     <string name="seconds" msgid="3161515347216589235">"វិនាទី"</string>
-    <string name="week" msgid="5617961537173061583">"សប្ដាហ៍"</string>
-    <string name="weeks" msgid="6509623834583944518">"សប្ដាហ៍"</string>
-    <string name="year" msgid="4001118221013892076">"ឆ្នាំ"</string>
-    <string name="years" msgid="6881577717993213522">"ឆ្នាំ"</string>
+    <string name="week" msgid="5617961537173061583">"សប្ដាហ៍​"</string>
+    <string name="weeks" msgid="6509623834583944518">"សប្ដាហ៍​"</string>
+    <string name="year" msgid="4001118221013892076">"ឆ្នាំ​"</string>
+    <string name="years" msgid="6881577717993213522">"ឆ្នាំ​"</string>
   <plurals name="duration_seconds">
     <item quantity="one" msgid="6962015528372969481">"1 វិនាទី"</item>
     <item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> វិនាទី"</item>
@@ -1138,12 +1136,12 @@
     <string name="VideoView_error_title" msgid="3534509135438353077">"បញ្ហា​វីដេអូ"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"វីដេអូ​នេះ​មិន​ត្រឹមត្រូវ​សម្រាប់​​ចរន្ត​ចូល​ឧបករណ៍​នេះ។"</string>
     <string name="VideoView_error_text_unknown" msgid="3450439155187810085">"មិន​អាច​ចាក់​វីដេអូ​នេះ។"</string>
-    <string name="VideoView_error_button" msgid="2822238215100679592">"យល់​ព្រម"</string>
+    <string name="VideoView_error_button" msgid="2822238215100679592">"យល់​ព្រម​"</string>
     <string name="relative_time" msgid="1818557177829411417">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="noon" msgid="7245353528818587908">"រសៀល"</string>
     <string name="Noon" msgid="3342127745230013127">"រសៀល"</string>
     <string name="midnight" msgid="7166259508850457595">"កណ្ដាលអធ្រាត្រ"</string>
-    <string name="Midnight" msgid="5630806906897892201">"កណ្ដាល​អធ្រាត្រ"</string>
+    <string name="Midnight" msgid="5630806906897892201">"កណ្ដាល​អធ្រាត្រ​"</string>
     <string name="elapsed_time_short_format_mm_ss" msgid="4431555943828711473">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
     <string name="elapsed_time_short_format_h_mm_ss" msgid="1846071997616654124">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
     <string name="selectAll" msgid="6876518925844129331">"ជ្រើស​ទាំងអស់"</string>
@@ -1160,13 +1158,13 @@
     <string name="inputMethod" msgid="1653630062304567879">"វិធីសាស្ត្រ​បញ្ចូល"</string>
     <string name="editTextMenuTitle" msgid="4909135564941815494">"សកម្មភាព​អត្ថបទ"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"អស់​ទំហំ​ផ្ទុក"</string>
-    <string name="low_internal_storage_view_text" msgid="6640505817617414371">"មុខងារ​ប្រព័ន្ធ​មួយ​ចំនួន​អាច​មិន​ដំណើរការ"</string>
+    <string name="low_internal_storage_view_text" msgid="6640505817617414371">"មុខងារ​ប្រព័ន្ធ​មួយ​ចំនួន​អាច​មិន​ដំណើរការ​"</string>
     <string name="app_running_notification_title" msgid="8718335121060787914">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុង​ដំណើរការ"</string>
     <string name="app_running_notification_text" msgid="4653586947747330058">"ប៉ះ​ ដើម្បី​មើល​ព័ត៌មាន​បន្ថែម ឬ​បញ្ឈប់​កម្មវិធី។"</string>
-    <string name="ok" msgid="5970060430562524910">"យល់​ព្រម"</string>
-    <string name="cancel" msgid="6442560571259935130">"បោះ​បង់"</string>
-    <string name="yes" msgid="5362982303337969312">"យល់​ព្រម"</string>
-    <string name="no" msgid="5141531044935541497">"បោះ​បង់"</string>
+    <string name="ok" msgid="5970060430562524910">"យល់​ព្រម​"</string>
+    <string name="cancel" msgid="6442560571259935130">"បោះ​បង់​"</string>
+    <string name="yes" msgid="5362982303337969312">"យល់​ព្រម​"</string>
+    <string name="no" msgid="5141531044935541497">"បោះ​បង់​"</string>
     <string name="dialog_alert_title" msgid="2049658708609043103">"ប្រយ័ត្ន"</string>
     <string name="loading" msgid="7933681260296021180">"កំពុង​ផ្ទុក..."</string>
     <string name="capital_on" msgid="1544682755514494298">"បើក"</string>
@@ -1175,7 +1173,7 @@
     <string name="whichHomeApplication" msgid="4616420172727326782">"ជ្រើស​កម្មវិធី​ដើម"</string>
     <string name="alwaysUse" msgid="4583018368000610438">"ប្រើ​តាម​លំនាំដើម​សម្រាប់​សកម្មភាព​នេះ។"</string>
     <string name="clearDefaultHintMsg" msgid="3252584689512077257">"សម្អាត​លំនាំដើម​ក្នុង​ការកំណត់​ប្រព័ន្ធ &gt; កម្មវិធី &gt; ទាញ​យក។"</string>
-    <string name="chooseActivity" msgid="7486876147751803333">"ជ្រើស​សកម្មភាព"</string>
+    <string name="chooseActivity" msgid="7486876147751803333">"ជ្រើស​សកម្មភាព​​"</string>
     <string name="chooseUsbActivity" msgid="6894748416073583509">"ជ្រើស​កម្មវិធី​សម្រាប់​ឧបករណ៍​យូអេសប៊ី"</string>
     <string name="noApplications" msgid="2991814273936504689">"គ្មាន​កម្មវិធី​អាច​អនុវត្ត​សកម្មភាព​នេះ។"</string>
     <string name="aerr_title" msgid="1905800560317137752"></string>
@@ -1186,7 +1184,7 @@
     <string name="anr_activity_process" msgid="5776209883299089767">"សកម្មភាព <xliff:g id="ACTIVITY">%1$s</xliff:g> មិន​ឆ្លើយតប។\n\nតើ​អ្នក​ចង់​បិទ​វា?"</string>
     <string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> មិន​ឆ្លើយតប។ តើ​អ្នក​ចង់​បិទ​វា?"</string>
     <string name="anr_process" msgid="6513209874880517125">"ដំណើរការ <xliff:g id="PROCESS">%1$s</xliff:g> មិន​ឆ្លើយតប។ \n\nតើ​អ្នក​ចង់​បិទ​វា​ឬ?"</string>
-    <string name="force_close" msgid="8346072094521265605">"យល់​ព្រម"</string>
+    <string name="force_close" msgid="8346072094521265605">"យល់​ព្រម​"</string>
     <string name="report" msgid="4060218260984795706">"រាយការណ៍"</string>
     <string name="wait" msgid="7147118217226317732">"រង់ចាំ"</string>
     <string name="webpage_unresponsive" msgid="3272758351138122503">"ទំព័រ​ក្លាយ​ជា​មិន​ឆ្លើយតប។\n\nតើ​អ្នក​​ចង់​បិទ​វា?"</string>
@@ -1268,19 +1266,19 @@
     <string name="sms_short_code_details" msgid="3492025719868078457"><font fgcolor="#ffffb060">"នេះ​អាច​កាត់​លុយ"</font>" លើ​គណនី​ចល័ត​របស់​អ្នក។"</string>
     <string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"វា​នឹង​គិត​ថ្លៃ​សេវាកម្ម​លើ​គណនី​ចល័ត​របស់​អ្នក។"</font></string>
     <string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"ផ្ញើ"</string>
-    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"បោះ​បង់"</string>
+    <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"បោះ​បង់​"</string>
     <string name="sms_short_code_remember_choice" msgid="5289538592272218136">"ចងចាំ​ជម្រើស​របស់​ខ្ញុំ"</string>
     <string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"អ្នក​អាច​ប្ដូរ​វា​ពេល​ក្រោយ​ក្នុង​ការ​កំណត់ &gt; កម្មវិធី"</string>
     <string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"អនុញ្ញាត​ជា​និច្ច"</string>
     <string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"កុំ​អនុញ្ញាត"</string>
     <string name="sim_removed_title" msgid="6227712319223226185">"បាន​ដក​ស៊ីម​កាត​ចេញ"</string>
-    <string name="sim_removed_message" msgid="2333164559970958645">"បណ្ដាញ​ចល័ត​នឹង​ប្រើ​លែង​បាន​រហូត​ដល់​អ្នក​ចាប់ផ្ដើម​ជា​មួយ​ស៊ីម​កាត​ដែល​បា​បញ្ចូល​ត្រឹមត្រូវ។"</string>
+    <string name="sim_removed_message" msgid="2333164559970958645">"បណ្ដាញ​ចល័ត​នឹង​ប្រើ​លែង​បាន​រហូត​ដល់​អ្នក​ចាប់ផ្ដើម​ជា​មួយ​ស៊ីម​កាត​ដែល​បា​បញ្ចូល​ត្រឹមត្រូវ។​"</string>
     <string name="sim_done_button" msgid="827949989369963775">"រួចរាល់"</string>
     <string name="sim_added_title" msgid="3719670512889674693">"បាន​បន្ថែម​ស៊ីម​កាត"</string>
     <string name="sim_added_message" msgid="6599945301141050216">"ចាប់ផ្ដើម​ឧបករណ៍​របស់​អ្នក​ឡើង​វិញ ដើម្បី​ចូល​ដំណើរការ​បណ្ដាញ​ចល័ត។"</string>
     <string name="sim_restart_button" msgid="4722407842815232347">"ចាប់ផ្ដើម​ឡើងវិញ"</string>
-    <string name="time_picker_dialog_title" msgid="8349362623068819295">"កំណត់​ម៉ោង"</string>
-    <string name="date_picker_dialog_title" msgid="5879450659453782278">"កំណត់​កាល​បរិច្ឆេទ"</string>
+    <string name="time_picker_dialog_title" msgid="8349362623068819295">"កំណត់​ម៉ោង​"</string>
+    <string name="date_picker_dialog_title" msgid="5879450659453782278">"កំណត់​កាល​បរិច្ឆេទ​"</string>
     <string name="date_time_set" msgid="5777075614321087758">"កំណត់"</string>
     <string name="date_time_done" msgid="2507683751759308828">"រួចរាល់"</string>
     <string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"ថ្មី៖ "</font></string>
@@ -1358,7 +1356,7 @@
     <string name="permdesc_copyProtectedData" msgid="4390697124288317831">"ឲ្យ​កម្មវិធី​ដក​សេវាកម្ម​នៃ​កម្មវិធី​ផ្ទុក​​លំនាំដើម ដើម្បី​ចម្លង​មាតិកា។​ មិន​សម្រាប់​ប្រើ​ដោយ​កម្មវិធី​លំនាំដើម។"</string>
     <string name="permlab_route_media_output" msgid="1642024455750414694">"នាំ​ផ្លូវ​លទ្ធផល​មេឌៀ"</string>
     <string name="permdesc_route_media_output" msgid="4932818749547244346">"ឲ្យ​កម្មវិធី​នាំ​ផ្លូវ​លទ្ធផល​មេឌៀ​ទៅ​ឧបករណ៍​​ខាង​ក្រៅ​ផ្សេង។"</string>
-    <string name="permlab_access_keyguard_secure_storage" msgid="7565552237977815047">"ចូល​ដំណើរការ​ឧបករណ៍​ផ្ទុក​សុវត្ថិភាព"</string>
+    <string name="permlab_access_keyguard_secure_storage" msgid="7565552237977815047">"ចូល​ដំណើរការ​ឧបករណ៍​ផ្ទុក​សុវត្ថិភាព​"</string>
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"ឲ្យ​កម្មវិធី​ចូល​​ការ​ផ្ទុក​មាន​សុវត្ថិភាព keguard ។"</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"ពិនិត្យ​ការ​បង្ហាញ និង​លាក់​ការ​ការពារ"</string>
     <string name="permdesc_control_keyguard" msgid="3043732290518629061">"ឲ្យ​កម្មវិធី​គ្រប់គ្រង keguard ។"</string>
@@ -1377,7 +1375,7 @@
     <string name="ime_action_go" msgid="8320845651737369027">"ទៅ"</string>
     <string name="ime_action_search" msgid="658110271822807811">"ស្វែងរក"</string>
     <string name="ime_action_send" msgid="2316166556349314424">"ផ្ញើ"</string>
-    <string name="ime_action_next" msgid="3138843904009813834">"បន្ទាប់"</string>
+    <string name="ime_action_next" msgid="3138843904009813834">"បន្ទាប់​"</string>
     <string name="ime_action_done" msgid="8971516117910934605">"រួចរាល់"</string>
     <string name="ime_action_previous" msgid="1443550039250105948">"មុន"</string>
     <string name="ime_action_default" msgid="2840921885558045721">"អនុវត្ត"</string>
@@ -1386,7 +1384,7 @@
     <string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"កម្មវិធី​មួយ ឬ​ច្រើន​ដូច​ខាង​ក្រោម​ស្នើ​សិទ្ធិ ដើម្បី​ចូល​គណនី​របស់​អ្នក​ឥឡូវ និង​ពេល​អនាគត។"</string>
     <string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"តើ​អ្នក​ចង់​អនុញ្ញាត​សំណើ​នេះ?"</string>
     <string name="grant_permissions_header_text" msgid="6874497408201826708">"ស្នើ​ចូល"</string>
-    <string name="allow" msgid="7225948811296386551">"អនុញ្ញាត"</string>
+    <string name="allow" msgid="7225948811296386551">"អនុញ្ញាត​"</string>
     <string name="deny" msgid="2081879885755434506">"បដិសេធ"</string>
     <string name="permission_request_notification_title" msgid="6486759795926237907">"បាន​ស្នើ​សិទ្ធិ"</string>
     <string name="permission_request_notification_with_subtitle" msgid="8530393139639560189">"បាន​ស្នើ​សិទ្ធិ\nសម្រាប់​គណនី <xliff:g id="ACCOUNT">%s</xliff:g> ។"</string>
@@ -1409,12 +1407,12 @@
     <string name="no_file_chosen" msgid="6363648562170759465">"គ្មាន​ឯកសារ​បាន​ជ្រើស"</string>
     <string name="reset" msgid="2448168080964209908">"កំណត់​ឡើងវិញ"</string>
     <string name="submit" msgid="1602335572089911941">"ដាក់​ស្នើ"</string>
-    <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"បាន​បើក​របៀប​រថយន្ត"</string>
+    <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"បាន​បើក​របៀប​រថយន្ត​"</string>
     <string name="car_mode_disable_notification_message" msgid="8035230537563503262">"ប៉ះ​ ដើម្បី​ចេញ​ពី​របៀប​រថយន្ត​។"</string>
     <string name="tethered_notification_title" msgid="3146694234398202601">"ភ្ជាប់ ឬ​ហតស្ពត​សកម្ម"</string>
     <string name="tethered_notification_message" msgid="6857031760103062982">"ប៉ះ​ ដើម្បី​រៀបចំ។"</string>
     <string name="back_button_label" msgid="2300470004503343439">"ថយក្រោយ"</string>
-    <string name="next_button_label" msgid="1080555104677992408">"បន្ទាប់"</string>
+    <string name="next_button_label" msgid="1080555104677992408">"បន្ទាប់​"</string>
     <string name="skip_button_label" msgid="1275362299471631819">"រំលង"</string>
     <string name="throttle_warning_notification_title" msgid="4890894267454867276">"ការ​ប្រើ​ទិន្នន័យ​ចល័ត​ខ្ពស់"</string>
     <string name="throttle_warning_notification_message" msgid="3340822228599337743">"ប៉ះ​ ដើម្បី​​ស្វែងយល់​បន្ថែម​អំពី​ការ​ប្រើ​​​ទិន្នន័យ​ចល័ត​។"</string>
@@ -1440,7 +1438,7 @@
     <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"ឧបករណ៍​ផ្ទុក​យូអេសប៊ី​បច្ចុប្បន្ន​កំពុង​ប្រើ​ដោយ​កុំព្យូទ័រ។"</string>
     <string name="media_shared" product="default" msgid="5706130568133540435">"បច្ចុប្បន្ន​កាត​អេសឌី​កំពុង​ប្រើ​ដោយ​កុំព្យូទ័រ"</string>
     <string name="media_unknown_state" msgid="729192782197290385">"មិន​ស្គាល់​ស្ថានភាព​មេឌៀ​ខាង​ក្រៅ។"</string>
-    <string name="share" msgid="1778686618230011964">"ចែក​រំលែក"</string>
+    <string name="share" msgid="1778686618230011964">"ចែក​រំលែក​"</string>
     <string name="find" msgid="4808270900322985960">"រក"</string>
     <string name="websearch" msgid="4337157977400211589">"ស្វែងរក​តាម​បណ្ដាញ"</string>
     <string name="find_next" msgid="5742124618942193978">"រក​បន្ទាប់"</string>
@@ -1456,7 +1454,7 @@
     <string name="sync_undo_deletes" msgid="2941317360600338602">"មិន​ធ្វើ​ការ​លុប​វិញ"</string>
     <string name="sync_do_nothing" msgid="3743764740430821845">"មិន​ធ្វើអ្វី​ទេ​ឥឡូវ"</string>
     <string name="choose_account_label" msgid="5655203089746423927">"ជ្រើស​គណនី"</string>
-    <string name="add_account_label" msgid="2935267344849993553">"បន្ថែម​គណនី​ថ្មី"</string>
+    <string name="add_account_label" msgid="2935267344849993553">"បន្ថែម​គណនី​ថ្មី​​"</string>
     <string name="add_account_button_label" msgid="3611982894853435874">"បន្ថែម​គណនី"</string>
     <string name="number_picker_increment_button" msgid="2412072272832284313">"បង្កើន"</string>
     <string name="number_picker_decrement_button" msgid="476050778386779067">"បន្ថយ"</string>
@@ -1475,15 +1473,15 @@
     <string name="date_picker_increment_year_button" msgid="6318697384310808899">"បង្កើន​​ឆ្នាំ"</string>
     <string name="date_picker_decrement_year_button" msgid="4482021813491121717">"បន្ថយ​ឆ្នាំ"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
-    <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"បោះ​បង់"</string>
+    <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"បោះ​បង់​"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"លុប"</string>
     <string name="keyboardview_keycode_done" msgid="1992571118466679775">"រួចរាល់"</string>
     <string name="keyboardview_keycode_mode_change" msgid="4547387741906537519">"ប្ដូរ​របៀប"</string>
     <string name="keyboardview_keycode_shift" msgid="2270748814315147690">"Shift"</string>
     <string name="keyboardview_keycode_enter" msgid="2985864015076059467">"Enter"</string>
-    <string name="activitychooserview_choose_application" msgid="2125168057199941199">"ជ្រើស​កម្មវិធី"</string>
+    <string name="activitychooserview_choose_application" msgid="2125168057199941199">"ជ្រើស​កម្មវិធី​​"</string>
     <string name="activitychooserview_choose_application_error" msgid="8624618365481126668">"មិន​អាច​ចាប់ផ្ដើម <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
-    <string name="shareactionprovider_share_with" msgid="806688056141131819">"ចែករំលែក​ជា​មួយ"</string>
+    <string name="shareactionprovider_share_with" msgid="806688056141131819">"ចែករំលែក​ជា​មួយ​"</string>
     <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"ចែក​រំលែក​ជា​មួយ <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"គ្រប់គ្រង​ការ​រុញ។ ប៉ះ &amp; សង្កត់។"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"អូស​ ដើម្បី​ដោះ​សោ។"</string>
@@ -1497,7 +1495,7 @@
     <string name="storage_internal" msgid="4891916833657929263">"ឧបករណ៍​ផ្ទុក​ខាង​ក្នុង"</string>
     <string name="storage_sd_card" msgid="3282948861378286745">"កាត​អេសឌី"</string>
     <string name="storage_usb" msgid="3017954059538517278">"ឧបករណ៍​ផ្ទុក​យូអេសប៊ី"</string>
-    <string name="extract_edit_menu_button" msgid="8940478730496610137">"កែសម្រួល"</string>
+    <string name="extract_edit_menu_button" msgid="8940478730496610137">"កែសម្រួល​"</string>
     <string name="data_usage_warning_title" msgid="1955638862122232342">"ការព្រមាន​ប្រើ​ទិន្នន័យ"</string>
     <string name="data_usage_warning_body" msgid="2814673551471969954">"ប៉ះ ដើម្បី​មើល​ការ​ប្រើ និង​ការ​កំណត់។"</string>
     <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"បាន​បិទ​ទិន្នន័យ 2G​-3G"</string>
@@ -1554,7 +1552,7 @@
     <string name="media_route_status_available" msgid="6983258067194649391">"ទំនេរ"</string>
     <string name="media_route_status_not_available" msgid="6739899962681886401">"មិន​ទំនេរ"</string>
     <string name="media_route_status_in_use" msgid="4533786031090198063">"កំពុង​ប្រើ"</string>
-    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"អេក្រង់​ជាប់"</string>
+    <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"អេក្រង់​ជាប់​"</string>
     <string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"អេក្រង់ HDMI"</string>
     <string name="display_manager_overlay_display_name" msgid="5142365982271620716">"#<xliff:g id="ID">%1$d</xliff:g> ត្រួត​គ្នា"</string>
     <string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
@@ -1586,7 +1584,7 @@
     <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"ព្យាយាម​លំនាំ​ច្រើន​ពេក"</string>
     <string name="kg_login_instructions" msgid="1100551261265506448">"ដើម្បី​ដោះ​សោ ចូល​ក្នុង​គណនី Google ។"</string>
     <string name="kg_login_username_hint" msgid="5718534272070920364">"ឈ្មោះ​អ្នក​ប្រើ (អ៊ី​ម៉ែ​ល​)"</string>
-    <string name="kg_login_password_hint" msgid="9057289103827298549">"ពាក្យសម្ងាត់"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"ពាក្យសម្ងាត់​"</string>
     <string name="kg_login_submit_button" msgid="5355904582674054702">"ចូល"</string>
     <string name="kg_login_invalid_input" msgid="5754664119319872197">"ឈ្មោះ​អ្នកប្រើ ឬ​ពាក្យ​សម្ងាត់​មិន​ត្រឹមត្រូវ។"</string>
     <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"ភ្លេច​ឈ្មោះ​អ្នកប្រើ ឬ​ពាក្យ​សម្ងាត់​របស់​អ្នក?\nមើល "<b>"google.com/accounts/recovery"</b>" ។"</string>
@@ -1695,7 +1693,7 @@
     <string name="mediasize_japanese_you4" msgid="2091777168747058008">"You4"</string>
     <string name="mediasize_unknown_portrait" msgid="3088043641616409762">"​មិន​ស្គាល់​បញ្ឈរ"</string>
     <string name="mediasize_unknown_landscape" msgid="4876995327029361552">"មិន​ស្គាល់​ទេសភាព"</string>
-    <string name="write_fail_reason_cancelled" msgid="7091258378121627624">"បាន​បោះ​បង់"</string>
+    <string name="write_fail_reason_cancelled" msgid="7091258378121627624">"បាន​បោះ​បង់​"</string>
     <string name="write_fail_reason_cannot_write" msgid="8132505417935337724">"កំហុស​ក្នុង​ការ​សរសេរ​មាតិកា"</string>
     <string name="reason_unknown" msgid="6048913880184628119">"មិន​ស្គាល់"</string>
     <string name="reason_service_unavailable" msgid="7824008732243903268">"មិន​បា​ន​បើក​សេវាកម្ម​បោះពុម្ព"</string>
@@ -1727,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"ជ្រើស​ឆ្នាំ"</string>
     <string name="item_is_selected" msgid="949687401682476608">"បាន​ជ្រើស <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"បាន​លុប <xliff:g id="KEY">%1$s</xliff:g>"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"កន្លែង​ធ្វើការ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"ប្រើ​ការ​ចាក់សោ​កម្មវិធី?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"ចាក់សោ​កម្មវិធី​គឺ​ចាក់​សោ​ការ​បង្ហាញ​​ក្នុង​កម្មវិធី​តែ​មួយ។\n\nដើម្បី​ចាកចេញ ចុច​ និង​សង្កត់​ប៊ូតុង​កម្មវិធី​ថ្មីៗ $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"ទេ"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"ចាប់ផ្ដើម"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"ចាប់ផ្ដើម​ការ​ចាក់​សោ​កម្មវិធី"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"ចេញ​ពី​ការ​ចាក់​សោ​កម្មវិធី"</string>
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index cffe6bb..d2fd2b0 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -1001,10 +1001,8 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"앱이 설치된 알람 시계 앱에서 알람을 설정할 수 있도록 허용합니다. 일부 알람 시계 앱에는 이 기능이 구현되지 않을 수 있습니다."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"음성사서함 추가"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"앱이 음성사서함에 메시지를 추가할 수 있도록 허용합니다."</string>
-    <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) -->
-    <skip />
-    <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) -->
-    <skip />
+    <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"모든 음성사서함 읽기"</string>
+    <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"앱이 모든 음성사서함을 읽을 수 있도록 허용합니다."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"브라우저 위치 정보 권한 수정"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"앱이 브라우저의 위치 정보 권한을 수정할 수 있도록 허용합니다. 이 경우 악성 앱이 이 기능을 이용하여 임의의 웹사이트에 위치 정보를 보낼 수 있습니다."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"패키지 확인"</string>
@@ -1727,4 +1725,17 @@
     <string name="select_year" msgid="7952052866994196170">"연도 선택"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g>이(가) 선택됨"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> 삭제됨"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"업무용 <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for lock_to_app_title (5895142291937470019) -->
+    <skip />
+    <!-- no translation found for lock_to_app_description (8597199033462406175) -->
+    <skip />
+    <!-- no translation found for lock_to_app_negative (8522854387366288195) -->
+    <skip />
+    <!-- no translation found for lock_to_app_positive (7085139175671313864) -->
+    <skip />
+    <!-- no translation found for lock_to_app_start (8889002974248178076) -->
+    <skip />
+    <!-- no translation found for lock_to_app_exit (7033017307788432861) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index b44c9e0..8de71f9 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -1705,7 +1705,7 @@
     <string name="restr_pin_enter_old_pin" msgid="1462206225512910757">"PIN ປະ​ຈຸ​ບັນ"</string>
     <string name="restr_pin_enter_new_pin" msgid="5959606691619959184">"ລະຫັດ PIN ໃໝ່"</string>
     <string name="restr_pin_confirm_pin" msgid="8501523829633146239">"ຢືນຢັນລະຫັດ PIN ໃໝ່"</string>
-    <string name="restr_pin_create_pin" msgid="8017600000263450337">"ສ້າງ PIN ສໍາ​ລັບ​ການ​ປັບ​ປຸງ​ຂໍ້ຈໍາ​ກັດ"</string>
+    <string name="restr_pin_create_pin" msgid="8017600000263450337">"ສ້າງ PIN ສໍາ​ລັບ​ການ​ປັບ​ປຸງ​ຂໍ້ຈໍາ​ກັດ​"</string>
     <string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN ບໍ່​ກົງກັນ. ລອງໃໝ່ອີກຄັ້ງ​."</string>
     <string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN ​ສັ້ນ​ເກີນ​ໄປ​. ຕ້ອງມີຢ່າງໜ້ອຍ 4 ຫຼັກ​."</string>
   <plurals name="restr_pin_countdown">
@@ -1725,4 +1725,17 @@
     <string name="select_year" msgid="7952052866994196170">"ເລືອກ​ປີ"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> ຖືກເລືອກແລ້ວ"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> ຖືກລຶບແລ້ວ"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"​ບ່ອນ​ເຮັດ​ວຽກ <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for lock_to_app_title (5895142291937470019) -->
+    <skip />
+    <!-- no translation found for lock_to_app_description (8597199033462406175) -->
+    <skip />
+    <!-- no translation found for lock_to_app_negative (8522854387366288195) -->
+    <skip />
+    <!-- no translation found for lock_to_app_positive (7085139175671313864) -->
+    <skip />
+    <!-- no translation found for lock_to_app_start (8889002974248178076) -->
+    <skip />
+    <!-- no translation found for lock_to_app_exit (7033017307788432861) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 82548a0..dcac639 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Pasirinkite metus"</string>
     <string name="item_is_selected" msgid="949687401682476608">"Pasirinkta: <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"Ištrinta: <xliff:g id="KEY">%1$s</xliff:g>"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"Darbo <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Naudoti programos užrakinimo funkciją?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Naudojant programos užrakinimo funkciją ekrane užrakinama viena programa.\n\nJei norite išeiti, paspauskite ir palaikykite paspaudę naujausių programų mygtuką $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"NE"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"ĮJUNGTI"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Įjungti programos užrakinimo funkciją"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Išeiti iš programos užrakinimo funkcijos"</string>
 </resources>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 798a39d..a9a9984 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -1001,10 +1001,8 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Ļauj lietotnei iestatīt signālu instalētajā modinātājpulksteņa lietotnē. Dažās modinātājpulksteņu lietotnēs šo funkciju, iespējams, nevar ieviest."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"pievienot balss pastu"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Ļauj lietotnei pievienot ziņojumus jūsu balss pasta iesūtnei."</string>
-    <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) -->
-    <skip />
-    <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) -->
-    <skip />
+    <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"lasīt visus balss pasta ziņojumus"</string>
+    <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Ļauj lietotnei lasīt visus jūsu balss pasta ziņojumus."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"pārveidot pārlūkprogrammas ģeogrāfiskās atrašanās vietas atļaujas"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Ļauj lietotnei modificēt pārlūkprogrammas ģeogrāfiskās atrašanās vietas atļaujas. Ļaunprātīgas lietotnes to var izmantot, lai atļautu atrašanās vietas informācijas sūtīšanu uz citām vietnēm."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"pakotņu verificēšana"</string>
@@ -1727,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Atlasiet gadu."</string>
     <string name="item_is_selected" msgid="949687401682476608">"Atlasīts: <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> tika dzēsts."</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"Darbā: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Vai izmantot bloķēšanu darbībai vienā lietotnē?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Konfigurācija \"Bloķēšana darbībai vienā lietotnē\" nobloķē ekrānu vienā lietotnē.\n\nLai izietu, nospiediet un turiet pogu “Pēdējās izmantotās lietotnes” $."</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"NĒ"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"SĀKT"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Sākt bloķēšanu darbībai vienā lietotnē"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Iziet no bloķēšanas darbībai vienā lietotnē"</string>
 </resources>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index d19d607..c55bbcd 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Жилийг сонгоно уу"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> сонгогдсон"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> устсан"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"Ажлын <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Апп-дотор-түгжих-г ашиглах уу?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Апп-дотор-түгжих нь дэлгэцийг нэг апп дотор түгжинэ.\n\nГарахын тулд саяхны апп-ууд товчийг дараад барина уу $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"ҮГҮЙ"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"ЭХЛҮҮЛЭХ"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Апп-дотор-түгжих-г эхлүүлэх"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Апп-дотор-түгжих-с гарах"</string>
 </resources>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 49347a7..7c35ec5 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -1001,10 +1001,8 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Membenarkan apl untuk menetapkan penggera dalam apl penggera jam yang dipasang. Sesetengah applikasi jam penggera tidak boleh melaksanakan ciri ini."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"tambah mel suara"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Membenarkan apl untuk menambahkan mesej pada peti masuk mel suara anda."</string>
-    <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) -->
-    <skip />
-    <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) -->
-    <skip />
+    <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"baca semua mel suara"</string>
+    <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Membenarkan apl membaca semua mel suara anda."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"ubah suai kebenaran geolokasi Penyemak Imbas"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Membenarkan apl untuk mengubah suai kebenaran geolokasi Penyemak Imbas. Apl hasad boleh menggunakannya untuk membenarkan menghantar maklumat lokasi kepada laman web sembarangan."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"sahkan pakej"</string>
@@ -1727,4 +1725,18 @@
     <string name="select_year" msgid="7952052866994196170">"Pilih tahun"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> dipilih"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> dipadamkan"</string>
+    <!-- no translation found for managed_profile_label_badge (2355652472854327647) -->
+    <skip />
+    <!-- no translation found for lock_to_app_title (5895142291937470019) -->
+    <skip />
+    <!-- no translation found for lock_to_app_description (8597199033462406175) -->
+    <skip />
+    <!-- no translation found for lock_to_app_negative (8522854387366288195) -->
+    <skip />
+    <!-- no translation found for lock_to_app_positive (7085139175671313864) -->
+    <skip />
+    <!-- no translation found for lock_to_app_start (8889002974248178076) -->
+    <skip />
+    <!-- no translation found for lock_to_app_exit (7033017307788432861) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 40764c7..fb3f90e 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -1001,10 +1001,8 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Lar appen stille inn alarmen for en installert alarmklokke-app. Enkelte alarmklokke-apper implementerer kanskje ikke denne funksjonen."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"legge til talepost"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Lar appen legge til meldinger i talepostkassen din."</string>
-    <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) -->
-    <skip />
-    <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) -->
-    <skip />
+    <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"lese alle meldingene i talepostkassen"</string>
+    <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Lar appen lese alle meldingene i talepostkassen din."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"endre nettleserens tillatelser for geoposisjonering"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Lar appen endre nettleserens tillatelser for geoposisjonering. Ondsinnede apper kan bruke dette for å tillate sending av posisjonsinformasjon til vilkårlige nettsteder."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"bekrefte pakker"</string>
@@ -1727,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Velg året"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> er valgt"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> er slettet"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"Jobb-<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Vil du bruke lås-til-app?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Lås-til-app låser skjermen i en enkelt app.\n\nFor å avslutte trykker du på og holder nede nylige apper-knappen $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"NEI"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"START"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Start lås-til-app"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Avslutt lås-til-app"</string>
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 37c2594..b60d8c0 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Jaar selecteren"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> geselecteerd"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> verwijderd"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"Werk <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Lock-to-app gebruiken?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Met Lock-to-app wordt het scherm vergrendeld in één app.\n\nAls u dit wilt afsluiten, houdt u de knop \'Recente apps\' $ ingedrukt"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"NEE"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"START"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Lock-to-app starten"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Lock-to-app afsluiten"</string>
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index a3282e9..f71c8a8 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Wybierz rok"</string>
     <string name="item_is_selected" msgid="949687401682476608">"Wybrałeś <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> usunięte"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (praca)"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Chcesz użyć funkcji lock-to-app?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Po włączeniu funkcji lock-to-app na ekranie będzie wyświetlona pojedyncza aplikacja.\n\nAby wyłączyć tę funkcję, naciśnij i przytrzymaj przycisk ostatnio używanych aplikacji $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"NIE"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"START"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Włącz funkcję lock-to-app"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Wyłącz funkcję lock-to-app"</string>
 </resources>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index e85d902..4c5140f 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -1725,4 +1725,17 @@
     <string name="select_year" msgid="7952052866994196170">"Selecionar ano"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> selecionado"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> eliminado"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de trabalho"</string>
+    <!-- no translation found for lock_to_app_title (5895142291937470019) -->
+    <skip />
+    <!-- no translation found for lock_to_app_description (8597199033462406175) -->
+    <skip />
+    <!-- no translation found for lock_to_app_negative (8522854387366288195) -->
+    <skip />
+    <!-- no translation found for lock_to_app_positive (7085139175671313864) -->
+    <skip />
+    <!-- no translation found for lock_to_app_start (8889002974248178076) -->
+    <skip />
+    <!-- no translation found for lock_to_app_exit (7033017307788432861) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 59328f5..e677fb7 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1001,10 +1001,8 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Permite que o aplicativo defina um alarme em um aplicativo despertador instalado. Alguns aplicativos despertador podem não implementar este recurso."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"adicionar correio de voz"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permite que o aplicativo adicione mensagens a sua caixa de entrada do correio de voz."</string>
-    <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) -->
-    <skip />
-    <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) -->
-    <skip />
+    <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"ler todo o correio de voz"</string>
+    <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Permite que o aplicativo leia todos os seus correios de voz."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Modifique as permissões de geolocalização de seu navegador"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permite que o aplicativo modifique as permissões de geolocalização do navegador. Aplicativos maliciosos podem usar isso para permitir o envio de informações locais para sites arbitrários."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"verificar pacotes"</string>
@@ -1727,4 +1725,17 @@
     <string name="select_year" msgid="7952052866994196170">"Selecione o ano"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> selecionado"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> excluído"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"Trabalho: <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for lock_to_app_title (5895142291937470019) -->
+    <skip />
+    <!-- no translation found for lock_to_app_description (8597199033462406175) -->
+    <skip />
+    <!-- no translation found for lock_to_app_negative (8522854387366288195) -->
+    <skip />
+    <!-- no translation found for lock_to_app_positive (7085139175671313864) -->
+    <skip />
+    <!-- no translation found for lock_to_app_start (8889002974248178076) -->
+    <skip />
+    <!-- no translation found for lock_to_app_exit (7033017307788432861) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 83ba3a6..880a05d 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -2879,4 +2879,18 @@
     <skip />
     <!-- no translation found for deleted_key (7659477886625566590) -->
     <skip />
+    <!-- no translation found for managed_profile_label_badge (2355652472854327647) -->
+    <skip />
+    <!-- no translation found for lock_to_app_title (5895142291937470019) -->
+    <skip />
+    <!-- no translation found for lock_to_app_description (8597199033462406175) -->
+    <skip />
+    <!-- no translation found for lock_to_app_negative (8522854387366288195) -->
+    <skip />
+    <!-- no translation found for lock_to_app_positive (7085139175671313864) -->
+    <skip />
+    <!-- no translation found for lock_to_app_start (8889002974248178076) -->
+    <skip />
+    <!-- no translation found for lock_to_app_exit (7033017307788432861) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 11236b5..b734b22 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -1001,10 +1001,8 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Permite aplicaţiei să seteze o alarmă într-o aplicaţie de ceas cu alarmă instalată. Este posibil ca unele aplicaţii de ceas cu alarmă să nu implementeze această funcţie."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"adăugare mesagerie vocală"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Permite aplicaţiei să adauge mesaje în Mesaje primite în mesageria vocală."</string>
-    <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) -->
-    <skip />
-    <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) -->
-    <skip />
+    <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"acces la toate mesajele vocale"</string>
+    <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Permite aplicației să acceseze toate mesajele vocale."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"modificare permisiuni pentru locaţia geografică a browserului"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Permite aplicaţiei să modifice permisiunile privind locaţia geografică a browserului. Aplicaţiile rău intenţionate pot utiliza această permisiune pentru a permite trimiterea informaţiilor privind locaţia către site-uri web arbitrare."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"verificare pachete"</string>
@@ -1727,4 +1725,17 @@
     <string name="select_year" msgid="7952052866994196170">"Selectați anul"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> selectat"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> a fost șters"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> de serviciu"</string>
+    <!-- no translation found for lock_to_app_title (5895142291937470019) -->
+    <skip />
+    <!-- no translation found for lock_to_app_description (8597199033462406175) -->
+    <skip />
+    <!-- no translation found for lock_to_app_negative (8522854387366288195) -->
+    <skip />
+    <!-- no translation found for lock_to_app_positive (7085139175671313864) -->
+    <skip />
+    <!-- no translation found for lock_to_app_start (8889002974248178076) -->
+    <skip />
+    <!-- no translation found for lock_to_app_exit (7033017307788432861) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index c5f4c13..f727364 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1725,4 +1725,17 @@
     <string name="select_year" msgid="7952052866994196170">"Выберите год"</string>
     <string name="item_is_selected" msgid="949687401682476608">"Выбран элемент <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"Цифра <xliff:g id="KEY">%1$s</xliff:g> удалена"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"Рабочий <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for lock_to_app_title (5895142291937470019) -->
+    <skip />
+    <!-- no translation found for lock_to_app_description (8597199033462406175) -->
+    <skip />
+    <!-- no translation found for lock_to_app_negative (8522854387366288195) -->
+    <skip />
+    <!-- no translation found for lock_to_app_positive (7085139175671313864) -->
+    <skip />
+    <!-- no translation found for lock_to_app_start (8889002974248178076) -->
+    <skip />
+    <!-- no translation found for lock_to_app_exit (7033017307788432861) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index eb685ba..0d4ee13 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -1001,10 +1001,8 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Umožňuje aplikácii nastaviť budík v nainštalovanej aplikácii budík. Niektoré aplikácie budíka nemusia túto funkciu implementovať."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"pridať hlasovú schránku"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Umožní aplikácii pridávať správy do doručenej pošty hlasovej schránky."</string>
-    <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) -->
-    <skip />
-    <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) -->
-    <skip />
+    <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"čítanie všetkých hlasových schránok"</string>
+    <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Umožňuje aplikácii čítať všetky vaše hlasové schránky."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"zmeniť povolenia prehliadača poskytovať informácie o zemepisnej polohe"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Umožňuje aplikácii zmeniť povolenia prehliadača na poskytovanie údajov o zemepisnej polohe. Škodlivé aplikácie to môžu použiť na odosielanie informácií o polohe ľubovoľným webovým stránkam."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"overiť balíky"</string>
@@ -1727,4 +1725,17 @@
     <string name="select_year" msgid="7952052866994196170">"Vyberte rok"</string>
     <string name="item_is_selected" msgid="949687401682476608">"Bola vybratá položka <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"Číslo <xliff:g id="KEY">%1$s</xliff:g> bolo odstránené"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"Práca – <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <!-- no translation found for lock_to_app_title (5895142291937470019) -->
+    <skip />
+    <!-- no translation found for lock_to_app_description (8597199033462406175) -->
+    <skip />
+    <!-- no translation found for lock_to_app_negative (8522854387366288195) -->
+    <skip />
+    <!-- no translation found for lock_to_app_positive (7085139175671313864) -->
+    <skip />
+    <!-- no translation found for lock_to_app_start (8889002974248178076) -->
+    <skip />
+    <!-- no translation found for lock_to_app_exit (7033017307788432861) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 47568d6..44c523c 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -1001,10 +1001,8 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Programu omogoča nastavitev alarma v nameščenem programu budilke. Nekateri programi budilke morda nimajo te funkcije."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"dodajanje odzivnika"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Programu omogoča dodajanje sporočil prejetim sporočilom odzivnika."</string>
-    <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) -->
-    <skip />
-    <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) -->
-    <skip />
+    <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"branje vseh sporočil v odzivniku"</string>
+    <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Aplikaciji omogoča branje vseh sporočil v odzivniku."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Spreminjanje dovoljenj za geolokacijo brskalnika"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Programu omogoča spreminjanje geolokacijskih dovoljenj v brskalniku. Zlonamerni programi lahko to izkoristijo za pošiljanje podatkov o lokaciji poljubnim spletnim mestom."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"preveri pakete"</string>
@@ -1727,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Izberite leto"</string>
     <string name="item_is_selected" msgid="949687401682476608">"Izbrano: <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"Številka <xliff:g id="KEY">%1$s</xliff:g> je izbrisana"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> za delo"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Želite uporabiti zaklepanje v aplikaciji?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Zaklepanje v aplikaciji zaklene zaslon v eni aplikaciji.\n\nČe želite zapustiti ta način, pritisnite in pridržite gumb za nedavne aplikacije $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"NE"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"ZAŽENI"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Zagon zaklepanja v aplikaciji"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Izhod iz zaklepanja v aplikaciji"</string>
 </resources>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 4758c94..a07b7fa 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -1725,4 +1725,17 @@
     <string name="select_year" msgid="7952052866994196170">"Изаберите годину"</string>
     <string name="item_is_selected" msgid="949687401682476608">"Изабрали сте <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"Избрисали сте <xliff:g id="KEY">%1$s</xliff:g>"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> на послу"</string>
+    <!-- no translation found for lock_to_app_title (5895142291937470019) -->
+    <skip />
+    <!-- no translation found for lock_to_app_description (8597199033462406175) -->
+    <skip />
+    <!-- no translation found for lock_to_app_negative (8522854387366288195) -->
+    <skip />
+    <!-- no translation found for lock_to_app_positive (7085139175671313864) -->
+    <skip />
+    <!-- no translation found for lock_to_app_start (8889002974248178076) -->
+    <skip />
+    <!-- no translation found for lock_to_app_exit (7033017307788432861) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index af85340..4db7351 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Välj år"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> har markerats"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> har tagits bort"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> för arbetet"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Vill du använda Lås till app?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Med funktionen Lås till app låses skärmen i en enskild app.\n\nAvsluta genom att trycka länge på knappen för de senaste apparna $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"NEJ"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"STARTA"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Starta Lås till app"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Avsluta Lås till app"</string>
 </resources>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 755b9d2..df51691 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Chagua mwaka"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> kimechaguliwa"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> kimefutwa"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"Kazi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Ungependa kutumia lazimisha kutumia programu?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Lazimisha kutumia programu huonyeshwa katika programu moja. \n\n Ili uondoke bonyeza na ushikilie kitufe cha programu za hivi majuzi $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"HAPANA"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"ANZA"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Anzisha Lazimisha kutumia programu"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Ondoka kwenye Lazimisha kutumia programu"</string>
 </resources>
diff --git a/core/res/res/values-television/themes.xml b/core/res/res/values-television/themes.xml
index f92ff40..3333f1b 100644
--- a/core/res/res/values-television/themes.xml
+++ b/core/res/res/values-television/themes.xml
@@ -16,8 +16,13 @@
 <resources>
     <style name="Theme.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
     <style name="Theme.Dialog.AppError" parent="Theme.Leanback.Dialog.AppError" />
+    <style name="Theme.Dialog.TimePicker" parent="Theme.Leanback.Dialog.TimePicker" />
     <style name="Theme.Holo.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
+    <style name="Theme.Holo.Dialog.TimePicker" parent="Theme.Leanback.Dialog.TimePicker" />
     <style name="Theme.Holo.Light.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
+    <style name="Theme.Holo.Light.Dialog.TimePicker" parent="Theme.Leanback.Light.Dialog.TimePicker" />
     <style name="Theme.Material.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
+    <style name="Theme.Material.Dialog.TimePicker" parent="Theme.Leanback.Dialog.TimePicker" />
     <style name="Theme.Material.Light.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
+    <style name="Theme.Material.Light.Dialog.TimePicker" parent="Theme.Leanback.Light.Dialog.TimePicker" />
 </resources>
diff --git a/core/res/res/values-television/themes_device_defaults.xml b/core/res/res/values-television/themes_device_defaults.xml
index e01caa3..1938675 100644
--- a/core/res/res/values-television/themes_device_defaults.xml
+++ b/core/res/res/values-television/themes_device_defaults.xml
@@ -16,4 +16,6 @@
 <resources>
     <style name="Theme.DeviceDefault.Dialog.Alert" parent="Theme.Leanback.Dialog.Alert" />
     <style name="Theme.DeviceDefault.Light.Dialog.Alert" parent="Theme.Leanback.Light.Dialog.Alert" />
+    <style name="Theme.DeviceDefault.Dialog.TimePicker" parent="Theme.Leanback.Dialog.TimePicker" />
+    <style name="Theme.DeviceDefault.Light.Dialog.TimePicker" parent="Theme.Leanback.Light.Dialog.TimePicker" />
 </resources>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index b03221d..a0f0bb5 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"เลือกปี"</string>
     <string name="item_is_selected" msgid="949687401682476608">"เลือก <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"ลบ <xliff:g id="KEY">%1$s</xliff:g> แล้ว"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g>ที่ทำงาน"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"ใช้การล็อกแอปไหม"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"การล็อกแอปจะล็อกการแสดงไว้ในแอปเดียว\n\nหากต้องการออก ให้กดปุ่มแอปล่าสุด $ ค้างไว้"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"ไม่"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"เริ่มต้น"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"เริ่มใช้การล็อกแอป"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"ออกจากการล็อกแอป"</string>
 </resources>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index af88c3c..2b0eb8c 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1001,10 +1001,8 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Pinapayagan ang app na magtakda ng alarm sa isang naka-install na app ng alarm clock. Maaaring hindi ipatupad ng ilang apps ng alarm clock ang tampok na ito."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"magdagdag ng voicemail"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Pinapayagan ang app na magdagdag ng mga mensahe sa iyong inbox ng voicemail."</string>
-    <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) -->
-    <skip />
-    <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) -->
-    <skip />
+    <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"basahin ang lahat ng voicemail"</string>
+    <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Pinapayagan ang app na basahin ang lahat ng iyong voicemail."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"baguhin ang mga pahintulot ng geolocation ng Browser"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Pinapayagan ang app na baguhin ang mga pahintulot sa geolocation ng Browser. Maaari itong gamitin ng nakakahamak na apps upang payagan ang pagpapadala ng impormasyon ng lokasyon sa mga hindi tukoy na web site."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"i-verify ang mga package"</string>
@@ -1727,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Pumili ng taon"</string>
     <string name="item_is_selected" msgid="949687401682476608">"Napili ang <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"Tinanggal ang <xliff:g id="KEY">%1$s</xliff:g>"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> sa Trabaho"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Gagamitin ang lock-to-app?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Nila-lock ng Lock-to-app ang display sa iisang app.\n\nUpang lumabas pindutin nang matagal ang button ng mga kamakailang app $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"HINDI"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"SIMULAN"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Simulan ang Lock-to-app"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Lumabas sa Lock-to-app"</string>
 </resources>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index ee8c464..6c3ec18 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1001,10 +1001,8 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Uygulamaya, çalar saat uygulamasının alarmını ayarlama izni verir. Bazı çalar saat uygulamaları bu özelliği uygulayamayabilir."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"sesli mesaj ekle"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Uygulamaya, sesli mesaj gelen kutunuza mesaj ekleme izni verir."</string>
-    <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) -->
-    <skip />
-    <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) -->
-    <skip />
+    <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"tüm sesli mesajları oku"</string>
+    <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"Uygulamanın tüm sesli mesajlarınızı okumasına izin verir."</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"Tarayıcı\'nın coğrafi konum izinlerini değiştir"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Uygulamaya, Tarayıcı\'nın coğrafi konum izinlerini değiştirme izni verir. Kötü amaçlı uygulamalar keyfi web sitelerine konum bilgisi gönderilmesini sağlamak için bunu kullanabilirler."</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"paketleri doğrula"</string>
@@ -1727,4 +1725,17 @@
     <string name="select_year" msgid="7952052866994196170">"Yılı seçin"</string>
     <string name="item_is_selected" msgid="949687401682476608">"<xliff:g id="ITEM">%1$s</xliff:g> seçildi"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> silindi"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> (İş)"</string>
+    <!-- no translation found for lock_to_app_title (5895142291937470019) -->
+    <skip />
+    <!-- no translation found for lock_to_app_description (8597199033462406175) -->
+    <skip />
+    <!-- no translation found for lock_to_app_negative (8522854387366288195) -->
+    <skip />
+    <!-- no translation found for lock_to_app_positive (7085139175671313864) -->
+    <skip />
+    <!-- no translation found for lock_to_app_start (8889002974248178076) -->
+    <skip />
+    <!-- no translation found for lock_to_app_exit (7033017307788432861) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index b85fc99..f439595 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Виберіть рік"</string>
     <string name="item_is_selected" msgid="949687401682476608">"Вибрано: <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> видалено"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"Робоча <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Використовувати блокування в додатку?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Блокування в додатку блокує дисплей у певному додатку.\n\nЩоб вимкнути, натисніть і втримуйте кнопку останніх додатків ($)"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"НІ"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"УВІМКНУТИ"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Увімкнути блокування в додатку"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Вимкнути блокування в додатку"</string>
 </resources>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index b38fb87..9d8905a 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1364,8 +1364,8 @@
     <string name="permdesc_trust_listener" msgid="8233895334214716864">"Cho phép ứng dụng quan sát các thay đổi ở trạng thái đáng tin cậy."</string>
     <string name="permlab_provide_trust_agent" msgid="5465587586091358316">"Cung cấp tác nhân đáng tin cậy."</string>
     <string name="permdesc_provide_trust_agent" msgid="3865702641053068148">"Cho phép ứng dụng cung cấp tác nhân đáng tin cậy."</string>
-    <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"Khởi chạy trình đơn cài đặt đại lý đáng tin cậy."</string>
-    <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"Cho phép ứng dụng khởi chạy hoạt động thay đổi hoạt động của đại lý đáng tin cậy."</string>
+    <string name="permlab_launch_trust_agent_settings" msgid="7494179366945389098">"Chạy menu cài đặt đại lý đáng tin cậy."</string>
+    <string name="permdesc_launch_trust_agent_settings" msgid="985453787420853278">"Cho phép ứng dụng chạy hoạt động thay đổi hoạt động của đại lý đáng tin cậy."</string>
     <string name="permlab_bind_trust_agent_service" msgid="8242093169457695334">"Liên kết với một dịch vụ của đại lý đáng tin cậy"</string>
     <string name="permdesc_bind_trust_agent_service" msgid="7041930026024507515">"Cho phép ứng dụng liên kết với một dịch vụ của đại lý đáng tin cậy."</string>
     <string name="permlab_recovery" msgid="3157024487744125846">"Tương tác với hệ thống khôi phục và bản cập nhật"</string>
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Chọn năm"</string>
     <string name="item_is_selected" msgid="949687401682476608">"Đã chọn <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"Đã xóa <xliff:g id="KEY">%1$s</xliff:g>"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"<xliff:g id="LABEL">%1$s</xliff:g> làm việc"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Sử dụng lock-to-app?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Lock-to-app sẽ khóa màn hình trong một ứng dụng.\n\nĐể thoát, nhấn và giữ nút ứng dụng gần đây $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"KHÔNG"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"BẮT ĐẦU"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Bắt đầu Lock-to-app"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Thoát Lock-to-app"</string>
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index d730c49..eb1cb3b 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1001,10 +1001,8 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"允许应用在已安装的闹钟应用中设置闹钟。有些闹钟应用可能无法实现此功能。"</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"添加语音邮件"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"允许应用向您的语音信箱收件箱添加邮件。"</string>
-    <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) -->
-    <skip />
-    <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) -->
-    <skip />
+    <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"读取所有语音邮件"</string>
+    <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"允许应用读取您所有的语音邮件。"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"修改“浏览器”地理位置的权限"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"允许应用修改“浏览器”的地理位置权限。恶意应用可能借此向任意网站发送位置信息。"</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"验证软件包"</string>
@@ -1727,4 +1725,18 @@
     <string name="select_year" msgid="7952052866994196170">"选择年份"</string>
     <string name="item_is_selected" msgid="949687401682476608">"已选择<xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"已删除<xliff:g id="KEY">%1$s</xliff:g>"</string>
+    <!-- no translation found for managed_profile_label_badge (2355652472854327647) -->
+    <skip />
+    <!-- no translation found for lock_to_app_title (5895142291937470019) -->
+    <skip />
+    <!-- no translation found for lock_to_app_description (8597199033462406175) -->
+    <skip />
+    <!-- no translation found for lock_to_app_negative (8522854387366288195) -->
+    <skip />
+    <!-- no translation found for lock_to_app_positive (7085139175671313864) -->
+    <skip />
+    <!-- no translation found for lock_to_app_start (8889002974248178076) -->
+    <skip />
+    <!-- no translation found for lock_to_app_exit (7033017307788432861) -->
+    <skip />
 </resources>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 43a487b..2db1ba6 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1001,10 +1001,8 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"允許應用程式在安裝的鬧鐘應用程式中設定鬧鐘,某些鬧鐘應用程式可能沒有這項功能。"</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"新增留言"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"允許應用程式將訊息加到您的留言信箱收件箱。"</string>
-    <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) -->
-    <skip />
-    <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) -->
-    <skip />
+    <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"讀取所有語音留言"</string>
+    <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"允許應用程式讀取您的所有語音留言。"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"修改瀏覽器地理資訊的權限"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"允許應用程式修改瀏覽器的地理資訊權限。惡意應用程式可能會藉此允許將您的位置資訊任意傳送給某些網站。"</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"驗證套件"</string>
@@ -1727,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"選取年份"</string>
     <string name="item_is_selected" msgid="949687401682476608">"已選取<xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"<xliff:g id="KEY">%1$s</xliff:g> 已刪除"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"公司<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"使用 Lock-to-app?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Lock-to-app 會鎖定螢幕,只顯示單一應用程式的畫面。\n\n如要結束,請按住最近使用的應用程式按鈕 $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"否"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"啟動"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"啟動 Lock-to-app"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"結束 Lock-to-app"</string>
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 6658689..d362084 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -1001,10 +1001,8 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"允許應用程式在安裝的鬧鐘應用程式中設定鬧鐘,某些鬧鐘應用程式可能無法執行這項功能。"</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"新增語音留言"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"允許應用程式將訊息新增至您的語音信箱收件匣。"</string>
-    <!-- no translation found for permlab_readAllVoicemail (5834057671176753416) -->
-    <skip />
-    <!-- no translation found for permdesc_readAllVoicemail (7429033637738774985) -->
-    <skip />
+    <string name="permlab_readAllVoicemail" msgid="5834057671176753416">"讀取所有語音留言"</string>
+    <string name="permdesc_readAllVoicemail" msgid="7429033637738774985">"允許應用程式讀取您的所有語音留言。"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"修改瀏覽器地理資訊的權限"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"允許應用程式修改瀏覽器的地理位置權限。請注意,惡意應用程式可能利用此功能允許將您的位置資訊任意傳送給某些網站。"</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"驗證套件"</string>
@@ -1727,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"選取年份"</string>
     <string name="item_is_selected" msgid="949687401682476608">"已選取 <xliff:g id="ITEM">%1$s</xliff:g>"</string>
     <string name="deleted_key" msgid="7659477886625566590">"已刪除 <xliff:g id="KEY">%1$s</xliff:g>"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"公司<xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"使用 Lock-to-app?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Lock-to-app 會鎖定螢幕,只顯示單一應用程式的畫面。\n\n如要結束,請按住最近使用的應用程式按鈕 $"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"否"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"啟動"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"啟動 Lock-to-app"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"結束 Lock-to-app"</string>
 </resources>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 820ea50..23d2966 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -1725,4 +1725,11 @@
     <string name="select_year" msgid="7952052866994196170">"Khetha unyaka"</string>
     <string name="item_is_selected" msgid="949687401682476608">"I-<xliff:g id="ITEM">%1$s</xliff:g> ekhethiwe"</string>
     <string name="deleted_key" msgid="7659477886625566590">"I-<xliff:g id="KEY">%1$s</xliff:g> isusiwe"</string>
+    <string name="managed_profile_label_badge" msgid="2355652472854327647">"Umsebenzi <xliff:g id="LABEL">%1$s</xliff:g>"</string>
+    <string name="lock_to_app_title" msgid="5895142291937470019">"Sebenzisa isikhiya sohlelo lokusebenza?"</string>
+    <string name="lock_to_app_description" msgid="8597199033462406175">"Isikhiya kuhlelo lokusebenza sikhiyela isibonisi kuhlelo lokusebenza olulodwa.\n\nUkuze uphume cindezela uphinde ubambe inkinobho yezinhlelo zokusebenza zakamuva engu-$"</string>
+    <string name="lock_to_app_negative" msgid="8522854387366288195">"CHA"</string>
+    <string name="lock_to_app_positive" msgid="7085139175671313864">"QALA"</string>
+    <string name="lock_to_app_start" msgid="8889002974248178076">"Qala Isikhiya sohlelo lokusebenza"</string>
+    <string name="lock_to_app_exit" msgid="7033017307788432861">"Phuma kusikhiya sohlelo lokusebenza"</string>
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 4a6311a..a8a4d7a 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2424,7 +2424,7 @@
 
         <!-- Names a View such that it can be identified for Transitions. Names should be
              unique in the View hierarchy. -->
-        <attr name="viewName" format="string" />
+        <attr name="transitionName" format="string" />
 
         <!-- Specifies that this view should permit nested scrolling within a compatible
              ancestor view. -->
@@ -4813,6 +4813,32 @@
                  mirror images so that adjacent images always seam. -->
             <enum name="mirror" value="2" />
         </attr>
+        <!-- Defines the horizontal tile mode. When the tile mode is enabled, the bitmap is repeated.
+             Gravity is ignored when the tile mode is enabled. Default value is "disabled". -->
+        <attr name="tileModeX">
+            <!-- Do not tile the bitmap. This is the default value. -->
+            <enum name="disabled" value="-1" />
+            <!-- Replicates the edge color. -->
+            <enum name="clamp" value="0" />
+            <!-- Repeats the bitmap in both direction. -->
+            <enum name="repeat" value="1" />
+            <!-- Repeats the shader's image horizontally and vertically, alternating
+                 mirror images so that adjacent images always seam. -->
+            <enum name="mirror" value="2" />
+        </attr>
+        <!-- Defines the vertical tile mode. When the tile mode is enabled, the bitmap is repeated.
+             Gravity is ignored when the tile mode is enabled. Default value is "disabled". -->
+        <attr name="tileModeY">
+            <!-- Do not tile the bitmap. This is the default value. -->
+            <enum name="disabled" value="-1" />
+            <!-- Replicates the edge color. -->
+            <enum name="clamp" value="0" />
+            <!-- Repeats the bitmap in both direction. -->
+            <enum name="repeat" value="1" />
+            <!-- Repeats the shader's image horizontally and vertically, alternating
+                 mirror images so that adjacent images always seam. -->
+            <enum name="mirror" value="2" />
+        </attr>
         <!-- Enables or disables the mipmap hint. See
             {@link android.graphics.Bitmap#setHasMipMap(boolean)} for more information.
             Default value is false. -->
@@ -4971,6 +4997,12 @@
         <attr name="height" />
         <!-- Enables or disables dithering. -->
         <attr name="dither" />
+        <!-- If set, specifies the color to apply to the drawable as a tint. By default,
+             no tint is applied. May be a color state list. -->
+        <attr name="tint" />
+        <!-- When a tint color is set, specifies its Porter-Duff blending mode. The
+             default value is src_in, which treats the drawable as an alpha mask. -->
+        <attr name="tintMode" />
     </declare-styleable>
 
     <!-- ========================== -->
@@ -5291,10 +5323,10 @@
         <attr name="interpolator" />
         <!-- The match order to use for the transition. This is a comma-separated
              list of values, containing one or more of the following:
-             id, itemId, viewName, instance. These correspond to
+             id, itemId, name, instance. These correspond to
              {@link android.transition.Transition#MATCH_ID},
              {@link android.transition.Transition#MATCH_ITEM_ID},
-             {@link android.transition.Transition#MATCH_VIEW_NAME}, and
+             {@link android.transition.Transition#MATCH_NAME}, and
              {@link android.transition.Transition#MATCH_INSTANCE}, respectively.
              This corresponds to {@link android.transition.Transition#setMatchOrder(int...)}. -->
         <attr name="matchOrder" format="string" />
@@ -5349,10 +5381,10 @@
         <attr name="targetClass" />
         <!-- The fully-qualified name of the Class to exclude from this transition. -->
         <attr name="excludeClass" format="string" />
-        <!-- The viewName of the target on which this transition will animation changes. -->
-        <attr name="targetViewName" format="string" />
-        <!-- The viewName of the target to exclude from this transition. -->
-        <attr name="excludeViewName" format="string" />
+        <!-- The transitionName of the target on which this transition will animation changes. -->
+        <attr name="targetName" format="string" />
+        <!-- The transitionName of the target to exclude from this transition. -->
+        <attr name="excludeName" format="string" />
     </declare-styleable>
 
     <!-- Use <code>set</code> as the root tag of the XML resource that
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index f304514..dd316ed 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -125,9 +125,6 @@
 
     <color name="micro_text_light">#434343</color>
 
-    <color name="leanback_dark_gray">#ff333333</color>
-    <color name="leanback_light_gray">#ff888888</color>
-
     <drawable name="notification_template_icon_bg">#3333B5E5</drawable>
     <drawable name="notification_template_icon_low_bg">#0cffffff</drawable>
 
diff --git a/core/res/res/values/colors_leanback.xml b/core/res/res/values/colors_leanback.xml
new file mode 100644
index 0000000..dc0c673
--- /dev/null
+++ b/core/res/res/values/colors_leanback.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- Colors specific to Leanback themes. -->
+<resources>
+    <color name="background_leanback_dark">#ff324248</color>
+    <color name="background_leanback_light">#ffeeeeee</color>
+
+    <color name="primary_text_leanback_dark">#cceeeeee</color>
+    <color name="secondary_text_leanback_dark">#99eeeeee</color>
+
+    <color name="primary_text_leanback_light">#cc222222</color>
+    <color name="secondary_text_leanback_light">#99222222</color>
+
+</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index c3e4d94..727d286 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2115,7 +2115,7 @@
   <public type="attr" name="controlY1" />
   <public type="attr" name="controlX2" />
   <public type="attr" name="controlY2" />
-  <public type="attr" name="viewName" />
+  <public type="attr" name="transitionName" />
   <public type="attr" name="transitionGroup" />
   <public type="attr" name="viewportWidth" />
   <public type="attr" name="viewportHeight" />
@@ -2168,8 +2168,8 @@
   <public type="attr" name="fromId" />
   <public type="attr" name="reversible" />
   <public type="attr" name="splitTrack" />
-  <public type="attr" name="targetViewName" />
-  <public type="attr" name="excludeViewName" />
+  <public type="attr" name="targetName" />
+  <public type="attr" name="excludeName" />
   <public type="attr" name="matchOrder" />
   <public type="attr" name="windowDrawsSystemBarBackgrounds" />
   <public type="attr" name="statusBarColor"/>
@@ -2210,6 +2210,11 @@
   <public type="attr" name="propertyXName" />
   <public type="attr" name="propertyYName" />
   <public type="attr" name="relinquishTaskIdentity" />
+  <public type="attr" name="tileModeX" />
+  <public type="attr" name="tileModeY" />
+  <public type="attr" name="actionModeShareDrawable" />
+  <public type="attr" name="actionModeFindDrawable" />
+  <public type="attr" name="actionModeWebSearchDrawable" />
 
   <public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
 
diff --git a/core/res/res/values/styles_leanback.xml b/core/res/res/values/styles_leanback.xml
index a37da4e..72d0379 100644
--- a/core/res/res/values/styles_leanback.xml
+++ b/core/res/res/values/styles_leanback.xml
@@ -14,46 +14,12 @@
      limitations under the License.
 -->
 <resources>
-    <style name="DialogWindowTitle.Leanback" parent="DialogWindowTitle.Holo">
-        <item name="android:textAppearance">@style/TextAppearance.Leanback.DialogWindowTitle</item>
-    </style>
-
-    <style name="TextAppearance.Leanback.DialogWindowTitle" parent="TextAppearance.Holo.DialogWindowTitle">
-        <item name="android:fontFamily">sans-serif-condensed</item>
-        <item name="android:textColor">?attr/textColorPrimary</item>
-    </style>
-
-    <style name="Leanback.ButtonBar" parent="Holo.ButtonBar">
-        <item name="showDividers">none</item>
-    </style>
-
-    <style name="AlertDialog.Leanback" parent="AlertDialog.Holo">
+    <style name="AlertDialog.Leanback" parent="AlertDialog.Material">
         <item name="layout">@android:layout/alert_dialog_leanback</item>
         <item name="buttonPanelSideLayout">@android:layout/alert_dialog_leanback_button_panel_right</item>
-        <item name="progressLayout">@android:layout/progress_dialog_leanback</item>
-        <item name="fullDark">@android:color/background_dark</item>
-        <item name="topDark">@android:color/background_dark</item>
-        <item name="centerDark">@android:color/background_dark</item>
-        <item name="bottomDark">@android:color/background_dark</item>
-        <item name="fullBright">@android:color/background_dark</item>
-        <item name="topBright">@android:color/background_dark</item>
-        <item name="centerBright">@android:color/background_dark</item>
-        <item name="bottomBright">@android:color/background_dark</item>
-        <item name="bottomMedium">@android:color/background_dark</item>
-        <item name="centerMedium">@android:color/background_dark</item>
     </style>
 
     <style name="AlertDialog.Leanback.Light">
-        <item name="fullDark">@android:color/leanback_light_gray</item>
-        <item name="topDark">@android:color/leanback_light_gray</item>
-        <item name="centerDark">@android:color/leanback_light_gray</item>
-        <item name="bottomDark">@android:color/leanback_light_gray</item>
-        <item name="fullBright">@android:color/leanback_light_gray</item>
-        <item name="topBright">@android:color/leanback_light_gray</item>
-        <item name="centerBright">@android:color/leanback_light_gray</item>
-        <item name="bottomBright">@android:color/leanback_light_gray</item>
-        <item name="bottomMedium">@android:color/leanback_light_gray</item>
-        <item name="centerMedium">@android:color/leanback_light_gray</item>
     </style>
 
 </resources>
diff --git a/core/res/res/values/themes_leanback.xml b/core/res/res/values/themes_leanback.xml
index eba8dec..a571b98 100644
--- a/core/res/res/values/themes_leanback.xml
+++ b/core/res/res/values/themes_leanback.xml
@@ -14,26 +14,38 @@
      limitations under the License.
 -->
 <resources>
-    <style name="Theme.Leanback.Dialog.Alert" parent="Theme.Holo.Dialog.BaseAlert">
-      <item name="windowTitleStyle">@style/DialogWindowTitle.Leanback</item>
+    <style name="Theme.Leanback.Dialog.Alert" parent="Theme.Material.Dialog.BaseAlert">
+      <item name="colorBackground">@color/background_leanback_dark</item>
+      <item name="textColorPrimary">@color/primary_text_leanback_dark</item>
+      <item name="textColorSecondary">@color/secondary_text_leanback_dark</item>
       <item name="alertDialogStyle">@style/AlertDialog.Leanback</item>
-      <item name="buttonBarStyle">@style/Leanback.ButtonBar</item>
-      <item name="listDividerAlertDialog">@null</item>
     </style>
 
-    <style name="Theme.Leanback.Light.Dialog.Alert" parent="Theme.Holo.Light.Dialog.BaseAlert">
-      <item name="windowTitleStyle">@style/DialogWindowTitle.Leanback</item>
+    <style name="Theme.Leanback.Light.Dialog.Alert" parent="Theme.Material.Light.Dialog.BaseAlert">
+      <item name="colorBackground">@color/background_leanback_light</item>
+      <item name="textColorPrimary">@color/primary_text_leanback_light</item>
+      <item name="textColorSecondary">@color/secondary_text_leanback_light</item>
       <item name="alertDialogStyle">@style/AlertDialog.Leanback.Light</item>
-      <item name="buttonBarStyle">@style/Leanback.ButtonBar</item>
-      <item name="listDividerAlertDialog">@null</item>
     </style>
 
-    <style name="Theme.Leanback.Light.Dialog" parent="Theme.Holo.Light.Dialog">
-        <item name="windowTitleStyle">@style/DialogWindowTitle.Leanback</item>
+    <style name="Theme.Leanback.Dialog.TimePicker" parent="Theme.Material.Dialog.BaseTimePicker">
+      <item name="colorBackground">@color/background_leanback_dark</item>
+      <item name="textColorPrimary">@color/primary_text_leanback_dark</item>
+      <item name="textColorSecondary">@color/secondary_text_leanback_dark</item>
+      <item name="alertDialogStyle">@style/AlertDialog.Leanback</item>
     </style>
 
-    <style name="Theme.Leanback.Dialog" parent="Theme.Holo.Dialog">
-        <item name="windowTitleStyle">@style/DialogWindowTitle.Leanback</item>
+    <style name="Theme.Leanback.Light.Dialog.TimePicker" parent="Theme.Material.Light.Dialog.BaseTimePicker">
+      <item name="colorBackground">@color/background_leanback_light</item>
+      <item name="textColorPrimary">@color/primary_text_leanback_light</item>
+      <item name="textColorSecondary">@color/secondary_text_leanback_light</item>
+      <item name="alertDialogStyle">@style/AlertDialog.Leanback.Light</item>
+    </style>
+
+    <style name="Theme.Leanback.Light.Dialog" parent="Theme.Material.Light.Dialog">
+    </style>
+
+    <style name="Theme.Leanback.Dialog" parent="Theme.Material.Dialog">
     </style>
 
     <style name="Theme.Leanback.Dialog.AppError" parent="Theme.Leanback.Dialog">
diff --git a/core/res/res/values/themes_material.xml b/core/res/res/values/themes_material.xml
index 77e4307..b52b3a0 100644
--- a/core/res/res/values/themes_material.xml
+++ b/core/res/res/values/themes_material.xml
@@ -1092,26 +1092,30 @@
         <item name="windowCloseOnTouchOutside">false</item>
     </style>
 
-    <!-- Material theme for alert dialog windows, which is used by the
-         {@link android.app.AlertDialog} class.  This is basically a dialog
-         but sets the background to empty so it can do two-tone backgrounds.
-         For applications targeting Honeycomb or newer, this is the default
-         AlertDialog theme. -->
-    <style name="Theme.Material.Dialog.Alert">
+    <style name="Theme.Material.Dialog.BaseAlert">
         <item name="windowBackground">@color/transparent</item>
         <item name="windowTitleStyle">@style/DialogWindowTitle.Material</item>
         <item name="windowMinWidthMajor">@dimen/dialog_min_width_major</item>
         <item name="windowMinWidthMinor">@dimen/dialog_min_width_minor</item>
     </style>
 
-    <!-- Material theme for the TimePicker dialog windows, which is used by the
-         {@link android.app.TimePickerDialog} class. -->
-    <style name="Theme.Material.Dialog.TimePicker">
+    <!-- Material theme for alert dialog windows, which is used by the
+         {@link android.app.AlertDialog} class.  This is basically a dialog
+         but sets the background to empty so it can do two-tone backgrounds.
+         For applications targeting Honeycomb or newer, this is the default
+         AlertDialog theme. -->
+    <style name="Theme.Material.Dialog.Alert" parent="Theme.Material.Dialog.BaseAlert"/>
+
+    <style name="Theme.Material.Dialog.BaseTimePicker">
         <item name="windowBackground">@color/transparent</item>
         <item name="windowTitleStyle">@style/DialogWindowTitle.Material</item>
         <item name="windowContentOverlay">@null</item>
     </style>
 
+    <!-- Material theme for the TimePicker dialog windows, which is used by the
+         {@link android.app.TimePickerDialog} class. -->
+    <style name="Theme.Material.Dialog.TimePicker" parent="Theme.Material.Dialog.BaseTimePicker"/>
+
     <!-- Theme for a window that will be displayed either full-screen on
          smaller screens (small, normal) or as a dialog on larger screens
          (large, xlarge). -->
@@ -1206,25 +1210,29 @@
          (large, xlarge). -->
     <style name="Theme.Material.Light.DialogWhenLarge.NoActionBar" parent="@style/Theme.Material.Light.NoActionBar" />
 
-    <!-- Material light theme for alert dialog windows, which is used by the
-         {@link android.app.AlertDialog} class.  This is basically a dialog
-         but sets the background to empty so it can do two-tone backgrounds.
-         For applications targeting Honeycomb or newer, this is the default
-         AlertDialog theme. -->
-    <style name="Theme.Material.Light.Dialog.Alert">
+    <style name="Theme.Material.Light.Dialog.BaseAlert">
         <item name="windowBackground">@color/transparent</item>
         <item name="windowTitleStyle">@style/DialogWindowTitle.Material.Light</item>
         <item name="windowMinWidthMajor">@dimen/dialog_min_width_major</item>
         <item name="windowMinWidthMinor">@dimen/dialog_min_width_minor</item>
     </style>
 
-    <!-- Material Light theme for the TimePicker dialog windows, which is used by the
-         {@link android.app.TimePickerDialog} class. -->
-    <style name="Theme.Material.Light.Dialog.TimePicker">
+    <!-- Material light theme for alert dialog windows, which is used by the
+         {@link android.app.AlertDialog} class.  This is basically a dialog
+         but sets the background to empty so it can do two-tone backgrounds.
+         For applications targeting Honeycomb or newer, this is the default
+         AlertDialog theme. -->
+    <style name="Theme.Material.Light.Dialog.Alert" parent="Theme.Material.Light.Dialog.BaseAlert"/>
+
+    <style name="Theme.Material.Light.Dialog.BaseTimePicker">
         <item name="windowBackground">@color/transparent</item>
         <item name="windowTitleStyle">@style/DialogWindowTitle.Material.Light</item>
     </style>
 
+    <!-- Material Light theme for the TimePicker dialog windows, which is used by the
+         {@link android.app.TimePickerDialog} class. -->
+    <style name="Theme.Material.Light.Dialog.TimePicker" parent="Theme.Material.Light.Dialog.BaseTimePicker"/>
+
     <!-- Theme for a presentation window on a secondary display. -->
     <style name="Theme.Material.Light.Dialog.Presentation" parent="@style/Theme.Material.Light.NoActionBar.Fullscreen" />
 
diff --git a/docs/html/auto/images/assets/02_a_notif.gif b/docs/html/auto/images/assets/02_a_notif.gif
index 6a830ae..9f3d35d 100644
--- a/docs/html/auto/images/assets/02_a_notif.gif
+++ b/docs/html/auto/images/assets/02_a_notif.gif
Binary files differ
diff --git a/docs/html/auto/images/assets/02_b_switcher.gif b/docs/html/auto/images/assets/02_b_switcher.gif
index 626f94b..c4014e3 100644
--- a/docs/html/auto/images/assets/02_b_switcher.gif
+++ b/docs/html/auto/images/assets/02_b_switcher.gif
Binary files differ
diff --git a/docs/html/auto/images/assets/03_b_voice.gif b/docs/html/auto/images/assets/03_b_voice.gif
index ddd13e4..b280a9b 100644
--- a/docs/html/auto/images/assets/03_b_voice.gif
+++ b/docs/html/auto/images/assets/03_b_voice.gif
Binary files differ
diff --git a/docs/html/auto/images/assets/do_02_music_night.png b/docs/html/auto/images/assets/do_02_music_night.png
new file mode 100644
index 0000000..7faccfb
--- /dev/null
+++ b/docs/html/auto/images/assets/do_02_music_night.png
Binary files differ
diff --git a/docs/html/auto/images/assets/do_05_template.png b/docs/html/auto/images/assets/do_05_template.png
index 4e11243..63a07d8 100644
--- a/docs/html/auto/images/assets/do_05_template.png
+++ b/docs/html/auto/images/assets/do_05_template.png
Binary files differ
diff --git a/docs/html/auto/images/assets/do_05_template_night.png b/docs/html/auto/images/assets/do_05_template_night.png
new file mode 100644
index 0000000..6acd259
--- /dev/null
+++ b/docs/html/auto/images/assets/do_05_template_night.png
Binary files differ
diff --git a/docs/html/auto/images/logos/auto/abarth.png b/docs/html/auto/images/logos/auto/abarth.png
new file mode 100644
index 0000000..fd1d228
--- /dev/null
+++ b/docs/html/auto/images/logos/auto/abarth.png
Binary files differ
diff --git a/docs/html/auto/images/logos/auto/alpharomeo.png b/docs/html/auto/images/logos/auto/alpharomeo.png
new file mode 100644
index 0000000..51c8c58
--- /dev/null
+++ b/docs/html/auto/images/logos/auto/alpharomeo.png
Binary files differ
diff --git a/docs/html/auto/images/logos/auto/audi.png b/docs/html/auto/images/logos/auto/audi.png
index 9b99efe..86cb06b 100644
--- a/docs/html/auto/images/logos/auto/audi.png
+++ b/docs/html/auto/images/logos/auto/audi.png
Binary files differ
diff --git a/docs/html/auto/images/logos/auto/chrysler.png b/docs/html/auto/images/logos/auto/chrysler.png
index f366cba..c670c19 100644
--- a/docs/html/auto/images/logos/auto/chrysler.png
+++ b/docs/html/auto/images/logos/auto/chrysler.png
Binary files differ
diff --git a/docs/html/auto/images/logos/auto/dodge.png b/docs/html/auto/images/logos/auto/dodge.png
new file mode 100644
index 0000000..4d6fcc0
--- /dev/null
+++ b/docs/html/auto/images/logos/auto/dodge.png
Binary files differ
diff --git a/docs/html/auto/images/logos/auto/fiat.png b/docs/html/auto/images/logos/auto/fiat.png
index aaa5cf3..b9783d9 100644
--- a/docs/html/auto/images/logos/auto/fiat.png
+++ b/docs/html/auto/images/logos/auto/fiat.png
Binary files differ
diff --git a/docs/html/auto/images/logos/auto/ford.png b/docs/html/auto/images/logos/auto/ford.png
new file mode 100644
index 0000000..86a2670
--- /dev/null
+++ b/docs/html/auto/images/logos/auto/ford.png
Binary files differ
diff --git a/docs/html/auto/images/logos/auto/infinity.png b/docs/html/auto/images/logos/auto/infinity.png
index ad77351..a20e0a0 100644
--- a/docs/html/auto/images/logos/auto/infinity.png
+++ b/docs/html/auto/images/logos/auto/infinity.png
Binary files differ
diff --git a/docs/html/auto/images/logos/auto/jeep.png b/docs/html/auto/images/logos/auto/jeep.png
new file mode 100644
index 0000000..024c3d1
--- /dev/null
+++ b/docs/html/auto/images/logos/auto/jeep.png
Binary files differ
diff --git a/docs/html/auto/images/logos/auto/mercedesbenz.png b/docs/html/auto/images/logos/auto/mercedesbenz.png
deleted file mode 100644
index 05fab0f..0000000
--- a/docs/html/auto/images/logos/auto/mercedesbenz.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/auto/images/logos/auto/ram.png b/docs/html/auto/images/logos/auto/ram.png
new file mode 100644
index 0000000..9702587
--- /dev/null
+++ b/docs/html/auto/images/logos/auto/ram.png
Binary files differ
diff --git a/docs/html/auto/index.jd b/docs/html/auto/index.jd
index 35789c3..116f26d 100644
--- a/docs/html/auto/index.jd
+++ b/docs/html/auto/index.jd
@@ -11,15 +11,6 @@
 #jd-content>.content-footer.wrap {
   display:none;
 }
-</style>
-
-<style>
-#footer {
-  display: none;
-}
-.content-footer {
-  display: none;
-}
 #hero-height {
   height:calc(100% - 100px);
 }
@@ -44,60 +35,29 @@
 .auto-img-frame-cols {
   z-index:2;
   position:relative;
+  width:460px;
 }
 .auto-img-shot-cols {
+  width:447px;
   position:absolute;
-  top:5px;
-  left:2px;
+  top:8px;
+  left:7px;
   z-index:1;
 }
-</style>
-
-
-    <style>
-.fullpage>#footer,
-#jd-content>.content-footer.wrap {
-  display:none;
+.sdk-link {
+  font-size:16px;
+  padding-left:5px;
+  padding-right:15px;
 }
-</style>
-
-<style>
-#footer {
-  display: none;
+.sdk-link-title {
+  font-size:18px;
+  padding-left:5px;
+  padding-right:15px;
 }
-.content-footer {
-  display: none;
-}
-#hero-height {
-  height:calc(100% - 110px);
-}
-.img-logo {
-  margin:0 auto;
-  display:block;
-  margin-bottom:-28px !important;
-}
-.img-logo-thin {
-  margin:0 auto;
-  display:block;
-  margin-bottom:-55px !important;
-}
-.col-5 {
-  width:170px;
-}
-.auto-img-container-cols {
-  position:relative;
-  margin-bottom:25px;
-  margin-top:25px;
-}
-.auto-img-frame-cols {
-  z-index:2;
-  position:relative;
-}
-.auto-img-shot-cols {
-  position:absolute;
-  top:5px;
-  left:2px;
-  z-index:1;
+.sdk-link-desc {
+  font-size:14px;
+  padding-left:5px;
+  padding-right:15px;
 }
 </style>
 
@@ -116,13 +76,13 @@
                 <div class="landing-h1 hero">Android Auto</div>
                 <div class="landing-subhead hero">Entertainment and services on your dashboard</div>
                 <div class="landing-hero-description">
-                  <p style="width:450px">Display and control your handheld app in vehicles.
-                  Build apps with easy-to-use UI templates that
-                  let users keep their eyes on the road.</p>
+                  <p style="width:450px">Display and control your Android app in vehicles.
+                   Integrate your content with easy-to-use APIs and let Android Auto take
+                   care of the rest.</p>
                 </div>
 
               <div class="landing-body">
-                <a href="/auto/overview.html" class="landing-button landing-primary"
+                <a href="{@docRoot}auto/overview.html" class="landing-button landing-primary"
                    style="margin-top:40px;">
                   Developer Overview
                 </a>
@@ -134,7 +94,7 @@
 
       <div class="landing-scroll-down-affordance">
         <a class="landing-down-arrow" href="#android-in-car">
-          <img src="/wear/images/carrot.png" alt="Scroll down to read more">
+          <img src="{@docRoot}wear/images/carrot.png" alt="Scroll down to read more">
         </a>
       </div>
     </div> <!-- end .landing-section .landing-hero -->
@@ -145,130 +105,137 @@
       <div class="landing-section landing-gray-background" id="android-in-car">
         <div class="wrap">
           <div class="landing-section-h1">
-            <div class="landing-h1">Build Experiences for the Road</div>
+            <div class="landing-h1">Extending Android to Cars</div>
           </div>
           <div class="landing-body">
-            <div class="landing-subhead">Android Auto brings apps to the car, integrating with
-            the vehicle's input controls and display.</div>
+            <div class="landing-subhead">Android Auto brings the Android experience to
+            cars with apps like Google Now and Maps.</div>
             <div class="cols">
               <div class="col-8">
                 <div class="auto-img-container-cols">
-                  <img class="auto-img-frame-cols" src="/auto/images/assets/00_frame.png" />
-                  <img class="auto-img-shot-cols" src="/auto/images/assets/01_a_maps.png" />
+                  <img class="auto-img-frame-cols" src="{@docRoot}auto/images/assets/00_frame.png" />
+                  <img class="auto-img-shot-cols" src="{@docRoot}auto/images/assets/01_b_now.png" />
                 </div>
               </div>
               <div class="col-8">
                 <div class="auto-img-container-cols">
-                  <img class="auto-img-frame-cols" src="/auto/images/assets/00_frame.png" />
-                  <img class="auto-img-shot-cols" src="/auto/images/assets/01_b_now.png" />
+                  <img class="auto-img-frame-cols" src="{@docRoot}auto/images/assets/00_frame.png" />
+                  <img class="auto-img-shot-cols" src="{@docRoot}auto/images/assets/01_a_maps.png" />
                 </div>
               </div>
             </div>
+
             <p>When users connect their Android phones to compatible vehicles, Android Auto
              shows a standard interface that lets them start enabled apps and services.
              Android Auto locks the handheld device when connected, so drivers
-            interact with your app using the vehicle's input controls and touch display.</p>
+            interact with Auto by using the vehicle's input controls, touch display, and voice.</p>
             </p>
           </div>
         </div> <!-- end .wrap -->
       </div> <!-- end .landing-section -->
 
-      <div class="landing-section" >
+
+      <div class="landing-section">
         <div class="wrap">
           <div class="landing-section-header">
-            <div class="landing-h1">Minimize Distraction</div>
-            <div class="landing-subhead">
-             Standard UI templates for several app categories let users focus on the road. 
-            </div>       
+            <div class="landing-h1">Build for One Platform</div>
+            <div class="landing-subhead">Create apps with the Android APIs you're familiar with
+            and extend them to cars with the Auto SDK.
+            </div>
           </div>
+
           <div class="landing-body">
+
             <div class="cols">
               <div class="col-8">
                 <div class="auto-img-container-cols">
-                  <img class="auto-img-frame-cols" src="/auto/images/assets/00_frame.png" />
-                  <img class="auto-img-shot-cols" src="/auto/images/assets/03_b_voice.gif" />
+                  <img class="auto-img-frame-cols" src="{@docRoot}auto/images/assets/00_frame.png" />
+                  <img class="auto-img-shot-cols" src="{@docRoot}auto/images/assets/02_b_switcher.gif" />
                 </div>
               </div>
               <div class="col-8">
                 <div class="auto-img-container-cols">
-                  <img class="auto-img-frame-cols" src="/auto/images/assets/00_frame.png" />
-                  <img class="auto-img-shot-cols" src="/auto/images/assets/03_a_musict.png" />
+                  <img class="auto-img-frame-cols" src="{@docRoot}auto/images/assets/00_frame.png" />
+                  <img class="auto-img-shot-cols" src="{@docRoot}auto/images/assets/02_a_notif.gif" />
                 </div>
               </div>
             </div>
-            <p>These templates define the user interaction model for all
-             apps and let you hook into a standard UI with touch and voice controls. The templates
-             meet international best practices for reducing driver
-             distraction while still letting you customize and brand them to properly deliver your
-             content.
-             </p>
+            <p>Write your apps without having
+            to worry about vehicle-specific hardware differences like screen resolution, software
+            interfaces, knobs, and touch controls. Your users get the same experience on any compatible
+            vehicle such as a consistent app launcher and system events such as notifications.</p>
           </div>
         </div> <!-- end .wrap -->
       </div> <!-- end .landing-section -->
 
+
       <div class="landing-section landing-gray-background">
         <div class="wrap">
           <div class="landing-section-header">
-            <div class="landing-h1">Run on One Platform</div>
-            <div class="landing-subhead">Extend your existing apps with the Auto SDK and get the
-            same experience on any compatible vehicle.
+            <div class="landing-h1">Minimize Distraction</div>
+            <div class="landing-subhead">
+             Android Auto displays different UIs for several app categories that let users focus on the road.
             </div>
           </div>
-
           <div class="landing-body">
-
             <div class="cols">
               <div class="col-8">
                 <div class="auto-img-container-cols">
-                  <img class="auto-img-frame-cols" src="/auto/images/assets/00_frame.png" />
-                  <img class="auto-img-shot-cols" src="/auto/images/assets/02_a_notif.gif" />
+                  <img class="auto-img-frame-cols" src="{@docRoot}auto/images/assets/00_frame.png" />
+                  <img class="auto-img-shot-cols" src="{@docRoot}auto/images/assets/03_b_voice.gif" />
                 </div>
               </div>
               <div class="col-8">
                 <div class="auto-img-container-cols">
-                  <img class="auto-img-frame-cols" src="/auto/images/assets/00_frame.png" />
-                  <img class="auto-img-shot-cols" src="/auto/images/assets/02_b_switcher.gif" />
+                  <img class="auto-img-frame-cols" src="{@docRoot}auto/images/assets/00_frame.png" />
+                  <img class="auto-img-shot-cols" src="{@docRoot}auto/images/assets/03_a_musict.png" />
                 </div>
               </div>
             </div>
-            <p>Write your app once, without having
-            to worry about vehicle-specific hardware differences like screen resolution, software
-            interfaces, knobs, and touch controls. Your app runs the same on any compatible
-            vehicle.</p>
+            <p>Android Auto defines the user interaction model for all
+             apps and let you hook into a standard UI with touch and voice controls. The interface
+             is designed to reduce driver distraction while still letting you customize and brand them to properly deliver your content.
+             </p>
           </div>
         </div> <!-- end .wrap -->
       </div> <!-- end .landing-section -->
 
-
-
       <div class="landing-section" style="background-color:#f5f5f5">
         <div class="wrap">
           <div class="landing-section-header">
             <div class="landing-pre-h1">Coming soon</div>
             <div class="landing-h1">Android Auto SDK</div>
-            <div style="text-align:center;margin-top:20px;font-size:14pt;margin-bottom:-5px">
-                <a href="https://docs.google.com/a/google.com/forms/d/1ANgYOoYLkfyZ2JRPSU34Nep5yNaU-Ha2syXJ9b4xLrA/viewform">Sign up for updates</a>
-            </div>
           </div>
 
           <div class="landing-body">
             <p>In the coming months, we’ll be releasing the Android Auto SDK, which includes APIs
               and tools to make your existing apps compatible with Android Auto. The first version
-              of the SDK will provide templates and APIs for music, podcast, live radio, and audio
+              of the SDK will provide APIs for music, podcast, live radio, and audio
               news apps, as well as limited voice actions.</p>
-            <p style="margin-bottom:40px">
-              Future versions of the Android Auto SDK will include support for a selection of
-              Android notifications, additional voice actions, and templates and APIs for
-              messaging, communication, local search, and more.</p>
 
-              <a target="_blank" href="http://g.co/androidautodev">
-                <img class="landing-social-image" src="//www.google.com/images/icons/product/gplus-128.png" alt="+Android Auto Developers">
-              </a>
-              <p>
-                Join the Android Auto developer community on Google+ to stay involved, get the
-                latest updates, and exchange experiences with other developers.
-                <a target="_blank" href="http://g.co/androidautodev">+Android Auto Developers</a>
-              </p>
+            <div class="cols" style="margin-top:40px">
+              <div class="col-3-wide">
+                <p class="sdk-link-title">Updates</p>
+                <p class="sdk-link-desc">
+                  Register to receive more information and be notified when the SDK is available.
+                </p>
+                <a class="sdk-link" href="https://docs.google.com/a/google.com/forms/d/1ANgYOoYLkfyZ2JRPSU34Nep5yNaU-Ha2syXJ9b4xLrA/viewform">Sign up for updates</a>
+              </div>
+              <div class="col-3-wide">
+                <p class="sdk-link-title">Google+ Community</p>
+                <p class="sdk-link-desc">
+                  Stay involved, get updates, and exchange experiences with other developers.
+                </p>
+                <a class="sdk-link" href="http://g.co/androidautodev">Discuss on Google+</a>
+              </div>
+              <div class="col-3-wide">
+                <p class="sdk-link-title">Developer Overview</p>
+                <p class="sdk-link-desc">
+                  Learn more about developing apps for Android Auto when the SDK is available.
+                </p>
+                <a class="sdk-link" href="{@docRoot}auto/overview.html">Learn about the platform</a>
+              </div>
+            </div>
           </div>
 
         </div> <!-- end .wrap -->
@@ -287,67 +254,64 @@
           <div class="cols">
 
             <div class="col-4">
-              <img src="/auto/images/logos/apps/joyride.png"
+              <img src="{@docRoot}auto/images/logos/apps/joyride.png"
                    width="160" height="160" class="img-logo" />
             </div>
             <div class="col-4">
-              <img src="/auto/images/logos/apps/mlb.png"
+              <img src="{@docRoot}auto/images/logos/apps/mlb.png"
                    width="160" height="160" class="img-logo" />
             </div>
             <div class="col-4">
-              <img src="/auto/images/logos/apps/pandora.png"
+              <img src="{@docRoot}auto/images/logos/apps/pandora.png"
                    width="160" height="160" class="img-logo" />
             </div>
             <div class="col-4">
-              <img src="/auto/images/logos/apps/pocketcasts.png"
+              <img src="{@docRoot}auto/images/logos/apps/pocketcasts.png"
                    width="160" height="160" class="img-logo" />
             </div>
           </div>
           <div class="cols">
             <div class="col-4">
-              <img src="/auto/images/logos/apps/songza.png"
+              <img src="{@docRoot}auto/images/logos/apps/songza.png"
                    width="160" height="160" class="img-logo" />
             </div>
             <div class="col-4">
-              <img src="/auto/images/logos/apps/stitcher.png"
+              <img src="{@docRoot}auto/images/logos/apps/stitcher.png"
                    width="160" height="160" class="img-logo" />
             </div>
             <div class="col-4">
-              <img src="/auto/images/logos/apps/tunein.png"
+              <img src="{@docRoot}auto/images/logos/apps/tunein.png"
                    width="160" height="160" class="img-logo" />
             </div>
             <div class="col-4">
-              <img src="/auto/images/logos/apps/umano.png"
+              <img src="{@docRoot}auto/images/logos/apps/umano.png"
                    width="160" height="160" class="img-logo" />
             </div>
           </div>
           <div class="cols" style="margin-top:40px">
-             <div class="col-4">
-                <img src="/auto/images/logos/apps/iheartradio.png"
+              <div class="col-4">
+                <img src="{@docRoot}auto/images/logos/apps/iheartradio.png"
                      width="160" height="160" class="img-logo" />
               </div>
               <div class="col-12">
                 <p><em>
                 "The Android Auto APIs provide an easy way to integrate the most important features and functionality of iHeartRadio’s robust music service into a safety-minded automotive infotainment solution. The process was seamless, utilizing a flexible construct that allowed us to quickly adapt our existing product without losing any of the core experience our listeners know and love."</em></p>
-
-                <b>Ryan Goff<br>
-                Director of Automotive Integrations for Clear Channel Media and Entertainment</b>
               </div>
           </div>
           <div class="cols" style="margin-top:60px">
 
               <div class="col-4">
-                <img src="/auto/images/logos/apps/spotify.png"
+                <img src="{@docRoot}auto/images/logos/apps/spotify.png"
                      width="160" height="160" class="img-logo" />
               </div>
               <div class="col-12"><p style="margin-top:20px"><em>
               "Android Auto offers Spotify the exciting opportunity to easily enable safe access to millions of songs while driving. We were able to quickly develop for the platform using the new Android voice and media API extensions. As a result, Android users will soon be able to continue the Spotify experience in their cars, including being able to play any song, artist, album or playlist by voice.</em></p>
               </div>
+              </div>
           </div>
-        </div>
+        </div> <!-- end .wrap -->
+      </div> <!-- end .landing-section -->
 
-      </div> <!-- end .wrap -->
-    </div> <!-- end .landing-section -->
 
 
 
@@ -363,214 +327,141 @@
           </div>
           <div class="cols">
             <div class="col-5">
-              <img src="/auto/images/logos/auto/acura.png"
+              <img src="{@docRoot}auto/images/logos/auto/abarth.png"
                    width="120" height="120" class="img-logo" />
             </div>
             <div class="col-5">
-              <img src="/auto/images/logos/auto/audi.png"
+              <img src="{@docRoot}auto/images/logos/auto/alpharomeo.png"
                    width="120" height="120" class="img-logo" />
             </div>
             <div class="col-5">
-              <img src="/auto/images/logos/auto/bentley.png"
+              <img src="{@docRoot}auto/images/logos/auto/acura.png"
                    width="120" height="120" class="img-logo" />
             </div>
             <div class="col-5">
-              <img src="/auto/images/logos/auto/chevrolet.png"
+              <img src="{@docRoot}auto/images/logos/auto/audi.png"
                    width="120" height="120" class="img-logo" />
             </div>
             <div class="col-5">
-              <img src="/auto/images/logos/auto/chrysler.png"
+              <img src="{@docRoot}auto/images/logos/auto/bentley.png"
                    width="120" height="120" class="img-logo" />
             </div>
           </div>
           <div class="cols">
             <div class="col-5">
-              <img src="/auto/images/logos/auto/datsun.png"
+              <img src="{@docRoot}auto/images/logos/auto/chevrolet.png"
                    width="120" height="120" class="img-logo" />
             </div>
             <div class="col-5">
-              <img src="/auto/images/logos/auto/fiat.png"
+              <img src="{@docRoot}auto/images/logos/auto/chrysler.png"
                    width="120" height="120" class="img-logo" />
             </div>
             <div class="col-5">
-              <img src="/auto/images/logos/auto/honda.png"
+              <img src="{@docRoot}auto/images/logos/auto/dodge.png"
                    width="120" height="120" class="img-logo" />
             </div>
             <div class="col-5">
-              <img src="/auto/images/logos/auto/hyundai.png"
+              <img src="{@docRoot}auto/images/logos/auto/fiat.png"
                    width="120" height="120" class="img-logo" />
             </div>
             <div class="col-5">
-              <img src="/auto/images/logos/auto/infinity.png"
+              <img src="{@docRoot}auto/images/logos/auto/ford.png"
                    width="120" height="120" class="img-logo" />
             </div>
           </div>
           <div class="cols">
             <div class="col-5">
-              <img src="/auto/images/logos/auto/kia.png"
+              <img src="{@docRoot}auto/images/logos/auto/honda.png"
                    width="120" height="120" class="img-logo" />
             </div>
             <div class="col-5">
-              <img src="/auto/images/logos/auto/maserati.png"
+              <img src="{@docRoot}auto/images/logos/auto/hyundai.png"
                    width="120" height="120" class="img-logo" />
             </div>
             <div class="col-5">
-              <img src="/auto/images/logos/auto/mazda.png"
+              <img src="{@docRoot}auto/images/logos/auto/infinity.png"
                    width="120" height="120" class="img-logo" />
             </div>
             <div class="col-5">
-              <img src="/auto/images/logos/auto/mercedesbenz.png"
+              <img src="{@docRoot}auto/images/logos/auto/jeep.png"
                    width="120" height="120" class="img-logo" />
             </div>
             <div class="col-5">
-              <img src="/auto/images/logos/auto/mitsubishi.png"
+              <img src="{@docRoot}auto/images/logos/auto/kia.png"
                    width="120" height="120" class="img-logo" />
             </div>
           </div>
           <div class="cols">
             <div class="col-5">
-              <img src="/auto/images/logos/auto/nissan.png"
+              <img src="{@docRoot}auto/images/logos/auto/maserati.png"
                    width="120" height="120" class="img-logo" />
             </div>
             <div class="col-5">
-              <img src="/auto/images/logos/auto/opel.png"
+              <img src="{@docRoot}auto/images/logos/auto/mazda.png"
                    width="120" height="120" class="img-logo" />
             </div>
             <div class="col-5">
-              <img src="/auto/images/logos/auto/renault.png"
+              <img src="{@docRoot}auto/images/logos/auto/mitsubishi.png"
                    width="120" height="120" class="img-logo" />
             </div>
             <div class="col-5">
-              <img src="/auto/images/logos/auto/seat.png"
+              <img src="{@docRoot}auto/images/logos/auto/nissan.png"
                    width="120" height="120" class="img-logo" />
             </div>
             <div class="col-5">
-              <img src="/auto/images/logos/auto/skoda.png"
+              <img src="{@docRoot}auto/images/logos/auto/opel.png"
                    width="120" height="120" class="img-logo" />
             </div>
           </div>
           <div class="cols">
             <div class="col-5">
-              <img src="/auto/images/logos/auto/subaru.png"
+              <img src="{@docRoot}auto/images/logos/auto/ram.png"
                    width="120" height="120" class="img-logo" />
             </div>
             <div class="col-5">
-              <img src="/auto/images/logos/auto/suzuki.png"
+              <img src="{@docRoot}auto/images/logos/auto/renault.png"
                    width="120" height="120" class="img-logo" />
             </div>
             <div class="col-5">
-              <img src="/auto/images/logos/auto/volkswagen.png"
+              <img src="{@docRoot}auto/images/logos/auto/seat.png"
                    width="120" height="120" class="img-logo" />
             </div>
             <div class="col-5">
-              <img src="/auto/images/logos/auto/volvo.png"
+              <img src="{@docRoot}auto/images/logos/auto/skoda.png"
+                   width="120" height="120" class="img-logo" />
+            </div>
+            <div class="col-5">
+              <img src="{@docRoot}auto/images/logos/auto/subaru.png"
+                   width="120" height="120" class="img-logo" />
+            </div>
+          </div>
+          <div class="cols">
+            <div class="col-5">
+              <img src="{@docRoot}auto/images/logos/auto/suzuki.png"
+                   width="120" height="120" class="img-logo" />
+            </div>
+            <div class="col-5">
+              <img src="{@docRoot}auto/images/logos/auto/volkswagen.png"
+                   width="120" height="120" class="img-logo" />
+            </div>
+            <div class="col-5">
+              <img src="{@docRoot}auto/images/logos/auto/volvo.png"
                    width="120" height="120" class="img-logo" />
             </div>
             <div class="col-5">
               <!--<img src="/auto/images/logos/auto/skoda.png"
                    width="120" height="120" class="img-logo" />-->
             </div>
-          </div>
-
-          <div class="landing-body landing-align-center">
-              <div class="landing-subhead" style="margin-top:80px">
-                Android Auto is also coming soon to aftermarket systems from these manufacturers:
-              </div>
-          </div>
-          <div class="cols">
             <div class="col-5">
-              <img src="/auto/images/logos/hard/alpine.png"
-                   width="120" height="120" class="img-logo-thin" />
-            </div>
-            <div class="col-5">
-              <img src="/auto/images/logos/hard/clarion.png"
-                   width="120" height="120" class="img-logo-thin" />
-            </div>
-            <div class="col-5">
-              <img src="/auto/images/logos/hard/cloudcar.png"
-                   width="120" height="120" class="img-logo-thin" />
-            </div>
-            <div class="col-5">
-              <img src="/auto/images/logos/hard/delphi.png"
-                   width="120" height="120" class="img-logo-thin" />
-            </div>
-            <div class="col-5">
-              <img src="/auto/images/logos/hard/freescale.png"
-                   width="120" height="120" class="img-logo-thin" />
+              <!--<img src="/auto/images/logos/auto/skoda.png"
+                   width="120" height="120" class="img-logo" />-->
             </div>
           </div>
-          <div class="cols">
-            <div class="col-5">
-              <img src="/auto/images/logos/hard/fujitsuten.png"
-                   width="120" height="120" class="img-logo-thin" />
-            </div>
-            <div class="col-5">
-              <img src="/auto/images/logos/hard/harman.png"
-                   width="120" height="120" class="img-logo-thin" />
-            </div>
-            <div class="col-5">
-              <img src="/auto/images/logos/hard/jvc.png"
-                   width="120" height="120" class="img-logo-thin" />
-            </div>
-            <div class="col-5">
-              <img src="/auto/images/logos/hard/kenwood.png"
-                   width="120" height="120" class="img-logo-thin" />
-            </div>
-            <div class="col-5">
-              <img src="/auto/images/logos/hard/lg.png"
-                   width="120" height="120" class="img-logo-thin" />
-            </div>
-          </div>
-          <div class="cols">
-            <div class="col-5">
-              <img src="/auto/images/logos/hard/panasonic.png"
-                   width="120" height="120" class="img-logo-thin" />
-            </div>
-            <div class="col-5">
-              <img src="/auto/images/logos/hard/parrot.png"
-                   width="120" height="120" class="img-logo-thin" />
-            </div>
-            <div class="col-5">
-              <img src="/auto/images/logos/hard/pioneer.png"
-                   width="120" height="120" class="img-logo-thin" />
-            </div>
-            <div class="col-5">
-              <img src="/auto/images/logos/hard/renesas.png"
-                   width="120" height="120" class="img-logo-thin" />
-            </div>
-            <div class="col-5">
-              <img src="/auto/images/logos/hard/symphonyteleca.png"
-                   width="120" height="120" class="img-logo-thin" />
-            </div>
-          </div>
-          <div class="cols">
-            <div class="col-5">
-              <img src="/auto/images/logos/hard/texasinstruments.png"
-                   width="120" height="120" class="img-logo-thin" />
-            </div>
-            <div class="col-5">
-              <!--<img src="/auto/images/logos/hard/.png"
-                   width="120" height="120" class="img-logo-thin" />-->
-            </div>
-            <div class="col-5">
-              <!--<img src="/auto/images/logos/hard/.png"
-                   width="120" height="120" class="img-logo-thin" />-->
-            </div>
-            <div class="col-5">
-              <!--<img src="/auto/images/logos/hard/.png"
-                   width="120" height="120" class="img-logo-thin" />-->
-            </div>
-            <div class="col-5">
-              <!--<img src="/auto/images/logos/hard/.png"
-                   width="120" height="120" class="img-logo-thin" />-->
-            </div>
-          </div>
-        </div> <!-- end .wrap -->
-      </div> <!-- end .landing-section -->
+        </div>
+      </div>
     </div> <!-- end .landing-rest-of-page -->
-
-
-    <div class="content-footer wrap" itemscope="" itemtype="http://schema.org/SiteNavigationElement">
+    <div class="content-footer wrap" itemscope="" itemtype="http://schema.org/SiteNavigationElement"
+    style="border-top: none;">
       <div class="layout-content-col col-16" style="padding-top:4px">
         <style>#___plusone_0 {float:right !important;}</style>
         <div class="g-plusone" data-size="medium"></div>
@@ -581,13 +472,11 @@
         Except as noted, this content is
         licensed under <a href="http://creativecommons.org/licenses/by/2.5/">
         Creative Commons Attribution 2.5</a>. For details and
-        restrictions, see the <a href="/license.html">Content
+        restrictions, see the <a href="{@docRoot}license.html">Content
         License</a>.
       </div>
     </div>
-
-
-  </div> <!-- end landing-body-content -->
+  </div> <!-- end .landing-hero-container -->
 
   <script>
   $("a.landing-down-arrow").on("click", function(e) {
@@ -597,3 +486,5 @@
     e.preventDefault();
   });
   </script>
+
+</div> <!-- end landing-body-content -->
diff --git a/docs/html/auto/overview.jd b/docs/html/auto/overview.jd
index 728dff7..cf63b98 100644
--- a/docs/html/auto/overview.jd
+++ b/docs/html/auto/overview.jd
@@ -31,18 +31,16 @@
   margin-top:10px;
 }
 .auto-img-frame-cols {
+  width:380px;
   z-index:2;
   position:relative;
 }
 .auto-img-shot-cols {
+  width:369px;
   position:absolute;
-  top:0px;
-  left:0px;
+  top:7px;
+  left:6px;
   z-index:1;
-  border:1px solid #;
-  -webkit-border-radius: 7px;
-  -moz-border-radius: 7px;
-  border-radius: 7px;
 }
 .auto-col-2 {
   width:380px;
@@ -71,13 +69,13 @@
     </ol>
   </li>
   <li><a href="#architecture">Architecture</a></li>
-  <li><a href="#uitemplates">UI Templates</a>
+  <li><a href="#ui">User Interface</a>
     <ol>
       <li><a href="#launchapp">Launch App</a></li>
       <li><a href="#useractions">User Actions</a></li>
       <li><a href="#drawertransitions">Drawer Transitions</a></li>
       <li><a href="#daynighttransitions">Day and Night Transitions</a></li>
-      <li><a href="#customizetemplates">Customizing Templates</a></li>
+      <li><a href="#customizeui">Customizing the UI</a></li>
     </ol>
   </li>
   <li><a href="#devprocess">Development Process</a></li>
@@ -89,27 +87,33 @@
 
 <h1>Android Auto Developer Overview</h1>
 
-<p>Android Auto extends the Android platform to car entertainment systems. When users connect
-their Android handheld device to a compatible vehicle, Android Auto lets users project apps on
-the vehicle’s touchscreen and interact with them using the vehicle’s controls.</p>
+<p>Android Auto extends the Android platform into the car. When users connect
+their Android handheld device to a compatible vehicle, Android Auto provides a car-optimized
+Android experience on the vehicle's screen. Users interact with compatible apps and services
+through voice actions and the vehicle's input controls.</p>
+
+<p>The Android Auto SDK lets you easily extend your existing apps to work in the car, without
+having to worry about vehicle-specific hardware differences. You can use many Android APIs and
+services you are already familiar with. Android Auto provides an easy to use UI model and
+supports notifications and voice actions:</p>
 
 <dl>
-<dt style="margin-bottom:10px"><strong>UI Templates</strong></dt>
+<dt style="margin-bottom:10px"><strong>Media UI</strong></dt>
 <dd style="margin-bottom:20px">
-Android Auto defines interaction models and UI templates for several app categories. The
+Android Auto defines interaction models and car-specific UI patterns for apps. The
 first version of Android Auto supports media apps, such as music, podcast, live radio, and
-audio news apps. Future versions will support messaging, communication, local search apps,
-and more.
+audio news apps.
 </dd>
 <dt style="margin-bottom:10px"><strong>Notifications</strong></dt>
 <dd style="margin-bottom:20px">
 The platform will integrate with existing Android APIs for notifications. Users will get
-some notifications from Android apps on the vehicle’s screen.</dd>
+car appropiate notifications from Android apps on the vehicle's screen.</dd>
 
 <dt style="margin-bottom:10px"><strong>Voice Actions</strong></dt>
 <dd style="margin-bottom:20px">
-Android Auto supports voice search and voice actions for media apps. Future versions
-will support additional voice actions.</dd>
+Android Auto supports a set of voice actions to interact with compatible apps and services.
+Apps can respond to the voice actions they're interested in, such as playing a particular song
+or taking a note.</dd>
 
 <dt style="margin-bottom:10px"><strong>Easy Development Workflow</strong></dt>
 <dd style="margin-bottom:20px">
@@ -124,39 +128,52 @@
 
 <h2 id="design">Design</h2>
 
-<p>Digital experiences for cars should complement and augment driving, not demand the driver's
-attention. Designing these experiences for cars is fundamentally different than in the case of
-phones and tablets. It requires rethinking how these experiences unfold.</p>
+<p>Android Auto extends users' digital ecosystem into their cars, allowing drivers to stay
+connected to their virtual worlds while staying focused on the road ahead.</p>
 
-<h3 id="designprinciples">Design Principles</h3>
+<p>Because driving is the primary activity in the car, any digital experiences should be designed
+to complement and augment that activity. They should never demand the user's attention.</p>
 
-<p><strong>Glanceable</strong>. We designed Android Auto to reduce UI complexity, optimize user
-interactions, and lower cognitive load. Effective apps show just enough information
-and only provide features that do not require excessive menu interaction and navigation.</p>
+<p>Designing for cars is fundamentally different than designing for phones or tablets, and
+requires rethinking how experiences unfold. Because attention is limited and not all tasks are
+possible in the car, effective apps leverage the entire set of devices that drivers have,
+leveraging the app experience on those devices, outside of the car, to set the stage for simple
+experiences while driving.</p>
+
+<p>Android Auto experiences are:</p>
+
+<p><strong>Glanceable and simple</strong>. Driving requires users' full attention. In-car software
+should not. Android Auto was designed to simplify not only the UI, but to optimize interactions
+and require less thinking, induce lower cognitive load, and ultimately, be safer. Effective apps
+provide just enough information in the minimum amount of time the user needs to glance at it and
+return their attention back to the road. Apps should also reduce the number of features to only
+those that are safe and drive-appropriate.</p>
 
 <p><strong>Predictive, yet predictable</strong>. Android Auto leverages rich, contextual awareness
-to keep the driver informed about important situations. Timely help is combined with predictable
-functions. Effective apps use patterns for common tasks and show timely information only when
-relevant.</p>
+to keep the driver informed about important situations during the drive. Rich, timely help is
+combined with predictable functions. Effective apps make use of the patterns for common tasks and
+show timely information only when relevant.</p>
 
-<p><strong>Connected</strong>. Android Auto works with apps that drivers already use in other
-devices. Android Auto promotes a continuous app experience from phones and tablets to cars,
-providing access to user's existing settings, subscriptions, and digital libraries. Experiences
-that bring personal content and context from other devices are part of Android Auto.</p>
+<p><strong>Connected</strong>. By leveraging the user's personal ecosystem of apps and services,
+Android Auto promotes a continuous experience from phone to car to other devices. The user's
+music, destinations, and virtual ecosystem are always available to augment the drive. Experiences
+that leverage personal context and other devices are naturally part of Android Auto.</p>
 
-<p><strong>Integrated</strong>. Android Auto blends your apps with the vehicle's entertainment
-system, creating a truly integrated experience in every car. By using the vehicle's screen and
-controls, apps feel tailored to each car.</p>
+<p><strong>Naturally integrated</strong>. Android Auto blends the user's apps with the car,
+creating a truly integrated experience that leverages what is unique about each car. By using
+the screens, controls, and capabilities of the vehicle, Android Auto feels like an extension of
+the car.</p>
+
 
 
 
 <h2 id="architecture">Architecture</h2>
 
-<p>The Android Auto app projects your app's customized UI on the vehicle's screen. To communicate
+<p>The Android Auto app shows your app's customized UI on the vehicle's screen. To communicate
 with the Android Auto app, your media app implements a set of media interfaces.</p>
 
 <div style="width:750px;margin:0 auto">
-<img src="{@docRoot}auto/images/figure01.png" alt="" id="figure1" />
+<img src="{@docRoot}auto/images/figure01.png" alt="" />
 <p class="img-caption">
   <strong>Figure 1</strong> - Architecture of Android Auto.
 </p>
@@ -167,7 +184,7 @@
 <p><strong>Media App</strong> - Runs a media service that exposes content through browsing and
 playback APIs. The service provides content to the Android Auto app. This is your Android app.</p>
 
-<p><strong>Android Auto App</strong> - Creates a templated UI and handles user interactions.
+<p><strong>Android Auto App</strong> - Creates the UI and handles user interactions.
 This app uses a media client to request content from the media service running in the media
 app. The client requests data from the media service and monitors service states.</p>
 
@@ -186,21 +203,20 @@
 </ul>
 
 
-<h2 id="uitemplates">UI Templates</h2>
+<h2 id="ui">User Interface</h2>
 
-<p>The Android Auto app uses a templated UI to display content and user interaction
-opportunities. Android Auto provides you with a set of standard UI templates that follow
-international guidelines for minimizing driving distraction. You do not have to test your
-app's UI for for driver distraction, which is a lengthy and expensive process involving
-multiple legislations across the globe and different standards for each vehicle OEM.</p>
+<p>The Android Auto app uses a car-specific UI model to display content and user interaction
+opportunities. Android Auto provides you with a standard UI designed to minimize driver
+distraction. You do not have to test a custom UI for for driver distraction, which is a
+lengthy and expensive process involving multiple legislations across the globe and different
+standards for each vehicle OEM.</p>
 
-<p>The UI templates define interfaces for browsing, searching, and listening to content from
-media apps. Although you cannot change the standard template format or layout, you can customize
-the template colors, action icons, background images, and more.</p>
+<p>The UI defines interfaces for browsing, searching, and listening to content from
+media apps. You can customize the UI colors, action icons, background images, and more.</p>
 
-<h3 id="launchapp">Launch App Template</h3>
+<h3 id="launchapp">Launcher</h3>
 
-<p>The Launcher template shows all the compatible media apps installed on the user’s
+<p>The launcher shows all the compatible media apps installed on the user’s
 Android device and lets users select one of them from an scrollable list:</p>
 
 <div class="auto-img-container-single">
@@ -209,17 +225,15 @@
     <img class="auto-img-shot-cols" src="/auto/images/assets/do_01_switcher.png" />
   </div>
   <p class="img-caption" style="margin-top:0px">
-    <strong>Figure 2.</strong> The Launcher template.
+    <strong>Figure 2.</strong> The launcher.
   </p>
 </div>
 
-<h3>Primary App Template</h3>
+<h3>Primary App UI</h3>
 
-<p>After the user selects a media app, the display shows the primary app template. Figure
-3 shows the elements of this template that you can customize:</p>
-
-<p>You can customize the primary app template to show your own icons, app name, and
-background images. Figure 4 shows an example of a customized template:</p>
+<p>After the user selects a media app, the display shows the primary app UI.
+You can customize this UI to show your own icons, app name, and
+background images. Figure 3 shows an example of a customized UI:</p>
 
 <div class="cols">
 <div class="auto-col-2">
@@ -236,16 +250,16 @@
 </div>
 </div>
 <p class="img-caption">
-  <strong>Figure 4.</strong> A customized template.
+  <strong>Figure 3.</strong> A customized UI.
 </p>
 
 
 
 <h3 id="useractions">User Actions</h3>
 
-<p>The primary app template supports four main actions on the action bar, four auxiliary actions
+<p>The primary app UI supports four main actions on the action bar, four auxiliary actions
 on the overflow bar, and the <em>Return</em> action. You can use standard controls and customize
-the actions and icons, as shown in Figure 5.</p>
+the actions and icons, as shown in Figure 4.</p>
 
 <div class="auto-img-container-single">
   <div class="auto-img-container">
@@ -253,18 +267,13 @@
     <img class="auto-img-shot-cols" src="/auto/images/assets/do_03_more.png" />
   </div>
   <p class="img-caption" style="margin-top:0px">
-    <strong>Figure 5.</strong> Custom extra actions.
+    <strong>Figure 4.</strong> Custom extra actions.
   </p>
 </div>
 
 <h3 id="drawertransitions">Drawer Transitions</h3>
 
-<p>For browse actions, the display shows the drawer transition and template:</p>
-
-<p>After the transition from the primary app template to the drawer template, the drawer
-appears on the center. The customized drawer template shows the media containers and
-media files provided by the media service in your app. You can also customize drawers
-with icons for list items.</p>
+<p>For browse actions, the display shows the drawer transition as shown in Figure 5.</p>
 
 <div class="cols">
 <div class="auto-col-2">
@@ -281,18 +290,42 @@
 </div>
 </div>
 <p class="img-caption">
-  <strong>Figure 4.</strong> Generic and customized drawer templates.
+  <strong>Figure 5.</strong> Generic and customized drawers.
 </p>
 
+<p>After the transition from the primary app UI to the drawer UI, the drawer
+appears on the center. The customized drawer UI shows the media containers and
+media files provided by the media service in your app. You can also customize drawers
+with icons for list items.</p>
+
+
 <h3 id="daynighttransitions">Day and Night Transitions</h3>
 
-<p>All the templates support different color schemes for day and night, as shown in
-Figure 8. The platform provides the state (day or night) and makes adjustments automatically.</p>
+<p>All the UIs support different color schemes for day and night.
+The platform provides the state (day or night) and makes adjustments automatically.</p>
 
-<h3 id="customizetemplates">Customizing Templates</h3>
+<div class="cols">
+<div class="auto-col-2">
+  <div class="auto-img-container-cols">
+    <img class="auto-img-frame-cols" src="{@docRoot}auto/images/assets/00_frame.png" />
+    <img class="auto-img-shot-cols" src="{@docRoot}auto/images/assets/do_02_music.png" />
+  </div>
+</div>
+<div class="auto-col-2">
+  <div class="auto-img-container-cols">
+    <img class="auto-img-frame-cols" src="{@docRoot}auto/images/assets/00_frame.png" />
+    <img class="auto-img-shot-cols" src="{@docRoot}auto/images/assets/do_02_music_night.png" />
+  </div>
+</div>
+</div>
+<p class="img-caption">
+  <strong>Figure 6.</strong> Day and night modes.
+</p>
 
-<p>To customize the templates, provide the following app-specific resources and actions
-to the Android Auto media client.</p>
+<h3 id="customizeui">Customizing UIs</h3>
+
+<p>To customize the UI, you provide the following app-specific resources and actions
+to the Android Auto media client:</p>
 
 <ul>
 <li><strong>Resources</strong> - App logo, app name, theme colors, and background images.</li>
@@ -300,7 +333,7 @@
 <em>Favorite</em>, and <em>Bookmark</em>. These actions are app-specific.</li>
 </ul>
 
-<p>If provided, the media client automatically uses them in the templated UI.</p>
+<p>If provided, the media client automatically uses them in the UI.</p>
 
 
 <h2 id="devprocess">Development Process</h2>
@@ -312,10 +345,10 @@
 <p>To create a media app for Android Auto, you include an Android service in your app
 that implements the media service interfaces provided by the Android Auto SDK. These
 interfaces define functionality for browsing and finding content, playing media,
-customizing the UI template, and performing app-specific actions.</p>
+customizing the UI, and performing app-specific actions.</p>
 
 <p>The media service interfaces present the content library as a navigable tree and enable
-clients to play media, get album art, obtain theme resources for the UI template, and
+clients to play media, get album art, obtain theme resources for the UI, and
 invoke app-specific actions.</p>
 
 <p>You don’t have to create a new app for Android Auto: you can extend your existing
diff --git a/docs/html/design/auto/index.jd b/docs/html/design/auto/index.jd
new file mode 100644
index 0000000..aac79ab
--- /dev/null
+++ b/docs/html/design/auto/index.jd
@@ -0,0 +1,35 @@
+page.title=Auto
+@jd:body
+
+<style>
+.auto-img-container-cols {
+  position:relative;
+  margin-bottom:25px;
+  margin-top:25px;
+}
+.auto-img-frame-cols {
+  z-index:2;
+  position:relative;
+}
+.auto-img-shot-cols {
+  position:absolute;
+  top:5px;
+  left:2px;
+  z-index:1;
+}
+</style>
+
+<div class="auto-img-container-cols" style="float:right; margin:0 0 40px 40px;width:460px">
+  <img class="auto-img-frame-cols" src="/auto/images/assets/00_frame.png">
+  <img class="auto-img-shot-cols" src="/auto/images/assets/03_a_musict.png">
+</div>
+
+<p>Android Auto is <strong>coming soon</strong> and brings apps to the car,
+integrating with the vehicle's input controls and display.</p>
+
+<p>The future design guidelines provide templates that define the user interaction model for all apps and let you hook into a standard UI with touch and voice controls. The templates meet international best practices for reducing driver distraction while still letting you customize and brand them to properly deliver your content.</p>
+
+<p><a href="{@docRoot}auto/index.html">Learn more about Android Auto</a>.</p>
+
+
+
diff --git a/docs/html/design/design_toc.cs b/docs/html/design/design_toc.cs
index 2bd0bf9..885f336 100644
--- a/docs/html/design/design_toc.cs
+++ b/docs/html/design/design_toc.cs
@@ -5,7 +5,26 @@
     <ul>
       <li><a href="<?cs var:toroot ?>design/get-started/creative-vision.html">Creative Vision</a></li>
       <li><a href="<?cs var:toroot ?>design/get-started/principles.html">Design Principles</a></li>
-      <li><a href="<?cs var:toroot ?>design/get-started/ui-overview.html">UI Overview</a></li>
+    </ul>
+  </li>
+
+  <li class="nav-section">
+    <div class="nav-section-header"><a href="<?cs var:toroot ?>design/devices.html">Devices</a></div>
+    <ul>
+      <li><a href="<?cs var:toroot ?>design/handhelds/index.html">Phones &amp; Tablets</a></li>
+      <li class="nav-section">
+        <div class="nav-section-header">
+          <a href="<?cs var:toroot ?>design/wear/index.html">Wear</a></div>
+        <ul>
+          <li><a href="<?cs var:toroot ?>design/wear/creative-vision.html">Creative Vision</a></li>
+          <li><a href="<?cs var:toroot ?>design/wear/principles.html">Design Principles</a></li>
+          <li><a href="<?cs var:toroot ?>design/wear/structure.html">App Structure</a></li>
+          <li><a href="<?cs var:toroot ?>design/wear/patterns.html">UI Patterns</a></li>
+          <li><a href="<?cs var:toroot ?>design/wear/style.html">Style</a></li>
+        </ul>
+      </li>
+      <li><a href="<?cs var:toroot ?>design/tv/index.html">TV</a></li>
+      <li><a href="<?cs var:toroot ?>design/auto/index.html">Auto</a></li>
     </ul>
   </li>
 
@@ -67,25 +86,6 @@
   </li>
 
   <li class="nav-section">
-    <div class="nav-section-header"><a href="<?cs var:toroot ?>design/devices.html">Devices</a></div>
-    <ul>
-      <!-- wear design goes here -->
-      <li class="nav-section">
-        <div class="nav-section-header">
-          <a href="<?cs var:toroot ?>design/tv/index.html">TV</a></div>
-        <ul>
-          <li><a href="<?cs var:toroot ?>design/tv/principles.html">Design Principles</a></li>
-          <li><a href="<?cs var:toroot ?>design/tv/ui-overview.html">UI Overview</a></li>
-          <li><a href="<?cs var:toroot ?>design/tv/style.html">Style</a></li>
-          <li><a href="<?cs var:toroot ?>design/tv/patterns.html">Patterns</a></li>
-        </ul>
-      </li>
-
-    </ul>
-  </li>
-
-
-  <li class="nav-section">
     <div class="nav-section-header empty"><a href="<?cs var:toroot ?>design/downloads/index.html">Downloads</a></div>
   </li>
 
diff --git a/docs/html/design/devices.jd b/docs/html/design/devices.jd
new file mode 100644
index 0000000..0015d01
--- /dev/null
+++ b/docs/html/design/devices.jd
@@ -0,0 +1,37 @@
+page.title=Devices
+page.viewport_width=970
+section.landing=true
+header.hide=1
+footer.hide=1
+@jd:body
+
+<style>
+#landing-graphic-container {
+  position: relative;
+}
+
+#text-overlay {
+  position: absolute;
+  left: 0;
+  top: 420px;
+  width: 360px;
+
+}
+#hero-image {
+}
+</style>
+
+<div id="landing-graphic-container">
+  <div id="text-overlay">
+    <p itemprop="description">The device-centric UI principles, overviews, and detailed guidelines
+      described here build on the core <a href="{@docRoot}design/get-started/principles.html">Android Design Principles</a>
+      to provide more specific design guidance for different form factors.
+    </p>
+    <p>
+    <a href="{@docRoot}design/handhelds/index.html" class="landing-page-link">Phones &amp; Tablets</a></p>
+  </div>
+  <a id="hero-image" href="{@docRoot}design/handhelds/index.html">
+    <img src="{@docRoot}design/media/device_family.png">
+  </a>
+</div>
+
diff --git a/docs/html/design/get-started/creative-vision.jd b/docs/html/design/get-started/creative-vision.jd
index 1ce305a..9261c6e 100644
--- a/docs/html/design/get-started/creative-vision.jd
+++ b/docs/html/design/get-started/creative-vision.jd
@@ -6,10 +6,10 @@
 <div class="vspace size-1">&nbsp;</div>
 
 <p itemprop="description">
-  We focused the design of Android around three overarching goals, which apply
-  to our core apps as well as the system at large. As you design apps to work
-  with Android, consider these goals: <em>Enchant me</em>, <em>Simplify my
-  life</em>, and <em>Make me amazing</em>
+  Starting with Ice Cream Sandwich, we focused the design of
+  Android around these three overarching goals, which apply
+  to our core apps as well as the system at large.
+  As you work with Android, consider these goals.
 </p>
 
 <div class="vspace size-1">&nbsp;</div>
diff --git a/docs/html/design/get-started/principles.jd b/docs/html/design/get-started/principles.jd
index 0b7147b..73ec3a6 100644
--- a/docs/html/design/get-started/principles.jd
+++ b/docs/html/design/get-started/principles.jd
@@ -1,9 +1,16 @@
-page.title=Design Principles
+page.title=Android Design Principles
 @jd:body
 
-<p>These design principles were developed by and for the Android User Experience Team to keep users'
-best interests in mind. Consider them as you apply your own creativity and design thinking. Deviate
-with purpose.</p>
+<p>These design principles were developed by and for the Android
+User Experience Team to keep users' best interests in mind.
+For Android developers and designers, they continue to
+underlie the more  detailed design guidelines for different
+types of devices.</p>
+
+<p>
+Consider these principles as you apply your own
+creativity and design thinking. Deviate with purpose.
+</p>
 
 <h2 id="enchant-me">Enchant Me</h2>
 
diff --git a/docs/html/design/get-started/ui-overview.jd b/docs/html/design/handhelds/index.jd
similarity index 87%
rename from docs/html/design/get-started/ui-overview.jd
rename to docs/html/design/handhelds/index.jd
index 5f4c40f..882b070 100644
--- a/docs/html/design/get-started/ui-overview.jd
+++ b/docs/html/design/handhelds/index.jd
@@ -1,12 +1,20 @@
-page.title=UI Overview
+page.title=Phones &amp; Tablets
 @jd:body
 
-<p>Android's system UI provides the framework on top of which you build your app. Important aspects
-include the Home screen experience, global device navigation, and notifications.</p>
-<p>Your app will play an important part in keeping the overall Android experience consistent and
-enjoyable to use. At the end of this chapter we introduce the main elements for achieving this goal
-in your app.</p>
-<p>Read on for a quick overview of the most important aspects of the Android user interface.</p>
+<p>
+Android's system UI provides the framework on top of which you build your app,
+whether you're designing for phones, tablets, watches, or other form factors.
+Aspects of UI that are especially important for phones and tablets include
+the Home screen experience, global device navigation, and notifications.
+</p>
+
+<p>
+Your app will play an important part in keeping the overall Android experience
+consistent and enjoyable to use. This page introduces some of the main elements
+that can help you achieve this goal. The main Android Design topics listed on
+the left, after the Devices sections, provide detailed guidelines for phones
+and tablets.
+</p>
 
 <h2 id="home-all-apps-recents">Home, All Apps, and Recents</h2>
 
diff --git a/docs/html/design/index.jd b/docs/html/design/index.jd
index cb7dd4f..27e3169 100644
--- a/docs/html/design/index.jd
+++ b/docs/html/design/index.jd
@@ -13,7 +13,7 @@
 
 #text-overlay {
   position: absolute;
-  left: 36px;
+  left: 0;
   top: 42px;
   width: 266px;
 
@@ -34,5 +34,15 @@
   <a id="hero-image" href="/design/get-started/creative-vision.html">
     <img src="/design/media/index_landing_page.png">
   </a>
+
+<div style="background: hsl(8, 70%, 54%); margin: 0; padding: 20px 20px 10px 20px;color: #fff; position: absolute;top: 255px;width: 179px;">
+<h2 style="color: #fff;margin:0 0 10px; font-size:18px" class="norule">L Developer Preview</h2>
+<p> The next version of Android uses a design
+metaphor inspired by paper and ink that provides a reassuring sense of tactility. Before it arrives for users, you can get an early
+look at the new Material design.
+</p>
+<p><a class="white" href="{@docRoot}preview/material/index.html">Learn more about Material</a></p>
+</div>
+
 </div>
 
diff --git a/docs/html/design/media/device_family.png b/docs/html/design/media/device_family.png
new file mode 100644
index 0000000..7889884
--- /dev/null
+++ b/docs/html/design/media/device_family.png
Binary files differ
diff --git a/docs/html/design/media/wear/1D_picker.png b/docs/html/design/media/wear/1D_picker.png
new file mode 100644
index 0000000..46c6bf6
--- /dev/null
+++ b/docs/html/design/media/wear/1D_picker.png
Binary files differ
diff --git a/docs/html/design/media/wear/2D_picker.png b/docs/html/design/media/wear/2D_picker.png
new file mode 100644
index 0000000..82c766a
--- /dev/null
+++ b/docs/html/design/media/wear/2D_picker.png
Binary files differ
diff --git a/docs/html/design/media/wear/2D_picker_action.png b/docs/html/design/media/wear/2D_picker_action.png
new file mode 100644
index 0000000..8560ef8
--- /dev/null
+++ b/docs/html/design/media/wear/2D_picker_action.png
Binary files differ
diff --git a/docs/html/design/media/wear/Bluebird.png b/docs/html/design/media/wear/Bluebird.png
new file mode 100644
index 0000000..447e643
--- /dev/null
+++ b/docs/html/design/media/wear/Bluebird.png
Binary files differ
diff --git a/docs/html/design/media/wear/action_button.png b/docs/html/design/media/wear/action_button.png
new file mode 100644
index 0000000..dfdffa3
--- /dev/null
+++ b/docs/html/design/media/wear/action_button.png
Binary files differ
diff --git a/docs/html/design/media/wear/action_on_card.png b/docs/html/design/media/wear/action_on_card.png
new file mode 100644
index 0000000..d0b0fff
--- /dev/null
+++ b/docs/html/design/media/wear/action_on_card.png
Binary files differ
diff --git a/docs/html/design/media/wear/assets_specifics.png b/docs/html/design/media/wear/assets_specifics.png
new file mode 100644
index 0000000..35a3819
--- /dev/null
+++ b/docs/html/design/media/wear/assets_specifics.png
Binary files differ
diff --git a/docs/html/design/media/wear/bridgednotifications.jpg b/docs/html/design/media/wear/bridgednotifications.jpg
new file mode 100644
index 0000000..a9e57a4
--- /dev/null
+++ b/docs/html/design/media/wear/bridgednotifications.jpg
Binary files differ
diff --git a/docs/html/wear/images/circle_message2.png b/docs/html/design/media/wear/circle_message2.png
similarity index 100%
rename from docs/html/wear/images/circle_message2.png
rename to docs/html/design/media/wear/circle_message2.png
Binary files differ
diff --git a/docs/html/design/media/wear/clear_bold_type.jpg b/docs/html/design/media/wear/clear_bold_type.jpg
new file mode 100644
index 0000000..e4b742c
--- /dev/null
+++ b/docs/html/design/media/wear/clear_bold_type.jpg
Binary files differ
diff --git a/docs/html/design/media/wear/confirmation.png b/docs/html/design/media/wear/confirmation.png
new file mode 100644
index 0000000..513b85f
--- /dev/null
+++ b/docs/html/design/media/wear/confirmation.png
Binary files differ
diff --git a/docs/html/design/media/wear/contextualnotification.png b/docs/html/design/media/wear/contextualnotification.png
new file mode 100644
index 0000000..1ec7ac8
--- /dev/null
+++ b/docs/html/design/media/wear/contextualnotification.png
Binary files differ
diff --git a/docs/html/design/media/wear/continue_phone.png b/docs/html/design/media/wear/continue_phone.png
new file mode 100644
index 0000000..fed93b6
--- /dev/null
+++ b/docs/html/design/media/wear/continue_phone.png
Binary files differ
diff --git a/docs/html/design/media/wear/copywrite.png b/docs/html/design/media/wear/copywrite.png
new file mode 100644
index 0000000..78be0bd
--- /dev/null
+++ b/docs/html/design/media/wear/copywrite.png
Binary files differ
diff --git a/docs/html/design/media/wear/countdown.png b/docs/html/design/media/wear/countdown.png
new file mode 100644
index 0000000..11b1504
--- /dev/null
+++ b/docs/html/design/media/wear/countdown.png
Binary files differ
diff --git a/docs/html/design/media/wear/customlayout.jpg b/docs/html/design/media/wear/customlayout.jpg
new file mode 100644
index 0000000..9573cfc
--- /dev/null
+++ b/docs/html/design/media/wear/customlayout.jpg
Binary files differ
diff --git a/docs/html/design/media/wear/dismiss_cards.png b/docs/html/design/media/wear/dismiss_cards.png
new file mode 100644
index 0000000..2e2d53b
--- /dev/null
+++ b/docs/html/design/media/wear/dismiss_cards.png
Binary files differ
diff --git a/docs/html/design/media/wear/expandable_stacks.png b/docs/html/design/media/wear/expandable_stacks.png
new file mode 100644
index 0000000..edc2456
--- /dev/null
+++ b/docs/html/design/media/wear/expandable_stacks.png
Binary files differ
diff --git a/docs/html/wear/images/fitness-24.png b/docs/html/design/media/wear/fitness.png
similarity index 100%
rename from docs/html/wear/images/fitness-24.png
rename to docs/html/design/media/wear/fitness.png
Binary files differ
diff --git a/docs/html/design/media/wear/low_info_card.png b/docs/html/design/media/wear/low_info_card.png
new file mode 100644
index 0000000..a3ebf16
--- /dev/null
+++ b/docs/html/design/media/wear/low_info_card.png
Binary files differ
diff --git a/docs/html/design/media/wear/peek_card.png b/docs/html/design/media/wear/peek_card.png
new file mode 100644
index 0000000..2b12297
--- /dev/null
+++ b/docs/html/design/media/wear/peek_card.png
Binary files differ
diff --git a/docs/html/design/media/wear/selection_list.png b/docs/html/design/media/wear/selection_list.png
new file mode 100644
index 0000000..dcb0745
--- /dev/null
+++ b/docs/html/design/media/wear/selection_list.png
Binary files differ
diff --git a/docs/html/design/media/wear/separate_info_cards.jpg b/docs/html/design/media/wear/separate_info_cards.jpg
new file mode 100644
index 0000000..d4cb386
--- /dev/null
+++ b/docs/html/design/media/wear/separate_info_cards.jpg
Binary files differ
diff --git a/docs/html/design/media/wear/separate_info_cards_1.jpg b/docs/html/design/media/wear/separate_info_cards_1.jpg
new file mode 100644
index 0000000..b987aea
--- /dev/null
+++ b/docs/html/design/media/wear/separate_info_cards_1.jpg
Binary files differ
diff --git a/docs/html/design/media/wear/separate_info_cards_2.jpg b/docs/html/design/media/wear/separate_info_cards_2.jpg
new file mode 100644
index 0000000..1930cb8
--- /dev/null
+++ b/docs/html/design/media/wear/separate_info_cards_2.jpg
Binary files differ
diff --git a/docs/html/design/media/wear/single_action_controls.jpg b/docs/html/design/media/wear/single_action_controls.jpg
new file mode 100644
index 0000000..ef89da0
--- /dev/null
+++ b/docs/html/design/media/wear/single_action_controls.jpg
Binary files differ
diff --git a/docs/html/design/media/wear/voice_commands.png b/docs/html/design/media/wear/voice_commands.png
new file mode 100644
index 0000000..9839ed8
--- /dev/null
+++ b/docs/html/design/media/wear/voice_commands.png
Binary files differ
diff --git a/docs/html/design/tv/images/apps-games-rows.png b/docs/html/design/tv/images/apps-games-rows.png
deleted file mode 100644
index 1724147..0000000
--- a/docs/html/design/tv/images/apps-games-rows.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/tv/images/atv-home.png b/docs/html/design/tv/images/atv-home.png
deleted file mode 100644
index 2c18827..0000000
--- a/docs/html/design/tv/images/atv-home.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/tv/images/atv.png b/docs/html/design/tv/images/atv.png
deleted file mode 100644
index cd96164..0000000
--- a/docs/html/design/tv/images/atv.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/tv/images/overscan.png b/docs/html/design/tv/images/overscan.png
deleted file mode 100644
index bf08dd8..0000000
--- a/docs/html/design/tv/images/overscan.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/tv/images/recommendations.png b/docs/html/design/tv/images/recommendations.png
deleted file mode 100644
index 579b390..0000000
--- a/docs/html/design/tv/images/recommendations.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/tv/images/search.png b/docs/html/design/tv/images/search.png
deleted file mode 100644
index be0d778..0000000
--- a/docs/html/design/tv/images/search.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/tv/images/settings.png b/docs/html/design/tv/images/settings.png
deleted file mode 100644
index f9f45fa..0000000
--- a/docs/html/design/tv/images/settings.png
+++ /dev/null
Binary files differ
diff --git a/docs/html/design/tv/index.jd b/docs/html/design/tv/index.jd
index 2519e25..5534724 100644
--- a/docs/html/design/tv/index.jd
+++ b/docs/html/design/tv/index.jd
@@ -1,31 +1,15 @@
-page.title=Design for TV
-header.justLinks=1
-footer.hide=1
+page.title=TV
 @jd:body
 
-<style>
-#landing-graphic-container {
-  position: relative;
-}
 
-#text-overlay {
-  position: absolute;
-  left: 0;
-  top: 402px;
-  width: 220px;
-}
-</style>
+<img src="{@docRoot}preview/tv/design/images/atv-home.jpg"
+  width="460" height="283" style="float:right;margin:0 0 40px 40px" /> 
 
-<div id="landing-graphic-container">
-  <div id="text-overlay">
-    <span itemprop="description">
-      Build beautiful apps for the biggest screen in the house.</span>
-    <br><br>
-    <a href="{@docRoot}design/tv/principles.html"
-       class="landing-page-link">Design Principles</a>
-  </div>
 
-  <a href="{@docRoot}design/tv/principles.html">
-    <img src="{@docRoot}design/tv/images/atv.png" style="margin-left: 70px;">
-  </a>
-</div>
+<p>Android TV is <strong>coming soon</strong> and lets you engage your users in a new, shared environment.</p>
+
+<p>Users bring a specific set of expectations to the experience of watching TV, versus interacting
+with a phone or tablet. So find out how to get your app ready for its big-screen debut
+later this year by reading the
+<a href="{@docRoot}preview/tv/design/index.html">Android TV Design Guide</a>
+in the L Developer Preview.</p>
\ No newline at end of file
diff --git a/docs/html/design/tv/patterns.jd b/docs/html/design/tv/patterns.jd
deleted file mode 100644
index c8cc0b0..0000000
--- a/docs/html/design/tv/patterns.jd
+++ /dev/null
@@ -1,100 +0,0 @@
-page.title=Patterns for TV
-page.tags="design"
-@jd:body
-
-<p>As a developer of apps for TV, you should follow certain patterns to enable users to
-  quickly understand and efficiently your app. This section describes recommended design patterns
-  for TV apps.</p>
-
-<h2>Navigation</h2>
-
-<p>Users typically navigate TV devices using a directional pad (D-Pad). This type of controller
-  limits movement to up, down, left, and right. In a typical D-Pad remote, hardware keys that
-  correspond to those directions are present and an additional action key is available to make a
-  selection. As you design your Android application for TVs, pay special attention to how users
-  navigate your application when using a remote control instead of a touchscreen.</p>
-
-<p>[add visual: D-Pad image or illustration]</p>
-
-<p>A key aspect of making your application work well with a D-Pad controller is to make sure
-  that there is always a object that is obviously in focus. If a user cannot see what is in focus,
-  they will not be able to navigate your app intuitively with this type of controller.</p>
-
-<p>Optimize your app screen layouts for D-Pad navigation. Align objects in your app lists and
-  grids to make navigation within each screen intuitive. Design your layout so it takes advantage of
-  two-axis navigation.</p>
-
-
-<h2>Home and Back Buttons</h2>
-
-<p>
-  In addition to the D-Pad buttons, Android TV devices always include Home and Back buttons on their
-  controllers. Make sure the Back button functions within your app in a way that is consistent with
-  the general <a href="{@docRoot}design/patterns/navigation.html">Android Design guidelines</a>.
-</p>
-
-
-<h2>Focus and Selection</h2>
-
-<p>Providing good focus and selection indicators is key to making your app useable on TV. As
-  mentioned previously, making sure that an object is always selected in your app is critical for
-  effective navigation using a D-Pad. This requirement also means that you must use focus indicators
-  that are easy to recognize and should be consistent throughout your app.</p>
-
-<p>
-  [add visual of selected item on screen]
-</p>
-
-<p>The default focus indicator used in Android TV use a combination of scale, shadow,
-  brightness, and opacity. The focus feedback is enhanced by displaying an animation going from a
-  non-focused to a focused state and back. Instead of immediately applying the focus transformation,
-  it is animated into place to reduce abrupt changes and help users notice how the object changed.</p>
-
-<h2>Audio Feedback</h2>
-
-<p>Sounds on Android TV bring a cinematic quality to the interaction experience. You should
-  consider adding sounds for user actions or to provide feedback when a user is only partially
-  visually engaged with the screen (e.g., because they have their hands full or are multitasking).
-  You should also consider using sounds as alternatives to error messages, for example to indicate
-  that a user has reached the end of a list or is trying to navigate to an undefined location.</p>
-
-<h2>Banners</h2>
-
-<p>
-  App Banners represent your app on the home screen of TV devices and serves and as a way for
-  users to launch your app. Here are specific requirements for the banner image:
-</p>
-
-<ul>
-  <li>Size: 320 x 180 px, xhdpi resource</li>
-  <li>Text should be included in the image. If your app is available in more than one
-      language, you must provide version of the banner image for each supported language.</li>
-</ul>
-
-
-<h2>App Icons</h2>
-
-<p>The app icon is shown in recommendation cards on the Home screen, search results and the main
-  Browse screen of your app if you use {@code BrowseFragment}. Here are the specific
-  requirements for the app icon:</p>
-
-<ul>
-  <li><p>Full color: size: 52x52dp, PNG</p></li>
-  <li><p>Monocolor: size 52x52dp, white(#fff) icon with transparent background, PNG</p></li>
-</ul>
-
-
-<h2>Background Images</h2>
-
-<p>Background images are displayed in the background of your app to provide additional visual
-  interest, information or branding. The BrowseFragment and DetailsFragment classes in the Leanback
-  support library provide specific support for background images and updating them as items are
-  brought into and out of focus. Here are the specific requirements for background images:</p>
-
-<ul>
-  <li>2016x1134 (1920x1080 + 5% extra margin for motion)</li>
-</ul>
-
-<p>
-  <strong>Note:</strong> If the image does not meet this requirement, it is scaled to fit.
-</p>
\ No newline at end of file
diff --git a/docs/html/design/tv/ui-overview.jd b/docs/html/design/tv/ui-overview.jd
deleted file mode 100644
index c58c9cd..0000000
--- a/docs/html/design/tv/ui-overview.jd
+++ /dev/null
@@ -1,63 +0,0 @@
-page.title=UI Overview for TV
-page.tags="design"
-@jd:body
-
-<p>The Android TV system user interface provides the launch pad for your app's big screen
-  experience. It's important to understand how your app is presented in the main user interface and
-  how your app can help users get to the content they want quickly, including contributing content
-  suggestions to the recommendations row.</p>
-
-<p>This section provides quick overview of the Android TV user interface.</p>
-
-
-<h2>Home Screen</h2>
-
-<p>The Home Screen is the start of a TV user's experience, providing search, content
-  recommendations, access to apps and settings. The Home Screen provides a rich and cinematic
-  overview of apps and content.</p>
-
-<img src="{@docRoot}design/tv/images/atv-home.png" alt="TV Home screen" />
-
-
-<h2>Search</h2>
-
-<p>By bringing the power of Google search to the big screen, Android TV makes new, dynamic
-  connections between content - a favorite movie may connect to the discovery of a new music artist,
-  planning trip to Paris might surface new YouTube content and photos.</p>
-
-<img src="{@docRoot}design/tv/images/search.png" alt="Recommendations Row" />
-
-
-<h2>Recommendations</h2>
-
-<p>The recommendation row on Android TV is a central feature of the Home Screen that allows
-  users quick access to dynamic and relevant content for their media consumption activities. The
-  stream is optimized for quick browsing of personalized content and activity resumption (on the
-  device and across devices), while also providing a way for users to act on meaningful new content.</p>
-
-<img src="{@docRoot}design/tv/images/recommendations.png" alt="Recommendations Row" />
-
-<p>
-  The recommendations are based on the user’s recent and frequent usage behaviors, as well as
-  expressed content preferences. They are presented as cards that represent a system or app action,
-  notification, activity, or piece of actionable media. Your app can provide suggestions for the
-  recommendations row to help get your content noticed. To learn more, see
-  <a href="{@docRoot}preview/tv/build-ui/recommendations.html">Recommendations</a>.
-</p>
-
-
-<h2>Apps and Games</h2>
-
-<p>Apps and Games rows both have special areas on the Home Screen. Within these respective
-  areas, Apps and Games titles are reordered to reflect the user’s recent usage.</p>
-
-<img src="{@docRoot}design/tv/images/apps-games-rows.png" alt="Apps and Games Rows" />
-
-
-<h2>Settings</h2>
-
-<p>Access to Settings is found at the bottom of the Home Screen. From here, the user can access
-  Android and device-specific settings. Please see the "Settings" section for more detailed
-  information.</p>
-
-<img src="{@docRoot}design/tv/images/settings.png" alt="Settings Row" />
diff --git a/docs/html/design/wear/creative-vision.jd b/docs/html/design/wear/creative-vision.jd
new file mode 100644
index 0000000..4530744
--- /dev/null
+++ b/docs/html/design/wear/creative-vision.jd
@@ -0,0 +1,36 @@
+page.title=Creative Vision for Wear
+@jd:body
+
+
+<p>Android Wear devices provide just the right information at just the right time,
+allowing users to be more connected to both the virtual world and the real world. Great Android
+Wear experiences are:</p>
+
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+    <h4>Launched automatically</h4>
+    <p>Most people are used to launching apps by clicking an icon. Android Wear is different. Wearable apps are aware of the user’s context - time, location, physical activity, and so on. The apps use this information to insert cards into the stream when they become relevant. This makes Android Wear timely, relevant and very specific.</p>
+  </div>
+  <div class="layout-content-col span-6" style="margin-left:75px">
+  <h4>Glanceable</h4>
+  <p>A classic wrist watch is designed to let you see the time in a split second and get on with what you were doing. Designing for Android Wear is no different. The less time it takes to use your software, the more time the user can be present in whatever they are doing. Android wear is fast, sharp and immediate.</p>
+  </div>
+</div>
+
+
+<div class="layout-content-row">
+  <div class="layout-content-col span-6">
+  <h4>Zero or low interaction</h4>
+  <p>Staying true to the strengths afforded by a smaller form factor, Android Wear focuses on simple interactions, only requiring input by the user when absolutely necessary. Most inputs are based around touch swipes or voice, and inputs requiring fine-grained finger movements are avoided. Android Wear is gestural, simple, and fast.</p>
+  </div>
+  <div class="layout-content-col span-6" style="margin-left:75px">
+  <h4>All about suggest and demand</h4>
+  <p>Android Wear is like a great personal assistant: it knows you and your preferences, it only interrupts you when absolutely necessary, and it’s always on hand to provide a ready answer. Android Wear is helpful, respectful, and responsive.</p>
+  </div>
+</div>
+
+<p>By providing a smart connection to the rest of the world while respecting the user’s attention, Android Wear feels personal and global, simple and smart, unobtrusive and ever-ready. Applications that represent these principles will feel most at home in the overall Android Wear experience.</p>
+
+<p>Third party apps extend Android Wear to be more specialized and helpful throughout the day. Installing apps are a way for the user to tell the Android Wear how to do that.</p>
+
diff --git a/docs/html/design/wear/index.jd b/docs/html/design/wear/index.jd
new file mode 100644
index 0000000..3536445
--- /dev/null
+++ b/docs/html/design/wear/index.jd
@@ -0,0 +1,67 @@
+page.title=Wear
+@jd:body
+
+
+
+<p>Designing apps for wearables powered by Android Wear
+is substantially different than designing for phones or
+tablets: different strengths and weaknesses, different use cases, different ergonomics.
+To get started, you should understand the overall vision for the Android Wear experience,
+and how apps fit into and enhance this experience.</p>
+
+<p>A new form factor deserves a new UI model. At a high level, the Android Wear UI consists of two
+main spaces centered around the core functions of <strong>Suggest</strong> and
+<strong>Demand</strong>. Your app will have an important role to play in both of these
+spaces.</p>
+
+
+
+<h2 id="Stream">Suggest: The Context Stream</h2>
+
+<div class="framed-wear-square" style="float:right;margin:0 -22px 60px 40px">
+  <img src="{@docRoot}wear/images/screens/stream.gif">
+</div>
+
+<p>The context stream is a vertical list of cards, each showing a useful or timely piece of information. Much like the Google Now feature on Android phones and tablets, users swipe vertically to navigate from card to card. Only one card is displayed at a time, and background photos are used to provide additional visual information. Your application can create cards and inject them into the stream when they are most likely to be useful.</p>
+
+<p>This UI model ensures that users don’t have to launch many different applications to check for updates; they can simply glance at their stream for a brief update on what’s important to them.</p>
+
+<p>Cards in the stream are more than simple notifications. They can be swiped horizontally to reveal additional pages. Further horizontal swiping may reveal buttons, allowing the user to take action on the notification. Cards can also be dismissed by swiping left to right, removing them from the stream until the next time the app has useful information to display.</p>
+
+
+
+
+<h2 id="CueCard">Demand: The Cue Card</h2>
+
+<div class="framed-wear-square" style="float:right;margin:0 -22px 60px 40px">
+  <img src="{@docRoot}wear/images/screens/cuecard.gif">
+</div>
+
+<p>For cases where Android Wear does not suggest an answer proactively through the context stream, the cue card allows users to speak to Google. The cue card is opened by saying, “OK Google” or by tapping on the background of the home screen. Swiping up on the cue card shows a list of suggested voice commands, which can also be tapped.</p>
+
+<p>At a technical level, each suggested voice command activates a specific type of intent. As a developer, you can match your applications to some of these intents so that users can complete tasks using these voice commands. Multiple applications may register for a single voice intent, and the user will have the opportunity to choose which application they prefer to use.</p>
+
+<p>Applications can respond to a voice command in the same way as they can respond to a tap on a regular in-stream action button: by adding or updating a stream card, or by launching a full screen application. Voice input often takes the form of a command, such as "remind me to get milk," in which case a simple confirmation animation is sufficient to display before automatically returning to the Context Stream.</p>
+
+
+<h2 id="Other">Other UI Features</h2>
+
+<ul>
+<li>The <strong>Home screen</strong> is the default state of the device and features:
+  <ul>
+  <li>The background, showing either content relating to the first card or a custom watch face design, depending on the watch face the user has chosen. Tapping anywhere on the background or saying "Ok Google" starts a voice query.
+  <li>Status indicators, showing connectivity, charging status, airplane mode, and in some watch faces a count of unread items.
+  <li>The top ranked card in the Context Stream, peeking up at the bottom of the screen. The amount of the peek card that appears is determined by the current watch face.
+  </ul>
+</li>
+
+<li><strong>Watch faces</strong> may be chosen by the user to appear in the background of the Home screen. Watch faces display the time and accommodate the top ranked peek card. The user can choose a different watch face by long pressing on the current one.</li>
+
+<li>Some devices may enter a low-power <strong>Ambient Mode</strong> when not being used. This usually involves dimming the screen in some way. The contents of a peek card will automatically be optimized for display in this state. Users can exit ambient mode by tapping on the screen, by tilting the screen towards them, or by pressing a hardware button if one exists.</li>
+
+<li>Swiping down on the Home screen reveals the <strong>Date and Battery</strong> display. Dragging further down toggles <strong>Mute mode</strong>, preventing interruptive notifications from vibrating and illuminating the screen.</li>
+
+<li>The <strong>Settings screen</strong> can be invoked from the cue card or on some devices using a hardware button. From here the user may shut down or restart their device, adjust screen brightness, toggle airplane mode, and access device information.</li>
+
+<li><strong>Full screen apps</strong> can be launched on top of the main stream where a wider range of interaction is called for. Although not stylistically limited to the context stream pattern, apps should respect the same design principles as the rest of the system. For more information, see the <a href="{@docRoot}design/wear/structure.html">App Structure</a> guide.</li>
+</ul>
\ No newline at end of file
diff --git a/docs/html/design/wear/patterns.jd b/docs/html/design/wear/patterns.jd
new file mode 100644
index 0000000..8f4698c
--- /dev/null
+++ b/docs/html/design/wear/patterns.jd
@@ -0,0 +1,150 @@
+page.title=UI Patterns for Wear
+@jd:body
+
+
+
+<p>Android Wear is used for micro-interactions, and so adhering to consistent design patterns that users are already accustomed to is paramount.</p>
+
+<h2>Cards</h2>
+
+<p>Cards in the stream can take slightly different forms:</p>
+
+<div class="framed-wear-square-small" style="float:left;margin:0 20px 20px 0">
+  <img src="{@docRoot}design/media/wear/Bluebird.png">
+</div>
+
+<div class="framed-wear-square-small" style="float:left;margin:0 20px 20px 0">
+  <img src="{@docRoot}design/media/wear/single_action_controls.jpg">
+</div>
+
+<div class="framed-wear-square-small" style="float:left;margin:0 20px 20px 0">
+  <img src="{@docRoot}design/media/wear/expandable_stacks.png">
+</div>
+                
+<ul style="clear:both">
+<li>Standard cards for displaying information from a notification</li>
+<li>Single-action controls (such as a play/pause toggle)</li>
+<li>Expandable stack of cards, for grouping a set of related notifications together</li>
+</ul>
+
+
+<h2>App icons</h2>
+
+<div class="framed-wear-square-small" style="float:right;margin:0 0 20px 60px">
+  <img src="{@docRoot}design/media/wear/clear_bold_type.jpg">
+</div>
+
+<p>App icons appear in a fixed position overhanging the edge at the top right of the card by default for all notifications in the Context Stream. This is an opportunity for cards to be recognized as coming from a specific source. Photo backgrounds should be used only to convey information, not to brand a card. App icons are necessary only on the leftmost card; it is not necessary to add the app icon to pages.</p>
+
+<h2 style="clear:both">Pages</h2>
+
+<div class="framed-wear-square-small" style="float:right;margin:0 0 20px 40px">
+  <img src="{@docRoot}design/media/wear/separate_info_cards_2.jpg">
+</div>
+
+<div class="framed-wear-square-small" style="float:right;margin:0 0 20px 40px">
+  <img src="{@docRoot}design/media/wear/separate_info_cards_1.jpg">
+</div>
+
+<p>Supplementary information should be displayed on additional cards to the right of a main Context Stream card. In most cases one additional detail card should be sufficient. For example, a weather card might show the weather for the current location today, with subsequent days listed in an additional card to the right. Keep the number of detail cards as low as possible. Actions (see below) should always come after pages; don’t change the order or interleave them.</p>
+
+
+<h2 style="clear:both">Dismissing cards</h2>
+
+  <img src="{@docRoot}design/media/wear/dismiss_cards.png" height="147">
+
+<p>Swiping from left to right on a card causes it to be dismissed from the stream. Dismissed cards may return when they next have relevant information. State is synced between the Android Wear context stream and the notifications on the Android handheld device, so dismissing from one causes an automatic dismissal from the other.</p>
+
+
+
+<h2 style="clear:both">Action buttons</h2>
+
+<div class="framed-wear-square-small" style="float:right;margin:0 0 20px 40px">
+  <img src="{@docRoot}design/media/wear/action_button.png">
+</div>
+
+<p>Where the user may need to take action on the information shown in a notification, you can provide action buttons. These are system-rendered buttons that appear to the right of detail cards. They consist of a white icon set on a blue system-rendered circular button and a short caption with a verb. Actions should be limited to three for a single card row.</p>
+
+<p>Tapping on an action button can cause an action to be executed; or an action to be continued on the companion handheld; or a full screen activity to be invoked for further input (see “2D Picker” section below).</p>
+
+<p>Refer to the UI Toolkit provided in the Downloads section for detailed specs regarding action icons.</p>
+
+
+<h2 style="clear:both">Action countdown and confirmation</h2>
+
+<div class="framed-wear-square-small" style="float:right;margin:0 0 20px 40px">
+  <img src="{@docRoot}design/media/wear/countdown.png">
+</div>
+
+<p>Where tapping on an action button results in an action being executed, one of the following can happen:</p>
+
+<ol>
+<li>The action is completed immediately and the result of the action is shown (either by updating the relevant card contents immediately, or by showing a confirmation animation).</li>
+<li>A short countdown animation to completing the action is played, which the user can interrupt to cancel. Once the timer has counted down, a confirmation animation is played. This animation can be custom-designed by developers.</li>
+<li>A confirmation step is required. This is for actions that are potentially damaging if accidentally triggered. A generic confirmation template is supplied by the system. Once the user confirms, the standard confirmation animation is played.</li>
+<li>The cue card can be invoked to continue specifying the action. For example in a messaging application, tapping a “Reply” action button invokes the Cue Card and prompts for voice input. In this case the prompt label (such as “Speak your message…”) and a set of sample voice suggestions can be specified by developers.</li>
+</ol>
+
+
+<h2 style="clear:both">Continuing activities on phone</h2>
+
+<div class="framed-wear-square-small" style="float:right;margin:0 0 20px 40px">
+  <img src="{@docRoot}design/media/wear/continue_phone.png">
+</div>
+
+<p>Developers should attempt to perform actions on the wearable device wherever possible. In cases where the phone must be used, a generic animation should be played once the action button has been tapped and the corresponding Android app will open on the phone.</p>
+
+
+<h2 style="clear:both">Actions on cards (such as media controls)</h2>
+
+<div class="framed-wear-square-small" style="float:right;margin:0 0 20px 40px">
+  <img src="{@docRoot}design/media/wear/action_on_card.png">
+</div>
+
+<p>Some cards may benefit from having tappable actions directly on a card. Some guidance on when to use this pattern versus using an action button:</p>
+
+<ul>
+<li>This pattern should be used when only one possible action could be reasonably expected. For example, tapping on an address with a car icon and ETA seems like it would very obviously launch directions. Conversely, if you see a contact's photo and name, it's not clear what tapping would do (call them? email them?), so the pattern shouldn't be used in this case.</li>
+<li>On-card actions should not require a text label to be understood.</li>
+<li>On-card actions should only result in something happening on the wearable (apart from web links to open them on the phone).</li>
+<li>Only one action per card: no menus on a single card.</li>
+</ul>
+
+<p>Good examples of using an action on card include: play / pause music; toggle light switch on and off; navigate to an address; call a phone number.</p>
+
+
+<h2 style="clear:both">Card stacks</h2>
+<img src="/wear/images/11_bundles_B.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" alt="">
+<img src="/wear/images/11_bundles_A.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" alt="">
+<p>Card stacks group related cards together and allow them to be progressively expanded vertically in the stream. A tap on a stack fans the cards out so that the top edge of each card can be seen. A subsequent tap on a fanned card reveals that card fully. Stacks of cards revert to a fully collapsed state once the user has swiped away from them.</p>
+
+
+
+<h2 style="clear:both">2D Picker</h2>
+
+<p>A 2D Picker component in your app can be invoked from the cue card or from an action button. It allows users to choose from a list of items, and optionally select an attribute of each item. For example, in response to a voice action to “buy tickets to a movie tonight,” you could show a 2D Picker with a vertical list of movies playing, with each movie having a horizontal list of showtimes.</p>
+
+<img src="{@docRoot}design/media/wear/2D_picker_action.png" width="500" alt="">
+
+<p>In some instances, further information may be required. In these cases, the most probable default values for these choices should be chosen on the user’s behalf with the option to edit before completing the action. This pattern is in keeping with Android Wear’s core design principle of minimizing interactions required.</p>
+
+
+<h2 style="clear:both">Voice commands</h2>
+
+<div class="framed-wear-square-small" style="float:right;margin:0 0 20px 40px">
+  <img src="{@docRoot}design/media/wear/voice_commands.png">
+</div>
+
+<p>It is possible for apps to take action in response to Android voice commands that invoke intents. For example, an app can register for the “Take a note” intent and capture the subsequent voice input for processing. In the case where multiple apps registered for the same intent, user preference will be captured once and saved. Users can edit their intent preferences in the Android Wear app on their handheld.</p>
+
+
+<h2 style="clear:both">Selection List</h2>
+
+<div class="framed-wear-square-small" style="float:right;margin:0 0 20px 40px">
+  <img src="{@docRoot}design/media/wear/selection_list.png">
+</div>
+
+<p>Choosing an item from a list is a common interaction. The Selection List pattern (available as the WearableListView component) creates a simple list optimized for ease of use on a small screen: the focused item snaps to the center of the screen, and a single tap selects. This widget is recommended as a common pattern for selecting items. It is used throughout the system UI, including in the list that can be accessed by swiping up on the cue card.</p>
+
+
+<p>Of course, it is possible for Android Wear apps to extend themselves beyond the familiarities of these patterns. For a deeper look at the options available, see the section on App Structure.</p>
diff --git a/docs/html/design/wear/principles.jd b/docs/html/design/wear/principles.jd
new file mode 100644
index 0000000..a214435
--- /dev/null
+++ b/docs/html/design/wear/principles.jd
@@ -0,0 +1,52 @@
+page.title=Design Principles for Wear
+@jd:body
+
+<style>
+p.try {
+  background:#e4e4e4;
+  padding:10px;
+}
+</style>
+
+<p>These design principles provide some simple heuristics about how you should plan and assess your
+Android Wear app design.</p>
+
+
+<h2>Focus on not stopping the user and all else will follow</h2>
+<p>A watch is a perfect form factor for a device that you can use while doing something else, such as cooking, eating, walking, running, or even having a conversation. If using your wearable app causes the user to stop whatever they’re doing, it’s a good occasion to consider how to improve it using the principles in this section.</p>
+
+<p class="try"><strong>Try this:</strong> Time a typical use of your Wear app. If using it takes more than 5 seconds, you should think about making your app more focused. Also try using your app while you’re having a conversation, and see how it affects your train of thought and eye contact.</p>
+
+
+<h2>Design for big gestures</h2>
+
+<p>When you swipe through photos on your phone you’re using a large area of the display, and you don’t have to be precise at all. That’s the best kind of interaction for a wearable device. Your users are going to use your app in all sorts of situations, the least frequent one might actually be sitting down at their desk.</p>
+
+<p class="try"><strong>Try this:</strong> Use your app in various everyday situations, such as walking, eating, talking to people, or ordering coffee. If you have to slow down while walking or stop the conversation to be precise, you should consider how your gestures could be bigger.</p>
+
+<h2>Think about stream cards first</h2>
+<p>The best experience on a wearable device is when the right content is there just when the user needs it. You can figure out when to show your cards with sensors, or events happening in the cloud. For the cases where it’s impossible to know when the user needs your app, you can rely on a voice action or touch.</p>
+
+<p class="try"><strong>Try this:</strong> Make a list of all the situations a user would find your app useful. What do they have in common? Same location? Time of day? Certain physical activities? You will most likely come up with several different situations - that’s a good sign, because it means that you can specialize your cards to those situations. Remember that the user always has the option of completely muting your stream cards if they feel they aren’t relevant enough.</p>
+
+
+<p>[image] </p>
+<p class="img-caption">An app that offers to check in users could appear in the stream suggesting the most likely place nearby, after a certain amount of time.</p>
+
+
+<h2>Do one thing, really fast</h2>
+<p>While users will engage with your app for only a few seconds at time, they'll use it many times throughout the day. A well-designed stream card carries one bit of information and potentially offers a few action buttons when the user swipes over.</p>
+
+<p class="try"><strong>Try this:</strong> How many bits of information is there in your design? Is everything absolutely necessary, or could you split it up into separate cards? If you’re designing a card, don’t forget that you can use multiple pages.</p>
+
+
+<h2>Design for the corner of the eye</h2>
+<p>The longer the user is looking at your app, the more you are pulling them out of the real world. Thinking about how to design your app for glanceability can vastly help the user get full value from your app and quickly go back to what they were doing.</p>
+
+<p class="try"><strong>Try this:</strong> To view your app with your peripheral vision, try focusing on your knuckles while your watch is displaying the app. Do you get a sense of what it is trying to do? Is it distinguishable from other apps? Does the background image help conveying the message? Does it use photos or a distinct shape and color?</p>
+
+<h2>
+Don’t be a constant shoulder tapper</h2>
+<p>A watch constantly touches the user’s skin. Being this intimate, you want to buzz the watch fewer times than you’re used to on the phone.</p>
+
+<p class="try"><strong>Try this:</strong> Next time you’re in a conversation, imagine someone tapping you your shoulder, interrupting you with the information you want your app to deliver. If the information delivered did not justify suspending a conversation, you should not make the notification interruptive.</p>
\ No newline at end of file
diff --git a/docs/html/design/wear/structure.jd b/docs/html/design/wear/structure.jd
new file mode 100644
index 0000000..caeb119
--- /dev/null
+++ b/docs/html/design/wear/structure.jd
@@ -0,0 +1,116 @@
+page.title=App Structure for Wear
+@jd:body
+
+
+<p>As outlined in the <a href="{@docRoot}design/wear/creative-vision.html">Creative Vision</a>,
+Android Wear apps do not adhere to the traditional mobile app model of touching an icon to launch into a self-contained experience. Rather, it is useful to think about the different spaces in the Android Wear UI and how your app might present itself across these spaces. For example, a typical app might begin by showing a notification card in the stream at a contextually relevant moment, then jump into a custom full screen UI for a micro-interaction, or maybe open the cue card to capture voice input that is then relayed back to the in-stream card.</p>
+
+<p>It’s important to make some fundamental decisions about how your users will interact with your app. There are a number of ways that functionality can manifest itself in Android Wear, and it is important to choose the places that provide maximum value and ease of use.</p>
+
+<p>For example, application functionality might show up in the following ways:</p>
+
+<ul>
+  <li>As a <strong>card in the main context stream</strong>:
+  <ul>
+    <li><strong>Bridged notifications</strong> are pushed to the wearable from the connected handheld (a phone or tablet) using the standard Android notifications framework. In general, bridged notifications mirror what’s happening on the handheld and use one of a predefined layout templates. Example: new message notification.
+    <li><strong>Contextual notifications</strong> are like smart notifications. They are generated locally on the wearable and appear at contextually relevant moments specificed by the app developer. Contextual notifications allow more freedom of control, allowing for custom layouts and dynamic updating of card contents. Example: live updating exercise stats.
+  </ul>
+  </li>
+  <li>As a <strong>full screen UI</strong> that temporarily overlays on top of the context stream:
+  <ul>
+    <li>The <strong>2D Picker</strong> is a simple design pattern (available in the SDK as a prebuilt component) aimed at asking the user to select from a set of items. This is a common interaction and a familiar pattern, so use of the familiar 2D Picker pattern is encouraged wherever possible. Example: choose from a set of artists and albums to play.
+    <li><strong>Custom layouts</strong> are also possible where apps need to extend beyond the basic card/stream metaphor. These apps should be distinctly separate from the core user experience in both appearance and interaction.</li>
+  </ul>
+  </li>
+</ul>
+
+
+<p>Apps can also open the cue card to capture voice input.</p>
+
+<p>Note that the different approaches above are listed in order of complexity. When designing your interactions, try to achieve them with the simplest approach possible. If your needs are more involved, move to the next level of complexity.</p>
+
+<p>Many applications will consist of a combination of these views, possibly with connections between them. For example, a contextual card may have an action that launches a more immersive experience. Inversely, an immersive experience may result in a card being added to the stream.</p>
+
+<p>Think of these different components as building blocks that can be snapped together into a single user flow. Avoid single monolithic full screen UIs that need to be launched and quit. Place simple notifications and ongoing information in the stream, and jump in and out of simple full screen activities to complete quick tasks before returning to the stream.</p>
+
+<p>In this section we will look at these different approaches and how combine them to create the best experience for your users.</p>
+
+
+<h2 id="Bridged">Bridged Notifications</h2>
+
+<div class="framed-wear-square-small" style="float:right;margin:0 -22px 60px 40px">
+  <img src="{@docRoot}design/media/wear/bridgednotifications.jpg">
+</div>
+
+<p>Bridged notifications are the simplest way of having content appear on an Android wearable. Since cards in the Android Wear stream are synced from the notifications on your connected handheld, any notifications created there automatically appear on Android Wear. Where appropriate, make sure to use the new APIs in the support library that enhance your app's notifications with features such as voice replies and notification pages.</p>
+
+
+
+<h2 id="Contextual">Contextual Notifications</h2>
+
+<p>Displaying information on contextual cards is at the core of the Android Wear user experience. Cards with focused trigger criteria appear at just the right time, delighting and assisting the user with timely, useful content. Refer to the Design principles section for details on how to think about triggering cards, and the UI overview section for a breakdown of the familiar system UI components that make up an entry in the context stream.</p>
+
+<p>An important aspect of creating contextual notifications is defining trigger conditions: what is the specific scenario in which your notification should appear? Think about using all sensor information available to you -- time, location, movement, identity, user habits and patterns, interaction with nearby devices, and more -- and describe the specific combination of sensor readings that should result in your app presenting itself.</p>
+
+
+<img src="{@docRoot}design/media/wear/contextualnotification.png" width="500" alt="" />
+
+
+<p>For example, imagine you were building a running app. If the user is standing at the beginning of their regular running trail, at the time that they often go for a run, and we detect a running activity... they are probably going for a run! This would be a great time to present a contextual card that offers to track their run.</p>
+
+<p>Putting effort into getting your contextual triggering just right is one of the most impactful things you can do to create a delightful experience for your users.</p>
+
+<p>You may use the standard Android notifications framework to create cards using a range of provided templates, or draw your own ActivityView inside cards for a custom card layout. Make sure to refer to the Style section to make sure your custom ActivityView layouts are sympathetic to the overall design of cards in the stream. Use ActivityViews to create custom card layouts that are stylistically consistent with neighboring cards in the stream; do not invent entirely new or conflicting UI patterns inside cards.</p>
+
+<p>Contextual cards are ideal for situations where it may be useful to push information to the user, when the information may be useful on an ongoing basis or referred back to, or when context strongly indicates that the information is useful. Refer to the section on Respecting Users Attention in the Design Principles section for details on targeted triggering. Triggering too often or in unsuitable contexts will result in users being annoyed by your app.</p>
+
+
+
+<h2 id="Picker">2D Picker</h2>
+
+<p>The 2D Picker design pattern (available as the GridViewPager component) is useful for showing a range of options or asking a user to make a quick selection. Google search results on Android Wear are a great example of the GridViewPager pattern in action.</p>
+
+<p>A 2D Picker is called up as an overlay on the main UI by tapping a card or button, or through a voice action. It preserves the same look and feel as the main context stream, giving users a familiar and predictable set of interaction patterns to rely on.</p>
+
+<p>On Android Wear, the basic hierarchy is vertical-then-horizontal, never horizontal-then-vertical, with a recommended vertical limit of five cards. Each vertical slot may consist of one card, as in the Google results case, or multiple cards which may be swiped horizontally.</p>
+
+<img src="{@docRoot}design/media/wear/1D_picker.png" alt="" width="499px" />
+<p class="img-caption">This pattern can be used to present a single vertical list, or a “1D Picker”</p>
+
+<img src="{@docRoot}design/media/wear/2D_picker.png" alt="" width:760px" />
+<p class="img-caption">It can also be used as a 2D matrix of options, as a way of presenting categorized options.</p>
+
+<p>This flexibility means that developers can choose to present a one or two-dimensional set of options. For example, a music app could use a vertical list to present a list of albums by a given artist (one dimension of options), and it could additionally allow each album slot to be horizontally swipeable to also choose a song from each album (a second dimension of options).</p>
+
+<p>Do not add buttons or pages to horizontal 2D Picker rows; rows should only be used to present a list or grid of similar options in this context. Provide a clear call to action on the card using the Action cards pattern detailed in the <a href="{@docRoot}design/wear/patterns.html">UI Patterns</a> guide.</p>
+
+<p>2D Picker should be automatically dismissed when a selection is made. It may also be exited by swiping back down on the first card, or by swiping left to right on a leftmost card.</p>
+
+<p>The simplicity of individual cards within a 2D Picker is a feature. Remember that in many cases the user may be on the go or attempting to complete a task as quickly as possible. As such, micro-interactions and familiar input mechanism are paramount, and using the already-familiar pattern of vertically-then-horizontally oriented cards gives users exactly what they want with as little fuss as possible. Strive to minimize the number of results or options that you present. Show the most popular or repeatedly-used options at the top of the list of cards to avoid scrolling. Learn the user's preferences and use context detection to put the most likely option for any given situation at the top. In general, optimize for fast task completion over excessive customization.</p>
+
+
+
+<h2 id="Custom">Custom Layouts</h2>
+
+<p>Some interactions may require a broader range of input mechanisms than is possible within the limitations of a card-based UI. For example, an app that allows for location selection may require the user to swipe in many directions before tapping to drop a pin. In cases like this, it is recommended to momentarily launch out of the context stream UI and present an immersive, full screen app with a custom layout.</p>
+
+<p>Custom full screen apps provides the benefit of flexibility: you can launch your own Android activity that takes up the entire screen, and capture all touch events, making a wide range of UIs possible.</p>
+
+<img src="{@docRoot}design/media/wear/customlayout.jpg" alt="" width="760px" />
+
+
+<p>However, be cautious of making this the default way of accessing your app’s functionality. Users will thank you for presenting your content in the familiar, simple environment of the context stream if it is possible to do so. Only enter full screen mode when the interactions required are not possible using the card UI. Full screen is a modal state to be entered for the purpose of achieving a specific task, and in most cases should be easily and quickly exited. You should use full screen apps to achieve a single, quick task within a broader user flow that hinges off the Context Stream. A great full screen experience will present itself quickly, ask for some user input, and then self-quit back to the stream.</p>
+
+<p>To avoid confusion, avoid using the specific styles and idioms of the context stream when designing immersive experiences. If you find yourself replicating the structure of the card layout, your should probably be using a 2D Picker. Make your immersive experience visually distinct. However, still adhere to the <a href="{@docRoot}design/wear/principles.html">Design Principles</a>, which apply universally to Android Wear interfaces.</p>
+
+<p>Because Android wearables do not feature a home or back button, exiting the application at the appropriate time is the responsibility of the app developer. Exiting always leads back to the context stream. Where possible, exit automatically or present the option to exit at logical break points using acknowledge/cancel buttons. For example:</p>
+
+<ol>
+<li>A map view that allows the user to slide a map to drop a pin on a location should automatically exit when the pin has been placed.</li>
+<li>A short game should automatically exit back to the stream at the end of each game.</li>
+<li>A drawing app should display the option to exit after 5 seconds of inactivity.</li>
+</ol>
+
+<p>Even with logical exit points like these, some cases may exist where the user may want to immediately initiate an exit. This may be particularly common in apps of longer duration. In all cases, the developer should <strong>present the option to quit the app on long press</strong> using DismissOverlayView. Your design should long press for the sole purpose of prompting to quit.</p>
+
+<p>Seamlessly and fluidly moving between the context stream and immersive mode makes your app feel like an integrated part of the Android Wear experience.</p>
\ No newline at end of file
diff --git a/docs/html/design/wear/style.jd b/docs/html/design/wear/style.jd
new file mode 100644
index 0000000..ed39bd6
--- /dev/null
+++ b/docs/html/design/wear/style.jd
@@ -0,0 +1,102 @@
+page.title=Style for Wear
+@jd:body
+
+
+<p>Here are a number of design considerations to bear in mind that are particular to Android Wear.</p>
+
+<h2 id="ScreenSize">Screen Size</h2>
+
+<img src="{@docRoot}design/media/wear/circle_message2.png" height="200"
+   style="float:right;margin:0 0 20px 60px">
+
+<img src="{@docRoot}design/media/wear/fitness.png" height="200"
+  style="float:right;margin:0 0 20px 60px">
+
+<p>Be mindful of different device sizes and shapes. Wearable devices are a form of fashion and expression for their owners, and so Android Wear supports  a variety of forms. Most of the complexities of supporting these different devices is taken care of at a system level, but bear in mind different screen types when designing custom full screen apps.</p>
+
+<p>Use the Android Wear emulator to test both square and round devices, and note that <code>WatchViewStub</code> is available to activities to detect whether a square or round device is being used.</p>
+
+
+
+
+<h2 id="Assets" style="clear:both">Specific Assets Required</h2>
+
+<img src="{@docRoot}design/media/wear/assets_specifics.png" width="300"
+  style="float:left;margin:0 60px 20px 0">
+
+<p>A core set of standard assets may need to be provided depending on your card design: app icon, background image or images, action icons, actions confirmation animation. Of course, your specific design may necessitate other assets. Background image should be provided in landscape format at least 600px width for notifications that include pages of cards, since the system automatically adds a parallaxing effect.</p>
+
+
+
+<h2 id="PeekCard" style="clear:both">Peek Card Readability</h2>
+
+<img src="{@docRoot}design/media/wear/peek_card.png" width="300"
+  style="float:left;margin:0 60px 20px 0">
+
+<p>Test your card layout to ensure that useful information is conveyed in the peek state on the Home screen. The main message of the card should be readable in the peek state, particularly for contextual cards. Content that requires an interaction to be read, for example a long message, should be cropped appropriately to provide an affordance to the user to swipe the card to read more.</p>
+
+
+
+<h2 id="InfoDensity" style="clear:both">Low Information Density</h2>
+
+<div class="framed-wear-square-small" style="float:right;margin:0 0 40px 60px">
+  <img src="{@docRoot}design/media/wear/low_info_card.png">
+</div>
+
+<p>Cards should be designed to be glanceable in a split second, just like reading the time on a traditional watch. In most cases a pairing of an icon and value, or a title and short caption should be enough to convey a meaningful message. Note that the background photo should also be used to convey information; backgrounds that change to reflect and support the primary message in the card work great. For example, in the case illustrated above a suitable background image is chosen to reflect severity of the current traffic conditions. This is not just a nice piece of attention to detail; the background actually reinforces the message and makes the content more glanceable.</p>
+
+
+<h2 id="Chunks" style="clear:both">Separate Information into Chunks</h2>
+
+<img src="{@docRoot}design/media/wear/separate_info_cards.jpg" width="400"
+  style="float:left;margin:0 60px 20px 0">
+
+<p>In cases where additional information is absolutely necessary, don’t crowd out a card layout to the point where glanceability is affected. Instead, add an additional page (or multiple pages, if needed) to the right of the main card in the stream to which the user can swipe for more information. See also “Continuing activities on phone”, below.</p>
+
+
+<h2 id="KeepMinimum" style="clear:both">Keep Notifications to a Minimum</h2>
+
+<p>Don’t abuse the user’s attention. Active notifications (that is, those that cause the device to vibrate) should only be used in cases that are both timely and involve a contact, for example receiving a message from a friend. Non-urgent notifications should be silently added to the Context Stream. See also the general Android Notifications Guidelines.</p>
+
+
+<h2 id="Typography" style="clear:both">Use Clear, Bold Typography</h2>
+
+<div class="framed-wear-square-small" style="float:right;margin:0 0 60px 40px">
+  <img src="{@docRoot}design/media/wear/clear_bold_type.jpg">
+</div>
+
+<p>The system font is Roboto Condensed, with Regular and Light variants. Text should adhere to the size and color recommendations (see the UI Toolkit in the Downloads section). In general, text should be displayed as large as possible. Your goal should be to convey maximum information with minimum fuss.</p>
+
+
+<h2 id="Branding" >Use Consistent Branding and Color</h2>
+
+<p>The app icon is used to identify and brand your application. The icon is optional but when present always appears in the same location, overhanging the top edge of the card at the right. Note that app icons or branding should not be displayed in the background photo, which is reserved to display an image relevant to the information on the card.</p>
+
+
+<h2 id="Copywrite" style="clear:both">Copywrite Sparingly</h2>
+
+<div class="framed-wear-square-small" style="float:right;margin:0 0 60px 40px">
+  <img src="{@docRoot}design/media/wear/copywrite.png">
+</div>
+
+<p>Omit needless text. Design for glanceability, not reading. Use words and phrases, not sentences. Use icons paired with values instead of text wherever possible. Text strings should be as concise as possible, and long pieces of text will be truncated to fit on a single card.</p>
+
+
+<h2 id="BeDiscreet" >Be Discreet if Necessary</h2>
+
+<p>Wearables are personal devices by nature, but they are not completely private. If your notification serves content that may be particularly sensitive or embarrassing (such as notifications from a dating app or a medical status report), consider not displaying all of the information in a peek card. A notification could place the sensitive information on a second page that must be swiped to, or an application could show different amounts of detail in peek and focused card positions.</p>
+
+
+<h2 id="ConfirmAnim" style="clear:both">Confirmation Animations</h2>
+
+<div class="framed-wear-square-small" style="float:left;margin:0 40px 40px 0 ">
+  <img src="{@docRoot}design/media/wear/confirmation.png">
+</div>
+
+<p>If your app allows the user to perform an action, it is necessary to provide positive feedback. Show a generic confirmation animation or create your own. A confirmation animation is an opportunity to express your app’s character and insert a moment of delight for your user. Keep animations short (less than 1000ms) and simple. Animating the confirmation icon is an effective way of transitions the user to a new state after completing an action.</p>
+
+
+
+
+
+
diff --git a/docs/html/google/gcm/ccs.jd b/docs/html/google/gcm/ccs.jd
index 03addfd..4389e3d 100644
--- a/docs/html/google/gcm/ccs.jd
+++ b/docs/html/google/gcm/ccs.jd
@@ -19,7 +19,11 @@
         <li><a href="#response">Response format</a></li>
       </ol>
       </li>
-  <li><a href="#upstream">Upstream Messages</a> </li>
+  <li><a href="#upstream">Upstream Messages</a>
+    <ol>
+      <li><a href="#receipts">Receive return receipts</a></li>
+    </ol>
+  </li>
   <li><a href="#flow">Flow Control</a> </li>
   <li><a href="#implement">Implementing an XMPP-based App Server</a>
     <ol class="toc">
@@ -43,9 +47,6 @@
 </div>
 </div>
 
-<p class="note"><strong>Note:</strong> To try out this feature, sign up using
-<a href="https://services.google.com/fb/forms/gcm/">this form</a>.</p>
-
 <p>The GCM Cloud Connection Server (CCS) is an XMPP endpoint that provides a
 persistent, asynchronous, bidirectional connection to Google servers. The
 connection can be used to send and receive messages between your server and
@@ -149,8 +150,8 @@
   <li>CCS adds the field {@code message_id}, which is required. This ID uniquely
 identifies the message in an XMPP connection. The ACK or NACK from CCS uses the
 {@code message_id} to identify a message sent from 3rd-party app servers to CCS.
-Therefore, it's important that this {@code message_id} not only be unique, but
-always present.</li>
+Therefore, it's important that this {@code message_id} not only be unique (per
+sender ID), but always present.</li>
 </ul>
 
 <p>In addition to regular GCM messages, control messages are sent, indicated by
@@ -188,7 +189,8 @@
           &quot;hello&quot;:&quot;world&quot;,
       }
       &quot;time_to_live&quot;:&quot;600&quot;,
-      &quot;delay_while_idle&quot;: true/false
+      &quot;delay_while_idle&quot;: true/false,
+      &quot;delivery_receipt_requested&quot;: true/false
   }
   &lt;/gcm&gt;
 &lt;/message&gt;
@@ -227,42 +229,48 @@
 <p>Below are some examples.</p>
 
 <p>Bad registration:</p>
+
 <pre>&lt;message&gt;
-  &lt;data:gcm xmlns:data=&quot;google:mobile:data&quot;&gt;
+  &lt;gcm xmlns=&quot;google:mobile:data&quot;&gt;
   {
-    &quot;error&quot;:&quot;BAD_REGISTRATION&quot;,  // error code
+    &quot;message_type&quot;:&quot;nack&quot;,
     &quot;message_id&quot;:&quot;msgId1&quot;,
-    &quot;from&quot;:&quot;PA91bHFOtaQGSwupt5l1og&quot;,
-    &quot;message_type&quot;:&quot;nack&quot;
+    &quot;from&quot;:&quot;SomeInvalidRegistrationId&quot;,
+    &quot;error&quot;:&quot;BAD_REGISTRATION&quot;,
+    &quot;error_description&quot;:&quot;Invalid token on 'to' field: SomeInvalidRegistrationId&quot;
   }
-  &lt;/data:gcm&gt;
+  &lt;/gcm&gt;
 &lt;/message&gt;</pre>
 
-<p>Invalid "time to live":</p>
+<p>Invalid JSON:</p>
 
 <pre>&lt;message&gt;
-  &lt;data:gcm xmlns:data=&quot;google:mobile:data&quot;&gt;
-  {
-     &quot;error&quot;:&quot;InvalidJson : INVALID_TTL : Invalid value (-1) for \&quot;time_to_live\&quot;: must be between 0 and \&quot;2419200\&quot;\n&quot;,
-     &quot;message_id&quot;:&quot;msgId1&quot;,
-     &quot;from&quot;:&quot;APA91bHFOtaQGSwupt5l1og&quot;,
-     &quot;message_type&quot;:&quot;nack&quot;
-  }
-  &lt;/data:gcm&gt;
-&lt;/message&gt;</pre>
+ &lt;gcm xmlns=&quot;google:mobile:data&quot;&gt;
+ {
+   &quot;message_type&quot;:&quot;nack&quot;,
+   &quot;message_id&quot;:&quot;msgId1&quot;,
+   &quot;from&quot;:&quot;APA91bHFOtaQGSwupt5l1og&quot;,
+   &quot;error&quot;:&quot;INVALID_JSON&quot;,
+   &quot;error_description&quot;:&quot;InvalidJson: JSON_TYPE_ERROR : Field \&quot;time_to_live\&quot; must be a JSON java.lang.Number: abc&quot;
+ }
+ &lt;/gcm&gt;
+&lt;/message&gt;
+</pre>
 
-<p>JSON type error:</p>
+<p>Quota exceeded:</p>
 
 <pre>&lt;message&gt;
-  &lt;data:gcm xmlns:data=&quot;google:mobile:data&quot;&gt;
-  {
-     &quot;error&quot;:&quot;InvalidJson : JSON_TYPE_ERROR : Field \&quot;delay_while_idle\&quot; must be a JSON java.lang.Boolean: not-boolean-user-supplied-value\n&quot;,
-     &quot;message_id&quot;:&quot;msgId1&quot;,
-     &quot;from&quot;:&quot;APA91bHFOtaQGSwupt5l1og&quot;,
-     &quot;message_type&quot;:&quot;nack&quot;
-  }
-  &lt;/data:gcm&gt;
-&lt;/message&gt;</pre>
+ &lt;gcm xmlns=&quot;google:mobile:data&quot;&gt;
+ {
+   &quot;message_type&quot;:&quot;nack&quot;,
+   &quot;message_id&quot;:&quot;msgId1&quot;,
+   &quot;from&quot;:&quot;APA91bHFOtaQGSwupt5l1og&quot;,
+   &quot;error&quot;:&quot;QUOTA_EXCEEDED&quot;,
+   &quot;error_description&quot;:&quot;Short-term downstream quota exceeded for this registration id&quot;
+ }
+ &lt;/gcm&gt;
+&lt;/message&gt;
+</pre>
 
 
 <p>The following table lists NACK error codes. Unless otherwise
@@ -300,7 +308,7 @@
 </tr>
 <tr>
 <td>{@code INVALID_JSON}</td>
-<td>The JSON message payload was not valid.</td>
+<td>The JSON message payload is not valid.</td>
 </tr>
 <tr>
 <td>{@code QUOTA_EXCEEDED}</td>
@@ -309,10 +317,10 @@
 rate.</td>
 </tr>
 <tr>
-<td>{@code SERVICE_UNAVAILABLE}</td>
-<td>CCS is not currently able to process the message. The
-message should be retried over the same connection using exponential backoff
-with an initial delay of 1 second.</td>
+  <td>{@code SERVICE_UNAVAILABLE}</td>
+  <td>CCS is not currently able to process the message. The
+    message should be retried over the same connection using exponential backoff
+    with an initial delay of 1 second.</td>
 </tr>
 </table>
 
@@ -382,8 +390,8 @@
 // Bundle data consists of a key-value pair
 data.putString("hello", "world");
 // "time to live" parameter
-// This is optional. It specifies a value in seconds up to 4 weeks.
-int ttl = [0 seconds, 4 weeks]
+// This is optional. It specifies a value in seconds up to 24 hours.
+int ttl = [0 seconds, 24 hours]
 
 gcm.send(GCM_SENDER_ID + "&#64;gcm.googleapis.com", id, ttl, data);
 </pre>
@@ -419,6 +427,69 @@
   &lt;/gcm&gt;
 &lt;/message&gt;</pre>
 
+<h3 id="receipts">Receive return receipts</h3>
+
+<p>You can use upstream messaging to get receipt notifications, confirming
+that a given message was sent to a device. Your 3rd-party app server receives the receipt
+notification from CCS once the message has been sent to the device.</p>
+
+<p>To enable this feature, the message your 3rd-party app server sends to CCS must include
+a field called <code>&quot;delivery_receipt_requested&quot;</code>. When this field is set to
+<code>true</code>, CCS sends a return receipt. Here is an XMPP stanza containing a JSON
+message with <code>&quot;delivery_receipt_requested&quot;</code> set to <code>true</code>:</p>
+
+<pre>&lt;message id=&quot;&quot;&gt;
+  &lt;gcm xmlns=&quot;google:mobile:data&quot;&gt;
+  {
+      &quot;to&quot;:&quot;REGISTRATION_ID&quot;,
+      &quot;message_id&quot;:&quot;m-1366082849205&quot;
+      &quot;data&quot;:
+      {
+          &quot;hello&quot;:&quot;world&quot;,
+      }
+      &quot;time_to_live&quot;:&quot;600&quot;,
+      &quot;delay_while_idle&quot;: true,
+      <strong>&quot;delivery_receipt_requested&quot;: true</strong>
+  }
+  &lt;/gcm&gt;
+&lt;/message&gt;
+</pre>
+
+<p>Here is an example of a receipt notification message that CCS sends back to your 3rd-party
+app server:</p>
+
+</p>
+<pre>&lt;message id=&quot;&quot;&gt;
+  &lt;gcm xmlns=&quot;google:mobile:data&quot;&gt;
+  {
+      &quot;category&quot;:&quot;com.example.yourapp&quot;, // to know which app sent it
+      &quot;data&quot;:
+      {
+         &#x201c;message_status&quot;:&quot;MESSAGE_SENT_TO_DEVICE&quot;,
+         &#x201c;original_message_id&#x201d;:&#x201d;m-1366082849205&#x201d;
+         &#x201c;device_registration_id&#x201d;: &#x201c;REGISTRATION_ID&#x201d;
+      },
+      &quot;message_id&quot;:&quot;dr2:m-1366082849205&quot;,
+      &quot;message_type&quot;:&quot;receipt&quot;,
+      &quot;from&quot;:&quot;gcm.googleapis.com&quot;
+  }
+  &lt;/gcm&gt;
+&lt;/message&gt;</pre>
+
+<p>Note the following:</p>
+
+<ul>
+  <li>The {@code &quot;message_type&quot;} is set to {@code &quot;receipt&quot;}.
+  <li>The {@code &quot;message_status&quot;} is set to {@code &quot;MESSAGE_SENT_TO_DEVICE&quot;},
+  indicating that the message was delivered. Notice that in this case,
+{@code &quot;message_status&quot;} is not a field but rather part of the data payload.</li>
+  <li>The receipt message ID consists of the original message ID, but with a
+<code>dr:</code> prefix. Your 3rd-party app server must send an ACK back with this ID,
+which in this example is {@code dr2:m-1366082849205}.</li>
+  <li>The original message ID and status are inside the
+{@code &quot;data&quot;} field.</li>
+</ul>
+
 <h2 id="flow">Flow Control</h2>
 
 <p>Every message sent to CCS receives either an ACK or a NACK response. Messages
diff --git a/docs/html/google/gcm/client.jd b/docs/html/google/gcm/client.jd
index ac446dc..20bff10 100644
--- a/docs/html/google/gcm/client.jd
+++ b/docs/html/google/gcm/client.jd
@@ -246,7 +246,8 @@
 <h3 id="sample-register">Register for GCM</h3>
 <p>An Android application needs to register with GCM servers before it can receive
 messages. When an app registers, it receives a registration ID, which it can then
-store for future use. In the following snippet the {@code onCreate()} method in the sample app's
+store for future use (note that registration IDs must be kept secret). In the
+following snippet the {@code onCreate()} method in the sample app's
 main activity checks to see if the app is already registered with GCM and with
 the server:</p>
 
diff --git a/docs/html/google/gcm/gcm.jd b/docs/html/google/gcm/gcm.jd
index 88bf659..19151b9 100644
--- a/docs/html/google/gcm/gcm.jd
+++ b/docs/html/google/gcm/gcm.jd
@@ -123,7 +123,7 @@
 it to the 3rd-party application server, which uses it to identify each device 
 that has registered to receive messages for a given Android application. In other words,
 a registration ID is tied to a particular Android application running on a particular
-device.
+device. Note that registration IDs must be kept secret.
 <br/>
 <br/>
 <strong>Note:</strong> If you use 
diff --git a/docs/html/google/gcm/index.jd b/docs/html/google/gcm/index.jd
index 70f7a9c..56e0865 100644
--- a/docs/html/google/gcm/index.jd
+++ b/docs/html/google/gcm/index.jd
@@ -14,7 +14,10 @@
   <h1 itemprop="name" style="margin-bottom:0;">Google Cloud Messaging for Android</h1>
   <p itemprop="description">
   Google Cloud Messaging for Android (GCM) is a service that allows you to send data
-from your server to your users' Android-powered device, and also to receive messages from devices on the same connection. The GCM service handles all aspects of queueing of messages and delivery to the target Android application running on the target device. GCM is completely free no matter how big your messaging needs are, and there are no quotas.
+from your server to your users' Android-powered device, and also to receive messages from
+devices on the same connection. The GCM service handles all aspects of queueing of messages
+and delivery to the target Android application running on the target device. GCM is
+completely free no matter how big your messaging needs are, and there are no quotas.
 </p>
 
 </div>
@@ -27,31 +30,39 @@
     <p>This could be a lightweight
 message telling your app there is new data to be fetched from the
 server (for instance, a movie uploaded by a friend), or it could be a message containing
-up to 4kb of payload data (so apps like instant messaging can consume the message directly). <a href="{@docRoot}google/gcm/gcm.html">GCM Architectural Overview.</a></p>
+up to 4kb of payload data (so apps like instant messaging can consume the message directly).
+<a href="{@docRoot}google/gcm/gcm.html">GCM Architectural Overview.</a></p>
 
     <h4>Send "send-to-sync" messages</h4>
-    <p>A send-to-sync (collapsible) message is often a "tickle" that tells a mobile application to sync data from the server. For example, suppose you have an email application. When a user receives new email on the server, the server pings the mobile application with a "New mail" message. This tells the application to sync to the server to pick up the new email.
-    <a href="{@docRoot}google/gcm/adv.html#s2s">Send-to-sync messages</a>.</p>
-    </a>
+    <p>A send-to-sync (collapsible) message is often a "tickle" that tells a mobile
+    application to sync data from the server. For example, suppose you have an email
+    application. When a user receives new email on the server, the server pings the mobile
+    application with a "New mail" message. This tells the application to sync to the server
+    to pick up the new email.
+    <a href="{@docRoot}google/gcm/adv.html#s2s">Learn more &raquo;</a></p>
 
     <h4>Send messages with payload</h4>
-    <p>Unlike a send-to-sync message, every "message with payload" (non-collapsible message) is delivered. The payload the message contains can be up to 4kb.
-    <a href="{@docRoot}google/gcm/adv.html#payload">Messages with payload</a>.</p>
+    <p>Unlike a send-to-sync message, every "message with payload" (non-collapsible message)
+    is delivered. The payload the message contains can be up to 4kb.
+    <a href="{@docRoot}google/gcm/adv.html#payload">Learn more &raquo;</a></p>
   </div>
 
 
   <div class="col-6 normal-links">
     <h3 style="clear:left">New Features</h3>
-    <h4>Faster, easier GCM setup</h4>
-    <p>Streamlined registration makes it simple and fast to add GCM support to your Android app. <a href="{@docRoot}google/gcm/gs.html">Learn more &raquo;</a></p>
-    <h4>Upstream messaging over XMPP</h4>
-    <p>GCM's Cloud Connection Service (CCS) lets you communicate with Android devices over a persistent XMPP connection. The primary advantages of CCS are speed, and the ability to receive upstream messages (that is, messages from a device to the cloud). You can use the service in tandem with existing GCM APIs. Use <a href="https://services.google.com/fb/forms/gcm/">this form</a> to sign up for CCS. <a href="{@docRoot}google/gcm/ccs.html">Learn more &raquo;</a></p>
 
-    <h4>Seamless multi-device messaging</h4>
-    <p>Maps a single user to a notification key, which you can then use to send a single message to multiple devices owned by the user. Use <a href="https://services.google.com/fb/forms/gcm/">this form</a> to sign up for User Notifications. <a href="{@docRoot}google/gcm/notifications.html">Learn more &raquo;</a></p>
+
+
+    <h4>Return Receipts</h4>
+    <p>You can use upstream messaging to get receipt notifications, confirming that a given
+    message was sent to a device. Your 3rd-party app server receives the receipt notification
+    from CCS once the message has been sent to the device.
+    <a href="{@docRoot}google/gcm/ccs.html#receipts">Learn more &raquo;</a></p>
+
 
    <h4>Get Started</h4>
-    <p>Get started using the new features with a tutorial that walks you through creating a GCM app. <a href="{@docRoot}google/gcm/gs.html">Learn more &raquo;</a></p>
+    <p>Get started with a tutorial that walks you through creating a GCM app.
+    <a href="{@docRoot}google/gcm/gs.html">Learn more &raquo;</a></p>
   </div>
 
 </div>
diff --git a/docs/html/google/gcm/notifications.jd b/docs/html/google/gcm/notifications.jd
index 43a7368..2815f3d 100644
--- a/docs/html/google/gcm/notifications.jd
+++ b/docs/html/google/gcm/notifications.jd
@@ -14,8 +14,8 @@
 <h2>In this document</h2>
 
 <ol class="toc">
-  <li><a href="#request">Request Format</a></li>
-  <li><a href="#create">Generate a Notification Key</a></li>
+  <li><a href="#gen-server">Generate a Notification Key on the Server</a></li>
+  <li><a href="#gen-client">Generate a Notification Key on the Client</a></li>
   <li><a href="#add">Add Registration IDs</a></li>
   <li><a href="#remove">Remove Registration IDs</a></li>
   <li><a href="#upstream">Send Upstream Messages</a></li>
@@ -31,15 +31,11 @@
 
 <ol class="toc">
 <li><a href="{@docRoot}google/gcm/gs.html">Getting Started</a></li>
-<li><a href="https://services.google.com/fb/forms/gcm/" class="external-link" target="_android">CCS and User Notifications Signup Form</a></li>
 </ol>
 
 </div>
 </div>
 
-<p class="note"><strong>Note:</strong> To try out this feature, sign up using <a href="https://services.google.com/fb/forms/gcm/">this form</a>.</p>
-
-
 <p>With user notifications, 3rd-party app servers can send a single message to
 multiple instance of an app running on devices owned by a single user. This feature
 is called <em>user notifications</em>. User notifications make it possible for every
@@ -76,27 +72,23 @@
 <p>You can use this feature with either the <a href="ccs.html">XMPP</a> (CCS) or
 <a href="http.html">HTTP</a> connection server.</p>
 
+<p>You can generate notification keys in two different ways: on the server, and on
+the client, if the user has a Google account. All of the associated registration IDs
+can be mapped to a single user.</p>
 
 <p>The examples below show you how to perform generate/add/remove operations,
 and how to send upstream messages. For generate/add/remove operations, the
 message body is JSON.</p>
 
-<h2 id="request">Request Format</h2>
-<p>To send a  message, the application server issues a POST request to
-<code>https://android.googleapis.com/gcm/notification</code>.</p>
+<h2 id="gen-server">Generate a Notification Key on the Server</h2>
 
-<p>Here is the HTTP request header you should use for all create/add/remove operations:</p>
-
-<pre>content-type: "application/json"
-Header : "project_id": &lt;projectID&gt;
-Header: "Authorization", "key=API_KEY"
-</pre>
-
-<h2 id="create">Generate a Notification Key</h2>
+<p>To generate a notification key on the server, you create a new
+create a new <code>notification_key</code> and map it to a
+<code>notification_key_name</code>.</p>
 
 <p>This example shows how to create a new <code>notification_key</code> for a
 <code>notification_key_name</code> called <code>appUser-Chris</code>.
-The {@code notification_key_name} is a name or identifier (can be a username for
+The {@code notification_key_name} is a name or identifier (it can be a username for
 a 3rd-party app) that is unique to a given user. It is used by third parties to
 group together registration IDs for a single user. Note that <code>notification_key_name</code>
 and <code>notification_key</code> are unique to a group of registration IDs. It is also
@@ -116,10 +108,109 @@
    &quot;registration_ids&quot;: [&quot;4&quot;, &quot;8&quot;, &quot;15&quot;, &quot;16&quot;, &quot;23&quot;, &quot;42&quot;]
 }</pre>
 
+<h3 id="request-server">Request format</h3>
+
+<p>To send a message in cases where your notification key is generated on the server,
+the application server issues a POST request to
+<code>https://android.googleapis.com/gcm/notification</code>.</p>
+
+<p>Here is the HTTP request header you should use for all server side create/add/remove operations:</p>
+
+<pre>content-type: "application/json"
+Header : "project_id": &lt;projectID&gt;
+Header: "Authorization", "key=API_KEY"
+</pre>
+
+
+<h2 id="gen-client">Generate a Notification Key on the Client</h2>
+
+<p>Generating a notification key on the client is useful for cases where a server is unavailable.
+To generate a notification key on the client, the device must have at least one
+Google account. Note that the process for generating a notification key on the client is significantly
+different from the server process described above.</p>
+
+<p>To generate a notification key on the client:</p>
+
+<ol>
+  <li>Open your project in the <a href="https://cloud.google.com/console">Google Developers Console</a>.</li>
+  <li>Click <strong>APIS &amp; AUTH &gt; Credentials</strong>.</li>
+  <li>Under OAuth, click <strong>Create new Client ID</strong>.</li>
+  <li>In the <strong>Create Client ID</strong> dialog, select <strong>Web Application</strong> as
+the application type, and click <strong>Create Client ID</strong>.</li>
+  <li>Copy the value from <strong>Client ID for web application &gt; Client ID</strong>.
+This client ID represents a Google account "scope" that you will use to generate an {@code id_token}.</li>
+</ol>
+
+<p>Once you've followed the above steps and gotten a client ID from Google Developers Console,
+ you're ready to add this feature to your app. First check the device for the presence of a Google
+account. For example:</p>
+
+<pre>// This snippet takes the simple approach of using the first returned Google account,
+// but you can pick any Google account on the device.
+public String getAccount() {
+    Account[] accounts = AccountManager.get(getActivity()).
+        getAccountsByType(&quot;com.google&quot;);
+    if (accounts.length == 0) {
+        return null;
+    }
+    return accounts[0].name;
+}</pre>
+
+<p>Next, get an authentication token ({@code id_token}) by using the <code><a href=
+"http://developer.android.com/reference/com/google/android/gms/auth/GoogleAuthUtil.html">GoogleAuthUtil</a></code>
+class. For example:</p>
+
+<pre>String accountName = getAccount();
+
+// Initialize the scope using the client ID you got from the Console.
+final String scope = &quot;audience:server:client_id:&quot;
+        + &quot;1262xxx48712-9qs6n32447mcj9dirtnkyrejt82saa52.apps.googleusercontent.com&quot;;
+String id_token = null;
+try {
+    id_token = GoogleAuthUtil.getToken(context, accountName, scope);
+} catch (Exception e) {
+    log(&quot;exception while getting id_token: &quot; + e);
+}
+...</pre>
+
+<p>Now use <code>id_token</code> to authenticate your request.
+This add operation returns a {@code notification_key}.
+Third parties must save this {@code notification_key} (as well as its mapping to the
+<code>notification_key_name</code>)
+to use in subsequent operations. Note that a client request only takes a single regID.
+The only operations supported on the client side are add/remove.</p>
+
+<pre>request:
+{
+   &quot;operation&quot;: &quot;add&quot;,
+   &quot;notification_key_name&quot;: &quot;appUser-Chris&quot;,
+   &quot;registration_ids&quot;: [&quot;4&quot;]
+   &quot;id_token&quot;: &quot;id_token&quot;
+}</pre>
+
+<h3 id="request-client">Request format</h3>
+
+<p>To send a message in cases where your notification key is generated on the client,
+the application server issues a POST request to
+<code>https://android.googleapis.com/gcm/googlenotification</code>.</p>
+
+<p>Here is the HTTP request header you should use for all add/remove operations. The
+client side doesn't support the create operation;
+the add operation has the effect of creating the notification key if it doesn't already
+exist:</p>
+
+<pre>content-type: "application/json"
+Header : "project_id": &lt;projectID&gt;
+</pre>
+
+<p>Note that the authentication token is passed in the JSON body as shown above, not the header.
+This is different from the server case.</p>
+
+
 <h2 id="add">Add Registration IDs</h2>
 
 <p>This example shows how to add registration IDs for a given notification key.
-The maximum number of members allowed for a {@code notification_key} is 10.</p>
+The maximum number of members allowed for a {@code notification_key} is 20.</p>
 
 <p>Note that the <code>notification_key_name</code> is not strictly required for
 adding/removing regIDs. But including it protects you against accidentally using
diff --git a/docs/html/google/gcm/server.jd b/docs/html/google/gcm/server.jd
index ccd1267..e3a6b25 100644
--- a/docs/html/google/gcm/server.jd
+++ b/docs/html/google/gcm/server.jd
@@ -120,7 +120,8 @@
   <li>Able to store the API key and client registration IDs. The
 API key is included in the header of POST requests that send
 messages.</li>
- <li>Able to generate message IDs to uniquely identify each message it sends.</li>
+ <li>Able to generate message IDs to uniquely identify each message it sends. Message IDs
+should be unique per sender ID.</li>
 </ul>
 
 <h2 id="send-msg">Sending Messages</h2>
diff --git a/docs/html/google/gcs/gcs-signup.jd b/docs/html/google/gcs/gcs-signup.jd
new file mode 100644
index 0000000..7334cec
--- /dev/null
+++ b/docs/html/google/gcs/gcs-signup.jd
@@ -0,0 +1,10 @@
+page.title=Sign Up for Google Cloud Save
+
+@jd:body
+
+<p>Sign up to be a trial partner for Google Cloud Save.</p>
+
+
+<iframe src="https://docs.google.com/a/google.com/forms/d/1_V67YIXzLDLb-UzxOOpSjUDuJFfeYg3hEUT0oliK2ck/viewform?embedded=true" width="100%" height="930" frameborder="0" marginheight="0" marginwidth="0" id="signupform">Loading...</iframe>
+</body>
+</html>
diff --git a/docs/html/google/gcs/index.jd b/docs/html/google/gcs/index.jd
new file mode 100644
index 0000000..e5f4776
--- /dev/null
+++ b/docs/html/google/gcs/index.jd
@@ -0,0 +1,30 @@
+page.title=Google Cloud Save
+page.tags="gcs"
+header.hide=1
+@jd:body
+
+
+<div class="landing-banner">
+
+<div class="col-5" style="min-height:100px">
+  <img src="{@docRoot}images/google/gcs.png" />
+</div>
+<div class="col-7">
+
+  <h1 itemprop="name" style="margin-bottom:0;">Google Cloud Save</h1>
+  <p itemprop="description">
+  Google Cloud Save is a service that enables per-user data storage
+and sync in your apps with no backend programming required. Google Cloud Save
+stores its data
+in <a href="http://developers.google.com/datastore/">Google Cloud Datastore</a>,
+ a fully managed, schemaless database for storing non-relational data. Cloud
+Datastore automatically scales with your users.
+Google Cloud Save works even when your device is offline, and it
+provides an easy transition to server-side coding because
+the same database is accessible via App Engine and Compute Engine.
+Finally, Google Cloud Save provides a generous initial per-user free quota that
+expands as your user base grows.
+</p>
+<a href="{@docRoot}google/gcs/gcs-signup.html" class="button">Sign Up</a>
+</div>
+</div>
diff --git a/docs/html/google/index.jd b/docs/html/google/index.jd
index 2e97d62..4778a85 100644
--- a/docs/html/google/index.jd
+++ b/docs/html/google/index.jd
@@ -89,6 +89,16 @@
     to use Google Cloud Messaging.</p>
 </div>
 
+<div class="landing-cell">
+  <div class="cell-icon">
+  <img src="{@docRoot}images/google/gcs-small.png" width="40" >
+  </div>
+    <h4><a href="{@docRoot}google/gcs/index.html"
+    >Google Cloud Save</a></h4>
+    <p>Enable per-user data storage and sync in your apps with no backend programming
+    required.</p>
+</div>
+
 </div><!-- col-6 -->
 
 
diff --git a/docs/html/guide/practices/verifying-apps-art.jd b/docs/html/guide/practices/verifying-apps-art.jd
index 0eedfaf..8a88222 100644
--- a/docs/html/guide/practices/verifying-apps-art.jd
+++ b/docs/html/guide/practices/verifying-apps-art.jd
@@ -66,7 +66,7 @@
 href="{@docRoot}/tools/debugging/debugging-memory.html#LogMessages"><code>GC_FOR_ALLOC</code></a>-type
 occurrences or to reduce fragmentation. You can verify which runtime is in use
 by calling {@link java.lang.System#getProperty(java.lang.String)
-System.getProperty("dalvik.vm.version")}. If ART is in use, the property's value
+System.getProperty("java.vm.version")}. If ART is in use, the property's value
 is <code>"2.0.0"</code> or higher.</p>
 
 <p>Furthermore, a compacting garbage collector is under development in the <a
diff --git a/docs/html/images/google/datastore-logo.png b/docs/html/images/google/datastore-logo.png
new file mode 100644
index 0000000..a0fc0a0
--- /dev/null
+++ b/docs/html/images/google/datastore-logo.png
Binary files differ
diff --git a/docs/html/images/google/gcs-small.png b/docs/html/images/google/gcs-small.png
new file mode 100644
index 0000000..b8dbe0d
--- /dev/null
+++ b/docs/html/images/google/gcs-small.png
Binary files differ
diff --git a/docs/html/images/google/gcs.png b/docs/html/images/google/gcs.png
new file mode 100644
index 0000000..7355d64
--- /dev/null
+++ b/docs/html/images/google/gcs.png
Binary files differ
diff --git a/docs/html/images/home/auto.png b/docs/html/images/home/auto.png
index 233d69d..7ea01b0 100644
--- a/docs/html/images/home/auto.png
+++ b/docs/html/images/home/auto.png
Binary files differ
diff --git a/docs/html/images/home/tv.png b/docs/html/images/home/tv.png
index 47bf4b0..3cf2034 100644
--- a/docs/html/images/home/tv.png
+++ b/docs/html/images/home/tv.png
Binary files differ
diff --git a/docs/html/images/home/wear.png b/docs/html/images/home/wear.png
index c7a2045..dfaded7 100644
--- a/docs/html/images/home/wear.png
+++ b/docs/html/images/home/wear.png
Binary files differ
diff --git a/docs/html/images/tools/wizard2.png b/docs/html/images/tools/wizard2.png
new file mode 100644
index 0000000..921d58c
--- /dev/null
+++ b/docs/html/images/tools/wizard2.png
Binary files differ
diff --git a/docs/html/images/tools/wizard3.png b/docs/html/images/tools/wizard3.png
new file mode 100644
index 0000000..d5749d5
--- /dev/null
+++ b/docs/html/images/tools/wizard3.png
Binary files differ
diff --git a/docs/html/images/tools/wizard4.png b/docs/html/images/tools/wizard4.png
new file mode 100644
index 0000000..2709f7b
--- /dev/null
+++ b/docs/html/images/tools/wizard4.png
Binary files differ
diff --git a/docs/html/images/tools/wizard5.png b/docs/html/images/tools/wizard5.png
new file mode 100644
index 0000000..105cf2a
--- /dev/null
+++ b/docs/html/images/tools/wizard5.png
Binary files differ
diff --git a/docs/html/images/tools/wizard6.png b/docs/html/images/tools/wizard6.png
new file mode 100644
index 0000000..8b0691c
--- /dev/null
+++ b/docs/html/images/tools/wizard6.png
Binary files differ
diff --git a/docs/html/images/tools/wizard7.png b/docs/html/images/tools/wizard7.png
new file mode 100644
index 0000000..83396cf
--- /dev/null
+++ b/docs/html/images/tools/wizard7.png
Binary files differ
diff --git a/docs/html/index.jd b/docs/html/index.jd
index c2bf6b6..2f01538 100644
--- a/docs/html/index.jd
+++ b/docs/html/index.jd
@@ -7,7 +7,7 @@
 @jd:body
 
 <!-- Top full-bleed carousel -->
-<div class="home-new-carousel-1">
+<div class="home-new-carousel-1" style="margin-top:40px">
   <div class="fullscreen-carousel-content">
     <div class="vcenter">
       <div class="wrap clearfix">
@@ -42,7 +42,7 @@
   </div> <!-- end .fullscreen-carousel-content -->
 </div> <!-- end .fullscreen-carousel -->
 
-<div class="actions-bar">
+<div class="actions-bar" style="margin-top:30px">
   <div class="wrap">
     <div class="actions">
       <div><a href="{@docRoot}sdk/index.html">Get the SDK</a></div>
@@ -68,13 +68,33 @@
       <div class="landing-body" style="margin-top: 80px;">
         <div class="landing-breakout cols">
           <div class="col-3-wide">
-              <a href="{@docRoot}wear/index.html"><img src="{@docRoot}images/home/wear.png"></a>
+              <img src="{@docRoot}images/home/wear.png">
+              <p class="landing-small" style="margin-top:30px">
+                Provide information on-the-go for your users, whenever they need it.
+            </p>
+            <p class="landing-small">
+              <a href="{@docRoot}wear/index.html">Learn about Android Wear</a>
+            </p>
           </div>
           <div class="col-3-wide">            
-              <a href="{@docRoot}tv/index.html"><img src="{@docRoot}images/home/tv.png"></a>
+             <img src="{@docRoot}images/home/tv.png">
+              <p class="landing-small" style="margin-top:30px">
+                Build your apps for the big screen and bring your content to life.
+              </p>
+            <p class="landing-small">
+              <a href="{@docRoot}tv/index.html">Learn about Android TV</a>
+
+            </p>
           </div>
           <div class="col-3-wide">            
-              <a href="{@docRoot}auto/index.html"><img src="{@docRoot}images/home/auto.png"></a>
+              <img src="{@docRoot}images/home/auto.png">
+              <p class="landing-small" style="margin-top:30px">
+                Extend your music apps to automobile
+                entertainment systems.
+             </p>
+            <p class="landing-small">
+              <a href="{@docRoot}auto/index.html">Learn about Android Auto</a>
+            </p>
           </div>
         </div>
       </div>
diff --git a/docs/html/jd_extras.js b/docs/html/jd_extras.js
index eb7bfb6..03bbea1 100644
--- a/docs/html/jd_extras.js
+++ b/docs/html/jd_extras.js
@@ -1172,7 +1172,7 @@
     "tags": [],
     "url": "https://developers.google.com/edu/",
     "timestamp": null,
-    "image": "https://developers.google.com/edu/images/edu-guidelines.jpg",
+    "image": "https://developers.google.com/edu/images/home-android.png",
     "title": "Chrome Apps in Google Play for Education",
     "summary": "Find out more about Chrome apps in Google Play for Education.",
     "keywords": [],
diff --git a/docs/html/jd_tag_helpers.js b/docs/html/jd_tag_helpers.js
index b0fe67a..7538e4d 100644
--- a/docs/html/jd_tag_helpers.js
+++ b/docs/html/jd_tag_helpers.js
@@ -64,6 +64,7 @@
 // Type lookups
 
 var ALL_RESOURCES_BY_TYPE = {
+  'about': ABOUT_RESOURCES,
   'design': DESIGN_RESOURCES,
   'distribute': DISTRIBUTE_RESOURCES,
   'google': GOOGLE_RESOURCES,
@@ -79,6 +80,7 @@
 // Tag lookups
 
 var ALL_RESOURCES_BY_TAG = mergeMaps(
+  {map:ABOUT_BY_TAG,arr:ABOUT_RESOURCES},
   {map:DESIGN_BY_TAG,arr:DESIGN_RESOURCES},
   {map:DISTRIBUTE_BY_TAG,arr:DISTRIBUTE_RESOURCES},
   {map:GOOGLE_BY_TAG,arr:GOOGLE_RESOURCES},
diff --git a/docs/html/preview/api-overview.jd b/docs/html/preview/api-overview.jd
index 284ad2a..f992bf9 100644
--- a/docs/html/preview/api-overview.jd
+++ b/docs/html/preview/api-overview.jd
@@ -18,32 +18,27 @@
       <li><a href="#ART">New Android Runtime (ART)</a></li>
       <li><a href="#BehaviorNotifications">If your app implements notifications...</a></li>
       <li><a href="#BehaviorMediaControl">If your app uses RemoteControlClient...</a></li>
-      <li><a href="#BehaviorGetRecentTasks">If your app uses ActivityManager.getRecentTasks()...</a></li>
+<li><a href="#BehaviorGetRecentTasks">If your app uses ActivityManager.getRecentTasks()...</a></li>
     </ol>
   </li>
   <li><a href="#UI">User Interface</a>
     <ol>
       <li><a href="#MaterialDesign">Material design support</a></li>
-      <li><a href="#DoNotDisturb">Do Not Disturb mode</a></li>
       <li><a href="#LockscreenNotifications">Lockscreen notifications</a></li>
       <li><a href="#NotificationsMetadata">Notifications metadata</a></li>
       <li><a href="#Recents">Concurrent documents and activities in the Recents screen</a></li>
       <li><a href="#WebView">WebView updates</a></li>
     </ol>
   </li>
-  <li><a href="#UserInput">User Input</a>
-    <ol>
-      <li><a href="#IME">IME bug fixes and improvements</a></li>
-    </ol>
-  </li>
-  <li><a href="#Animations">Animation &amp; Graphics</a>
+  <li><a href="#Graphics">Graphics</a>
     <ol>
       <li><a href="#OpenGLES-3-1">Support for OpenGL ES 3.1</a></li>
+      <li><a href="#AndroidExtensionPack">Android Extension Pack</a></li>
     </ol>
   </li>
   <li><a href="#Multimedia">Multimedia</a>
     <ol>
-      <li><a href="#Camera-v2">Camera v2 API</a></li>
+      <li><a href="#Camera-v2">Camera API for advanced camera capabilities</a></li>
       <li><a href="#AudioPlayback">Audio playback</a></li>
       <li><a href="#MediaPlaybackControl">Media playback control</a></li>
     </ol>
@@ -55,7 +50,7 @@
   </li>
   <li><a href="#Wireless">Wireless and Connectivity</a>
     <ol>
-      <li><a href="#Multinetwork">Dynamic network selection and seamless handoff</a></li>
+      <li><a href="#Multinetwork">Multiple network connections</a></li>
       <li><a href="#BluetoothBroadcasting">Bluetooth broadcasting</a></li>
       <li><a href="#NFCEnhancements">NFC enhancements</a></li>
     </ol>
@@ -69,7 +64,7 @@
   <li><a href="#Enterprise">Enterprise</a>
     <ol>
       <li><a href="#ManagedProvisioning">Managed provisioning</a></li>
-      <li><a href="#LockToAppMode">Lock-to-App mode</a></li>
+      <li><a href="#TaskLocking">Task locking</a></li>
     </ol>
   </li>
   <li><a href="#Printing">Printing Framework</a>
@@ -82,20 +77,18 @@
       <li><a href="#TestingA11yImprovements">Testing and accessibility improvements</a></li>
     </ol>
   </li>
+  <li><a href="#IME">IME</a>
+    <ol>
+      <li><a href="#Switching">Easier switching between input languages</a></li>
+    </ol>
+  </li>
   <li><a href="#Manifest">Manifest Declarations</a>
     <ol>
       <li><a href="#ManifestFeatures">Declarable required features</a></li>
-      <li><a href="#ManifestPermissions">User permissions</a></li>
     </ol>
   </li>
 </ol>
 
-<h2>See also</h2>
-<ol>
-<li><a href="{@docRoot}sdk/api_diff/20/changes.html">API
-Differences Report &raquo;</a> </li>
-</ol>
-
 </div>
 </div>
 
@@ -163,10 +156,10 @@
 backgrounds to match the new material design widgets. Make sure that all your
 notifications look right with the new color scheme:</p>
 
-<div class="figure" style="width:220px">
+<div class="figure" style="width:320px">
   <img src="images/hun-example.png"
     srcset="images/hun-example@2x.png 2x"
-    alt="" width="220" height="372" id="figure1" />
+    alt="" width="320" height="541" id="figure1" />
   <p class="img-caption">
     <strong>Figure 1.</strong> Fullscreen activity showing a heads-up notification
   </p>
@@ -177,7 +170,7 @@
   <li>Update or remove assets that involve color.</li>
 
   <li>The system automatically inverts action icons in notifications. Use
-  {@code android.app.Notification.Builder.setColor()} to set an accent color
+  {@code android.app.Notification. Builder.setColor()} to set an accent color
   in a circle behind your {@link android.app.Notification#icon} image.</li>
 
   <li>The system ignores all non-alpha channels in action icons and the main
@@ -188,7 +181,9 @@
 <p>If you are currently adding sounds and vibrations to your notifications by
 using the {@link android.media.Ringtone}, {@link android.media.MediaPlayer},
 or {@link android.os.Vibrator} classes, remove this code so that
-the system can present notifications correctly in <a href="#DoNotDisturb">Do Not Disturb</a> mode. Instead, use the {@link android.app.Notification.Builder} methods instead to add sounds and vibration.</p>
+the system can present notifications correctly in Do
+not Disturb mode. Instead, use the {@link android.app.Notification.Builder}
+methods instead to add sounds and vibration.</p>
 
 <p>Notifications now appear in a small floating window
 (also called a <em>heads-up notification</em>) when the device is active
@@ -218,40 +213,46 @@
 providing a consistent experience for users across the lockscreen and
 unlocked device.</p>
 
-<p>The L Developer Preview introduces a new {@code android.app.Notification.MediaStyle} template which is recommended for this purpose. {@code MediaStyle} converts notification actions that you added with {@link android.app.Notification.Builder#addAction(int, java.lang.CharSequence, android.app.PendingIntent) Notification.Builder.addAction()} into compact buttons embedded in your app's media playback notifications.</p>
+<p>The L Developer Preview introduces a new
+{@code android.app.Notification.MediaStyle} template which is recommended for
+this purpose. {@code MediaStyle} converts notification actions that you added
+with
+{@link android.app.Notification.Builder#addAction(int, java.lang.CharSequence,
+  android.app.PendingIntent)
+Notification.Builder.addAction()} into compact buttons embedded in your app's
+media playback notifications.</p>
 
 <p>If you are using the new
-{@code android.media.session.MediaSession} class (see <a href="#MediaPlaybackControl">Media Playback Control</a> below), attach your session
-token with {@code Notification.MediaStyle.setMediaToken()} to inform the
-system that this notification controls an ongoing media session.</p>
+{@code android.media.session.MediaSession} class
+(see <a href="#MediaPlaybackControl">Media Playback Control</a> below), attach
+your session token with {@code Notification.MediaStyle.setMediaToken()} to
+inform the system that this notification controls an ongoing media session.</p>
 
 <p>Call {@code
 Notification.Builder.setVisibility(Notification.VISIBILITY_PUBLIC)} to mark a
-notification as safe to show atop any lockscreen (secure or otherwise). For more information, see
-<a href="#LockscreenNotifications">Lockscreen Notifications</a>.</p>
+notification as safe to show atop any lockscreen (secure or otherwise). For more
+information, see <a href="#LockscreenNotifications">Lockscreen Notifications</a>.</p>
 
 <h3 id="BehaviorGetRecentTasks">If your app uses ActivityManager.getRecentTasks()...</h3>
 
-<p>With the introduction of the new <em>concurrent documents and activities tasks</em> feature in the upcoming
-release (see <a href="#Recents">Concurrent documents and activities in Recents
-screen</a> below),
+<p>With the introduction of the new <em>concurrent documents and activities
+tasks</em> feature in the upcoming release (see <a href="#Recents">Concurrent
+documents and activities in Recents screen</a> below),
 the {@link android.app.ActivityManager#getRecentTasks
-ActivityManager.getRecentTasks()} method is now
-deprecated to improve user privacy. For backward
-compatibility, this method still returns a small subset of its data, including the
-calling application’s own tasks and possibly some other non-sensitive tasks
-(such as Home). If your app is using this method to retrieve its own tasks,
-use {@code android.app.ActivityManager.getAppTasks()} instead to retrieve that
-information.</p>
+ActivityManager.getRecentTasks()} method is now deprecated to improve user
+privacy. For backward compatibility, this method still returns a small subset of
+its data, including the calling application’s own tasks and possibly some other
+non-sensitive tasks (such as Home). If your app is using this method to retrieve
+its own tasks, use {@code android.app.ActivityManager.getAppTasks()} instead to
+retrieve that information.</p>
 
 <h2 id="UI">User Interface</h2>
 
 <h3 id="MaterialDesign">Material design support</h3>
 
 <p>The upcoming release adds support for Android's new <em>material</em> design
-style. You can create
-apps with material design that are visually dynamic and have UI element transitions
-that feel natural to users. This support includes:</p>
+style. You can create apps with material design that are visually dynamic and
+have UI element transitions that feel natural to users. This support includes:</p>
 
 <ul>
 
@@ -268,9 +269,9 @@
 <a href="{@docRoot}preview/material/index.html">Material Design</a>.</p>
 
 <h3 id="LockscreenNotifications">Lockscreen notifications</h3>
-<p>Lockscreens in the L Developer Preview have the ability to present notifications.
-Users can choose via <em>Settings</em> whether to allow sensitive notification
-content to be shown over a secure lockscreen.</p>
+<p>Lockscreens in the L Developer Preview have the ability to present
+notifications. Users can choose via <em>Settings</em> whether to allow
+sensitive notification content to be shown over a secure lockscreen.</p>
 
 <p>Your app can control the level of detail visible when its notifications are
 displayed over the secure lockscreen. To control the visibility level, call
@@ -287,46 +288,23 @@
 
 <p>When {@code VISIBILITY_PRIVATE} is set, you can also provide a redacted
 version of the notification content that hides personal details. For example,
-an SMS app might display a notification that shows "You have 3 new text messages." but hides the message content and senders. To provide this alternative notification, first create the replacement notification using {@link android.app.Notification.Builder}. When you create the private notification object, attach
-the replacement notification to it through the {@code Notification.Builder.setPublicVersion()} method.</p>
-
-<h3 id="DoNotDisturb">Do Not Disturb mode</h3>
-
-<p>The L Developer Preview introduces a new <em>Do Not Disturb</em> mode. When
-the user puts the device in <em>Do Not Disturb</em> mode, the device limits
-the frequency of the notifications it shows the user (when the user
-wants to avoid distractions). The user can
-customize the feature in a number of ways, such as:</p>
-
-<ul>
-  <li>Specifying important people, whose calls should go through even when
-    the device is in <em>Do Not Disturb</em> mode.</li>
-  <li>Setting custom categories to allow notifications when the device is in
-    <em>Do Not Disturb</em> mode. Examples of such categories include phone
-    calls and direct communications (like Hangouts and Skype calls).</li>
-  <li>Setting rules so <em>Do Not Disturb</em> automatically goes into effect in
-    certain conditions (like at particular times of day).</li>
-</ul>
-
-<p>You should add the appropriate metadata to your app notifications to help
-make sure <em>Do Not Disturb</em> mode handles them properly. For example, if
-your app is an alarm clock,
-you can tag the notification as an alarm so it will wake the user up even if the
-device is in <em>Do Not Disturb</em> mode. For more information, see <a
-href="#NotificationsMetadata">Notifications metadata</a>.</p>
+an SMS app might display a notification that shows "You have 3 new text messages."
+but hides the message content and senders. To provide this alternative
+notification, first create the replacement notification using
+{@link android.app.Notification.Builder}. When you create the private
+notification object, attach the replacement notification to it through the
+{@code Notification.Builder.setPublicVersion()} method.</p>
 
 <h3 id="NotificationsMetadata">Notifications metadata</h3>
 <p>The L Developer Preview uses metadata associated with your app notifications
-to sort the notifications more intelligently. The metadata you set also
-controls how the system presents your app notifications when the user is in <em>Do
-Not Disturb</em> mode. To set the metadata, call the following methods in
-{@code android.app.Notification.Builder} when you construct the
-notification:</p>
+to sort the notifications more intelligently. To set the metadata, call the
+following methods in {@code android.app.Notification.Builder} when you
+construct the notification:</p>
 
 <ul>
 <li>{@code setCategory()}. Depending on the message category, this tells
 the system how to handle your app notifications when the device is
-in <em>Do Not Disturb</em> mode (for example, if your notification represents an
+in <em>Do not Disturb</em> mode (for example, if your notification represents an
 incoming call, instant message, or alarm).
 <li>{@code setPriority()}. Notifications with the priority field set to
 {@code PRIORITY_MAX} or {@code PRIORITY_HIGH} will appear in a small floating
@@ -342,11 +320,11 @@
 <p>In previous releases, the
 <a href="{@docRoot}design/get-started/ui-overview.html">Recents screen</a>
 could only display a single task for each app that the user interacted with
-most recently. The L Developer Preview enables your app to open more tasks as
+most recently. Now your app can open more tasks as
 needed for additional concurrent activities for documents.
-This feature facilitates multitasking
-by letting users quickly switch between individual activities and documents
-from the Recents screen, with a consistent switching experience across all apps.
+This feature facilitates multitasking by letting users quickly switch between
+individual activities and documents from the Recents screen, with a consistent
+switching experience across all apps.
 Examples of such concurrent tasks might include open tabs in a web
 browser app, documents in a productivity app, concurrent matches in
 a game, or chats in a messaging app. Your app can manage its tasks
@@ -354,7 +332,8 @@
 
 <p>To insert a logical break so that the system treats your activity as a new
 task, use {@code android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT} when
-launching the activity with {@link android.app.Activity#startActivity(android.content.Intent) startActivity()}. You can also get this behavior by declaring the
+launching the activity with {@link android.app.Activity#startActivity(android.content.Intent)
+startActivity()}. You can also get this behavior by declaring the
 <a href="{@docRoot}guide/topics/manifest/activity-element.html">&lt;activity&gt;</a>
 attribute {@code documentLaunchMode="intoExisting"} or {@code ="always"} in your
 manifest.</p>
@@ -381,34 +360,12 @@
 been updated to incorporate 36.0.0.0 as the version number.</p>
 
 <p>Additionally, this release brings support for the
-<a href="https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html">WebAudio</a>, <a href="https://www.khronos.org/webgl/">WebGL</a>, and
-<a href="http://www.webrtc.org/">WebRTC</a> open standards. To learn more about
-the new features included in this release, see <a href="https://developer.chrome.com/multidevice/webview/overview">WebView for Android</a>.</p>
+<a href="http://webaudio.github.io/web-audio-api/" class="external-link">WebAudio</a>,
+<a href="https://www.khronos.org/webgl/" class="external-link">WebGL</a>, and
+<a href="http://www.webrtc.org/" class="external-link">WebRTC</a> open standards. To learn more about
+the new features included in this release, see <a href="https://developer.chrome.com/multidevice/webview/overview" class="external-link">WebView for Android</a>.</p>
 
-<h2 id="UserInput">User Input</h2>
-
-<h3 id="IME">IME bug fixes and improvements</h3>
-
-<p>Beginning in the L Developer Preview, users can more easily switch between
-all <a href="{@docRoot}guide/topics/text/creating-input-method.html">input
-method editors (IME)</a> supported by the platform. Performing the designated
-switching action (usually touching a Globe icon on the soft keyboard) will cycle
-among all such IMEs. This change takes place in
-{@link android.view.inputmethod.InputMethodManager#shouldOfferSwitchingToNextInputMethod
-InputMethodManager.shouldOfferSwitchingToNextInputMethod()}.</p>
-
-<p>In addition, the framework now checks whether the next IME includes a
-switching mechanism at all (and, thus, whether that IME supports switching to
-the IME after it). An
-IME with a switching mechanism will not cycle to an IME without one. This
-change takes place in
-{@link android.view.inputmethod.InputMethodManager#switchToNextInputMethod
-InputMethodManager.switchToNextInputMethod}.
-
-<p>To see an example of how to use the updated IME-switching APIs, refer to the
-updated soft-keyboard implementation sample in this release.</p>
-
-<h2 id="Animations">Animation &amp; Graphics</h2>
+<h2 id="Graphics">Graphics</h2>
 
 <h3 id="OpenGLES-3-1">Support for OpenGL ES 3.1</h3>
 <p>The L Developer Preview adds Java interfaces and native support for OpenGL
@@ -418,14 +375,16 @@
 <li>Compute shaders
 <li>Separate shader objects
 <li>Indirect draw commands
-<li>Enhanced texturing functionality
+<li>Multisample and stencil textures
 <li>Shading language improvements
-<li>Optional extensions for per-sample shading, advanced blending modes, and more
+<li>Extensions for advanced blend modes and debugging
 <li>Backward compatibility with OpenGL ES 2.0 and 3.0
 </ul>
 
-<p>The Java interface for OpenGL ES 3.1 on Android is provided with GLES31. When using OpenGL ES 3.1, be sure that you declare it in your manifest file with the
-<a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code &lt;uses-feature&gt;}</a> tag and the {@code android:glEsVversion} attribute. For example:</p>
+<p>The Java interface for OpenGL ES 3.1 on Android is provided with {@code GLES31}. When
+using OpenGL ES 3.1, be sure that you declare it in your manifest file with the
+<a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code &lt;uses-feature&gt;}</a>
+tag and the {@code android:glEsVversion} attribute. For example:</p>
 
 <pre>
 &lt;manifest&gt;
@@ -434,11 +393,36 @@
 &lt;/manifest&gt;
 </pre>
 
-<p>For more information about using OpenGL ES, including how to check the device’s supported OpenGL ES version at runtime, see the <a href="{@docRoot}guide/topics/graphics/opengl.html">OpenGL ES API guide</a>.</p>
+<p>For more information about using OpenGL ES, including how to check the
+device’s supported OpenGL ES version at runtime, see the
+<a href="{@docRoot}guide/topics/graphics/opengl.html">OpenGL ES API guide</a>.</p>
+
+<h3 id="AndroidExtensionPack">Android Extension Pack</h3>
+
+<p>In addition to OpenGL ES 3.1, this release provides an extension pack with Java interfaces and
+native support for advanced graphics functionality. These extensions are treated as a single
+package by Android. (If the {@code ANDROID_extension_pack_es31} extension is present, your app can
+assume all extensions in the package are present and enable the shading language features with
+a single {@code #extension} statement.</p>
+<p>The extension pack supports:</p>
+<ul>
+<li>Guaranteed fragment shader support for shader storage buffers, images, and
+  atomics (fragment shader support is optional in OpenGL ES 3.1.)</li>
+<li>Tessellation and geometry shaders</li>
+<li>ASTC (LDR) texture compression format</li>
+<li>Per-sample interpolation and shading</li>
+<li>Different blend modes for each color attachment in a frame buffer</li>
+</ul>
+
+<p>The Java interface for the extension pack is provided with {@code GLES31Ext}.
+In your app manifest, you can declare that support for the extension pack is
+required, with the
+<a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code &lt;uses-feature&gt;}</a>
+tag, but the precise syntax is not finalized in the L Developer Preview.</p>
 
 <h2 id="Multimedia">Multimedia</h2>
 
-<h3 id="Camera-v2">Camera v2 API</h3>
+<h3 id="Camera-v2">Camera API for advanced camera capabilities</h3>
 
 <p>The L Developer Preview introduces the new {@code android.hardware.camera2}
 API to facilitate fine-grain photo capture and image processing. You can now
@@ -456,18 +440,22 @@
 {@code onCaptureCompleted()}, providing you with the image capture metadata in a
 {@code CaptureResult}.</p>
 
+<p>To see an example of how to use the updated Camera API, refer to the {@code Camera2Basic}
+and {@code Camera2Video} implementation samples in this release.</p>
+
 <h3 id="AudioPlayback">Audio playback</h3>
 <p>This release includes the following changes to
   {@link android.media.AudioTrack}:</p>
 <ul>
   <li>Your app can now supply audio data in floating-point format
 ({@code android.media.AudioFormat.ENCODING_PCM_FLOAT}). This permits greater
-dynamic range, more consistent precision, and greater headroom. Floating-point arithmetic is especially useful during intermediate calculations. Playback
+dynamic range, more consistent precision, and greater headroom. Floating-point
+arithmetic is especially useful during intermediate calculations. Playback
 end-points use integer format for audio data, and with lower bit-depth. (In the
 L Developer Preview, portions of the internal pipeline are not yet
 floating-point.)
-  <li>Your app can now supply audio data as a {@link java.nio.ByteBuffer}, in the same
-format as provided by {@link android.media.MediaCodec}.
+  <li>Your app can now supply audio data as a {@link java.nio.ByteBuffer}, in
+the same format as provided by {@link android.media.MediaCodec}.
   <li>The {@code WRITE_NON_BLOCKING} option can simplify buffering and
     multithreading for some apps.
 </ul>
@@ -501,37 +489,44 @@
 
 <h3 id="DirectorySelection">Directory selection</h3>
 
-<p>The L Developer Preview extends the <a href="{@docRoot}guide/topics/providers/document-provider.html">Storage Access Framework</a> to let users select an entire directory, rather than individual files, to
-give your app read/write access to media files. When a directory is selected,
-your app also has access to all its child directories and content.</p>
+<p>The L Developer Preview extends the <a href="{@docRoot}guide/topics/providers/document-provider.html">Storage Access Framework</a> to let users select an entire directory subtree,
+giving apps read/write access to all contained documents without requiring user
+confirmation for each item.</p>
 
-<p>To get the absolute paths to directories on external storage devices where
-applications can store media files, call the new
-{@code android.content.Context.getExternalMediaDirs()} method. No
-additional
-permissions are needed by your app to read or write to the returned paths.
-In this context, "external storage devices" are those devices which the system
-considers to be a
-permanent part of the device, and includes emulated external storage and
-physical media slots such as SD cards in battery compartments.</p>
+<p>To select a directory subtree, build and send an
+{@code android.intent.action.OPEN_DOCUMENT_TREE} {@link android.content.Intent}.
+The system displays all
+{@link android.provider.DocumentsProvider} instances that support subtree selection,
+letting the user browse and select a directory. The returned URI represents access to the selected
+subtree. You can then use {@code DocumentsContract.buildChildDocumentsUriUsingTree()}
+and {@code DocumentsContract.buildDocumentUriUsingTree()} along with
+{@code ContentResolver.query()} to explore the subtree.</p>
 
-<p>You can bring up a system UI to allow the user to pick a directory subtree.
-To do so, send  {@code android.intent.action.OPEN_DOCUMENT_TREE} in an
-{@link android.content.Intent}. If the call is successful, the system displays
-the {@link android.provider.DocumentsProvider} instances installed on the
-device for the user to select. When the user selects a directory from this UI,
-the system returns a URI representing the selected directory tree.</p>
+<p>The new {@code DocumentsContract.createDocument()} method lets you create
+new documents or directories anywhere under the subtree. To manage
+existing documents, use {@code DocumentsContract.renameDocument()} and
+{@code DocumentsContract.deleteDocument()}. Check {@code DocumentsContract.Document.COLUMN_FLAGS}
+to verify provider support for these calls before issuing them.</p>
 
-<p>If you want to access a document in an existing directory, call the
-{@code android.provider.DocumentsContract.buildDocumentViaUri()} method.
-Pass the method a URI representing the path to the parent directory, and the
-target document
-ID. The method returns a new {@link android.net.Uri} which your app can
-use to write media content with {@code DocumentsContract.createDocument()}.
+<p>If you're implementing a {@link android.provider.DocumentsProvider} and want
+to support subtree selection, implement {@code DocumentsProvider.isChildDocument()}
+and include {@code Documents.Contract.FLAG_SUPPORTS_IS_CHILD} in your
+{@code Root.COLUMN_FLAGS}.</p>
+
+<p>The L Developer Preview also introduces new package-specific directories on
+shared storage where your app can place media files for inclusion in
+{@link android.provider.MediaStore}. The new
+{@code android.content.Context.getExternalMediaDirs()} returns paths to these
+directories on all shared storage devices. Similarly to
+{@link android.content.Context#getExternalFilesDir(java.lang.String) Context.getExternalFilesDir()},
+no additional permissions are needed by your app to access the returned paths. The
+platform periodically scans for new media in these directories, but you can also
+use {@link android.media.MediaScannerConnection} to explicitly scan for new
+content.</p>
 
 <h2 id="Wireless">Wireless &amp; Connectivity</h2>
 
-<h3 id="Multinetwork">Dynamic network selection and seamless handoff</h3>
+<h3 id="Multinetwork">Multiple network connections</h3>
 <p>The L Developer Preview provides new multi-networking APIs. These let your app
 dynamically scan for available networks with specific capabilities, and
 establish a connection to them. This is useful when your app requires a
@@ -561,7 +556,8 @@
 network.</p>
 
 <h3 id="BluetoothBroadcasting">Bluetooth broadcasting</h3>
-<p>Android 4.3 introduced platform support for <a href="{@docRoot}guide/topics/connectivity/bluetooth-le.html">Bluetooth Low Energy</a>
+<p>Android 4.3 introduced platform support for
+  <a href="{@docRoot}guide/topics/connectivity/bluetooth-le.html">Bluetooth Low Energy</a>
 (BLE) in the central role. In the L Developer Preview, an Android device can now
 act as a Bluetooth LE <em>peripheral device</em>. Apps can use this capability
 to make their presence known to
@@ -569,7 +565,8 @@
 function as a pedometer or health monitor and communicate its data with another
 BLE device.</p>
 
-<p>The new {@code android.bluetooth.le} APIs enable your apps to broadcast advertisements, scan for responses, and form connections with nearby BLE devices.
+<p>The new {@code android.bluetooth.le} APIs enable your apps to broadcast
+advertisements, scan for responses, and form connections with nearby BLE devices.
 You must add the {@code android.permission.BLUETOOTH_ADMIN} permission in your
 manifest in order for your app to use the new advertising and scanning features.</a>
 
@@ -652,6 +649,9 @@
 jobScheduler.schedule(uploadTask);
 </pre>
 
+<p>To see an example of how to use the {@code JobScheduler} API, refer to the
+{@code JobSchedulerSample} implementation sample in this release.</p>
+
 <h3 id="PowerMeasurementTools">Developer tools for power measurement</h3>
 <p>The L Developer Preview provides several new developer tools and APIs to help
 you better measure and understand your app's power usage.</p>
@@ -692,7 +692,7 @@
 
 <img src="images/battery_historian.png"
      srcset="images/battery_historian@2x.png 2x"
-    alt="" width="440" height="240"
+    alt="" width="760" height="462"
     id="figure2" />
 <p class="img-caption">
   <strong>Figure 2.</strong>HTML visualization generated by the Battery
@@ -726,7 +726,7 @@
 <div class="figure" style="width:360px">
   <img src="images/managed_apps_launcher.png"
     srcset="images/managed_apps_launcher@2x.png 2x"
-    alt="" width="360" height="572" id="figure3" />
+    alt="" width="360" height="609" id="figure3" />
   <p class="img-caption">
     <strong>Figure 3.</strong> Launcher screen showing managed apps (marked with
     a lock badge)
@@ -734,80 +734,93 @@
 </div>
 
 <p>The L Developer Preview provides new functionality for running apps within
-an enterprise environment:</p>
-<ul>
-<li><strong>Create managed user profiles</strong>. A device administrator can
-initiate a managed provisioning process to add a co-present but separate managed
-profile to a device with an existing personal account. The administrator has
-control over the managed profile.</li>
-<li><strong>Set device owner</strong>. Device administrators can also initiate a
-managed provisioning process to automatically provision a
-currently-unprovisioned device such that they have full control over the
-device.</li>
-</ul>
+an enterprise environment. A
+<a href="{@docRoot}guide/topics/admin/device-admin.html">device administrator</a> can
+initiate a managed provisioning process to add a co-present but separate <em>managed profile</em> to a device, if the user has an existing personal account.
+Apps that are associated with managed profiles will appear alongside
+non-managed apps in the user’s Launcher, Recent apps screen, and notifications.</p>
 
 <p>To start the managed provisioning process, send {@code
 ACTION_PROVISION_MANAGED_PROFILE} in an {@link android.content.Intent}. If the
 call is successful, the system triggers the {@code
 android.app.admin.DeviceAdminReceiver. onProfileProvisioningComplete()} callback.
 You can then call {@code app.admin.DevicePolicyManager. setProfileEnabled()} to
-set this profile to the enabled state.</p>
-
-<p>A user may be associated with more than one managed profile. To get a list of
-the managed profiles associated with the user, call
-{@code android.os.UserManager. getUserProfiles()}.</p>
-
-<p>Once a managed profile is created for a user, apps that are managed by the
-device administrator will appear alongside non-managed apps in the user’s
-Launcher, Recent apps screen, and notifications.</p>
+enable this managed profile.</p>
 
 <p>If you are developing a Launcher app, you can use the new {@code
 android.content.pm.LauncherApps} class to get a list of launchable activities
 for the current user and any associated managed profiles. Your Launcher can make
 the managed apps visually prominent by appending a “work” badge to the icon
-drawable with {@code android.os.UserManager.getBadgeDrawableForUser()}.</p>
+drawable with {@code android.os.UserManager. getBadgeDrawableForUser()}.</p>
 
-<h3 id="LockToAppMode">Lock-to-App mode</h3>
-<p>The L Developer Preview introduces a new <em>Lock-to-App</em> mode that
+<p>To see an example of how to use the new functionality, refer to the
+{@code BasicManagedProfile} implementation sample in this release.</p>
+
+<h3 id="TaskLocking">Task locking</h3>
+<p>The L Developer Preview introduces a new task locking API that
 lets you temporarily restrict users from leaving your app or being interrupted
-by notifications. Once your app activates this mode, users will not be able to
-see notifications, access other apps, or return to the Home screen, until your
+by notifications. This could be used, for example, if you are developing an
+education app to support high stakes assessment requirements on Android.
+Once your app activates this mode, users will not be able to see
+notifications, access other apps, or return to the Home screen, until your
 app exits the mode.</p>
 
-<p>To prevent unauthorized usage, the device on which you want to activate
-this mode must have managed profiles or must be fully controlled by a device administrator (see <a href="#ManagedProvisioning">Managed Provisioning</a> for more information). Furthermore, the device or managed profile owner must
-authorize apps to use this mode by calling {@code android.app.admin.DevicePolicyManager.setLockTaskComponents()}.</p>
+<p>To prevent unauthorized usage, only authorized apps can activate task locking.
+Furthermore, task locking authorization must be granted by a
+specially-configured <em>device owner</em> app, through the {@code android.app.admin.DevicePolicyManager.setLockTaskComponents()} method.</p>
 
-<p>Before activating this mode in your app, verify that your activity is authorized by calling {@code DevicePolicyManager.isLockTaskPermitted()}.</p>
+<p>To set up a device owner, follow these steps:</p>
+<ol>
+<li>Attach a device running an Android <a href="https://source.android.com/source/building-running.html" class="external-link">{@code userdebug}</a> build to your development machine.</li>
+<li>Install your device owner app.</li>
+<li>Create a {@code device_owner.xml} file and save it to the {@code /data/system}
+directory on the device.
+<pre>
+$ adb root
+$ adb shell stop
+$ rm /tmp/device_owner.xml
+$ echo "&lt;?xml version='1.0' encoding='utf-8' standalone='yes' ?&gt;"
+&gt;&gt; /tmp/device_owner.xml
+$ echo "&device-owner package=\"&lt;your_device_owner_package&gt;\"
+name=\"*&lt;your_organization_name&gt;\" /&gt;" &gt;&gt; /tmp/device_owner.xml
+$ adb push /tmp/device_owner.xml /data/system/device_owner.xml
+$ adb reboot
+</pre>
+</li>
+</ol>
 
-<p>To activate <em>Lock-to-App</em> mode, call
+<p>Before using the task locking API in your app, verify that your activity is
+authorized by calling {@code DevicePolicyManager.isLockTaskPermitted()}.</p>
+
+<p>To activate task locking, call
 {@code android.app.Activity.startLockTask()} from your authorized activity.</p>
 
-<p>When <em>Lock-to-App</em> mode is active, the following behavior takes
-effect:</p>
+<p>When task locking is active, the following behavior takes effect:</p>
 
 <ul>
-<li>The status bar is blank, and user notifications and status information is hidden.</li>
-<li>The Home and Recent Apps button is hidden.</li>
+<li>The status bar is blank, and user notifications and status information is
+hidden.</li>
+<li>The Home and Recent Apps buttons are hidden.</li>
 <li>Other apps may not launch new activities.</li>
 <li>The current app may start new activities, as long as doing so does not
 create new tasks.</li>
+<li>The user remains locked on your app until an authorized activity calls
+{@code Activity.stopLockTask()}.</li>
 </ul>
 
-<p>The device will remain in this mode until an authorized activity calls
-{@code Activity.stopLockTask()}.
-
 <h2 id="Printing">Printing Framework</h2>
 
 <h3 id="PDFRender">Render PDF as bitmap</h3>
 <p>You can now render PDF document pages into bitmap images for printing by
 using the new {@code android.graphics.pdf.PdfRenderer} class. You must specify a
-{@link android.os.ParcelFileDescriptor} that is seekable (that is, the content can be randomly
-accessed) on which the system writes the the printable content. Your app can
-obtain a page for rendering with {@code openPage()}, then call {@code render()}
-to turn the opened {@code PdfRenderer.Page} into a bitmap. You can also set
-additional parameters if you only want to convert a portion of the document into
-a bitmap image (for example, to implement <a href="http://en.wikipedia.org/wiki/Tiled_rendering">tiled rendering</a> in order to zoom in on the document).</p>
+{@link android.os.ParcelFileDescriptor} that is seekable (that is, the content
+can be randomly accessed) on which the system writes the the printable content.
+Your app can obtain a page for rendering with {@code openPage()}, then call
+{@code render()} to turn the opened {@code PdfRenderer.Page} into a bitmap. You
+can also set additional parameters if you only want to convert a portion of the
+document into a bitmap image (for example, to implement
+<a href="http://en.wikipedia.org/wiki/Tiled_rendering" class="external-link">tiled rendering</a> in
+order to zoom in on the document).</p>
 
 <h2 id="TestingA11y">Testing &amp; Accessibility </h2>
 
@@ -833,8 +846,7 @@
 can now retrieve detailed information about the properties of windows on the
 screen that sighted users can interact with. To retrieve a list of
 {@code android.view.accessibility.AccessibilityWindowInfo} objects
-representing the
-windows information, call the new
+representing the windows information, call the new
 {@code android.accessibilityservice.AccessibilityService.getWindows()} method.
 <li>You can use the new {@code android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction} to define standard or customized
 actions to perform on an {@link android.view.accessibility.AccessibilityNodeInfo}.
@@ -842,16 +854,42 @@
 previously found in {@code AccessibilityNodeInfo}.
 </ul>
 
+<h2 id="IME">IME</h2>
+
+<h3 id="Switching">Easier switching between input languages</h3>
+
+<p>Beginning in the L Developer Preview, users can more easily switch between
+all <a href="{@docRoot}guide/topics/text/creating-input-method.html">input
+method editors (IME)</a> supported by the platform. Performing the designated
+switching action (usually touching a Globe icon on the soft keyboard) will cycle
+among all such IMEs. This change takes place in
+{@link android.view.inputmethod.InputMethodManager#shouldOfferSwitchingToNextInputMethod
+InputMethodManager.shouldOfferSwitchingToNextInputMethod()}.</p>
+
+<p>In addition, the framework now checks whether the next IME includes a
+switching mechanism at all (and, thus, whether that IME supports switching to
+the IME after it). An
+IME with a switching mechanism will not cycle to an IME without one. This
+change takes place in
+{@link android.view.inputmethod.InputMethodManager#switchToNextInputMethod
+InputMethodManager.switchToNextInputMethod}.
+
+<p>To see an example of how to use the updated IME-switching APIs, refer to the
+updated soft-keyboard implementation sample in this release.</p>
+
 <h2 id="Manifest">Manifest Declarations</h2>
 
 <h3 id="ManifestFeatures">Declarable required features</h3>
-<p>The following values are now supported in the <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code &lt;uses-feature&gt;}</a> element, so you
-can ensure that your app is installed only on devices that provide the features
+<p>The following values are now supported in the
+<a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">{@code &lt;uses-feature&gt;}</a>
+element, so you can ensure that your app is installed only on devices that provide the features
 your app needs.</p>
 
 <ul>
 <li>{@code FEATURE_LEANBACK}. Declares that your app must be installed only on
-devices that support the <a href="{@docRoot}training/tv/index.html}">Android TV</a>user interface. Example:
+devices that support the
+<a href="{@docRoot}training/tv/index.html">Android TV</a> user interface.
+Example:
 <pre>
 &lt;uses-feature android:name="android.software.leanback"
               android:required="true" /&gt;
@@ -865,11 +903,5 @@
 </pre>
 </ul>
 
-<h3 id="ManifestPermissions">User permissions</h3>
-<p>The following values are now supported in the <a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">{@code &lt;uses-permission&gt;}</a> to declare the
-permissions your app requires in order to access certain APIs.
-
-<ul>
-<li>{@code SIM_COMMUNICATION}. Required to communicate with a SIM card using
-  logical channels.
-</ul>
+<p class="note">For a detailed view of all API changes in the L Developer Preview, see the
+<a href="{@docRoot}preview/reference.html">API Differences Report</a>.</p>
diff --git a/docs/html/preview/images/ActivitySceneTransitionBasic.png b/docs/html/preview/images/ActivitySceneTransitionBasic.png
new file mode 100644
index 0000000..ea58641
--- /dev/null
+++ b/docs/html/preview/images/ActivitySceneTransitionBasic.png
Binary files differ
diff --git a/docs/html/preview/images/ActivitySceneTransitionBasic@2x.png b/docs/html/preview/images/ActivitySceneTransitionBasic@2x.png
new file mode 100644
index 0000000..cd28ade
--- /dev/null
+++ b/docs/html/preview/images/ActivitySceneTransitionBasic@2x.png
Binary files differ
diff --git a/docs/html/preview/images/BasicManagedProfile.png b/docs/html/preview/images/BasicManagedProfile.png
new file mode 100644
index 0000000..7354842
--- /dev/null
+++ b/docs/html/preview/images/BasicManagedProfile.png
Binary files differ
diff --git a/docs/html/preview/images/BasicManagedProfile@2x.png b/docs/html/preview/images/BasicManagedProfile@2x.png
new file mode 100644
index 0000000..c232809
--- /dev/null
+++ b/docs/html/preview/images/BasicManagedProfile@2x.png
Binary files differ
diff --git a/docs/html/preview/images/JobSchedulerSample.png b/docs/html/preview/images/JobSchedulerSample.png
new file mode 100644
index 0000000..ee57bdb
--- /dev/null
+++ b/docs/html/preview/images/JobSchedulerSample.png
Binary files differ
diff --git a/docs/html/preview/images/JobSchedulerSample@2x.png b/docs/html/preview/images/JobSchedulerSample@2x.png
new file mode 100644
index 0000000..3d543db
--- /dev/null
+++ b/docs/html/preview/images/JobSchedulerSample@2x.png
Binary files differ
diff --git a/docs/html/preview/images/battery_historian.png b/docs/html/preview/images/battery_historian.png
index 5b0db74..f1d4e40 100644
--- a/docs/html/preview/images/battery_historian.png
+++ b/docs/html/preview/images/battery_historian.png
Binary files differ
diff --git a/docs/html/preview/images/battery_historian@2x.png b/docs/html/preview/images/battery_historian@2x.png
index dbb5d5e..8c8a87f 100644
--- a/docs/html/preview/images/battery_historian@2x.png
+++ b/docs/html/preview/images/battery_historian@2x.png
Binary files differ
diff --git a/docs/html/preview/images/hun-example.png b/docs/html/preview/images/hun-example.png
index 9613a92..251b938 100644
--- a/docs/html/preview/images/hun-example.png
+++ b/docs/html/preview/images/hun-example.png
Binary files differ
diff --git a/docs/html/preview/images/hun-example@2x.png b/docs/html/preview/images/hun-example@2x.png
index 3cb8f5b..5b98a36 100644
--- a/docs/html/preview/images/hun-example@2x.png
+++ b/docs/html/preview/images/hun-example@2x.png
Binary files differ
diff --git a/docs/html/preview/images/managed_apps_launcher.png b/docs/html/preview/images/managed_apps_launcher.png
index 983d904..b5ef407 100644
--- a/docs/html/preview/images/managed_apps_launcher.png
+++ b/docs/html/preview/images/managed_apps_launcher.png
Binary files differ
diff --git a/docs/html/preview/images/managed_apps_launcher@2x.png b/docs/html/preview/images/managed_apps_launcher@2x.png
index d298fd2..90d7d51 100644
--- a/docs/html/preview/images/managed_apps_launcher@2x.png
+++ b/docs/html/preview/images/managed_apps_launcher@2x.png
Binary files differ
diff --git a/docs/html/preview/index.html b/docs/html/preview/index.html
index be2d360..4f3f150 100644
--- a/docs/html/preview/index.html
+++ b/docs/html/preview/index.html
@@ -165,7 +165,7 @@
 
             <img src="/preview/images/l-dev-prev.png" style=" margin:0px 0 0 40px" width="860px"/>
             <div class="col-6" style="margin-left:660px; margin-top:-105px">
-   <a href="/preview/setup-sdk.html" class="landing-button landing-secondary" style="position:absolute;z-index:100;float:right;margin-top: 0px;">Get Started</a><!--
+   <a href="/preview/setup-sdk.html" class="landing-button landing-primary" style="position:absolute;z-index:100;float:right;margin-top: 0px;">Get Started</a><!--
             <p>Set up your environment and check out all the docs to get up and running.</p>-->
              
          
@@ -241,7 +241,7 @@
                   Let us know when you encounter problems, so we can fix them and make
                   the platform better for you and your users.
                     </p><p class="landing-small">
-                      <a target="_blank" href="https://code.google.com/p/android-developer-preview/">
+                      <a href="https://code.google.com/p/android-developer-preview/">
                       Report Issues</a>
                     </p>
                   <p></p>
@@ -257,7 +257,7 @@
                     Join the community of Android developers testing out the L Developer Preview and
                     share your thoughts and experiences.
                   </p><p class="landing-small">
-                    <a target="_blank" href="http://plus.google.com">
+                    <a href="https://plus.google.com/communities/113159138894928487684">
                     Discuss on Google+</a>
                     </p>
                 </div>
@@ -274,7 +274,7 @@
                   for news about the changes.
                   </p>
                   <p class="landing-small">
-                    <a target="_blank" href="/preview/support.html">Get Support</a>
+                    <a href="/preview/support.html">Get Support</a>
                   </p>
                 </div>
               </div>
@@ -358,4 +358,4 @@
   <script src="/jd_tag_helpers.js" type="text/javascript"></script>
 
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/docs/html/preview/material/animations.jd b/docs/html/preview/material/animations.jd
index cee782a..b8d063b 100644
--- a/docs/html/preview/material/animations.jd
+++ b/docs/html/preview/material/animations.jd
@@ -10,8 +10,9 @@
   <li><a href="#reveal">Reveal Effect</a></li>
   <li><a href="#transitions">Activity Transitions</a></li>
   <li><a href="#curvedmotion">Curved Motion</a></li>
-  <li><a href="#viewstate">View State Changes</a></li>
+  <li><a href="#viewstate">Animating View State Changes</a></li>
   <li><a href="#drawabletint">Drawable Tinting</a></li>
+  <li><a href="#colorextract">Extracting Colors from an Image</a></li>
 </ol>
 </div>
 </div>
@@ -32,19 +33,26 @@
 
 <h2 id="touch">Touch Feedback</h2>
 
-<p>In the Android L Developer Preview the default touch feedback animations for buttons use the new
+<p>The default touch feedback animations for buttons use the new
 <code>RippleDrawable</code> class, which transitions between different states with a ripple
 effect.</p>
 
-<p>To use this functionality in your custom views, create a <code>RippleDrawable</code> and set
-it as the background of your view. You can define a <code>RippleDrawable</code> as an XML resource
-using the <code>ripple</code> element.</p>
+<p>In most cases, this functionality should be applied in your view XML by specifying the
+background as <code>?android:attr/selectableItemBackground</code> for a bounded ripple or
+<code>?android:attr/selectableItemBackgroundBorderless</code> for a ripple that extends beyond
+the view bounds. You can also create a <code>RippleDrawable</code> and set
+it as the background of your view. Alternatively, you can define a <code>RippleDrawable</code>
+as an XML resource using the <code>ripple</code> element. The
+Android L Developer Preview animates the selection color with a ripple effect.</p>
+
+<p>You can assign a color to <code>RippleDrawable</code> objects. To change the default touch
+feedback color, use the theme's <code>android:colorControlHighlight</code> attribute.</p>
 
 
 <h2 id="reveal">Reveal Effect</h2>
 
-<p>The <code>View.createRevealAnimator</code> method enables you to animate a clipping circle
-to reveal or hide a view.</p>
+<p>The <code>ViewAnimationUtils.createCircularReveal</code> method enables you to animate a
+clipping circle to reveal or hide a view.</p>
 
 <p>To reveal a previously invisible view using this effect:</p>
 
@@ -61,7 +69,8 @@
 
 // create and start the animator for this view
 // (the start radius is zero)
-ValueAnimator anim = myView.createRevealAnimator(cx, cy, 0, finalRadius);
+ValueAnimator anim =
+    ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
 anim.start();
 </pre>
 
@@ -79,7 +88,8 @@
 int initialRadius = myView.getWidth();
 
 // create the animation (the final radius is zero)
-ValueAnimator anim = myView.createRevealAnimator(cx, cy, initialRadius, 0);
+ValueAnimator anim =
+    ViewAnimationUtils.createCircularReveal(myView, cx, cy, initialRadius, 0);
 
 // make the view invisible when the animation is done
 anim.addListener(new AnimatorListenerAdapter() {
@@ -97,25 +107,48 @@
 
 <h2 id="transitions">Activity Transitions</h2>
 
-<p>The Android L Developer Preview enables your app to customize the default animations for
-activity transitions. You can specify custom animations for enter and exit transitions and for
+<p>You can specify custom animations for enter and exit transitions and for
 transitions of shared elements between activities.</p>
 
 <ul>
-  <li>An <strong>enter</strong> transition determines how views in an activity enter the scene.
-  For example, in the <em>explode</em> enter transition the views enter the scene from outside
-  and fly in towards the center of the screen.</li>
+<li>An <strong>enter</strong> transition determines how views in an activity enter the scene.
+For example, in the <em>explode</em> enter transition, the views enter the scene from the outside
+and fly in towards the center of the screen.</li>
 
-  <li>An <strong>exit</strong> transition determines how views in an activity exit the scene. For
-  example, in the <em>explode</em> exit transition the views exit the scene away from the
-  center.</li>
+<li>An <strong>exit</strong> transition determines how views in an activity exit the scene. For
+  example, in the <em>explode</em> exit transition, the views exit the scene away from the
+center.</li>
 
-  <li>A <strong>shared elements</strong> transition determines how views that are shared between
-  two activities transition between these activities. For example, if two activities have the same
-  image in different positions and sizes, the <em>moveImage</em> shared element transition
-  translates and scales the image smoothly between these activities.</li>
+<li>A <strong>shared elements</strong> transition determines how views that are shared between
+two activities transition between these activities. For example, if two activities have the same
+image in different positions and sizes, the <em>moveImage</em> shared element transition
+translates and scales the image smoothly between these activities.</li>
 </ul>
 
+<p>The Android L Developer Preview supports these enter and exit transitions:</p>
+
+<ul>
+<li><em>explode</em> - Moves views in or out from the center of the scene.</li>
+<li><em>slide</em> - Moves views in or out from one of the edges of the scene.</li>
+<li><em>fade</em> - Mades views in or out of the scene.</li>
+</ul>
+
+<p>Any transition that extends the <code>android.transition.Visibility</code> class is supported
+as an enter or exit transition. For more information, see the API reference for the
+<code>android.transition.Transition</code> class.</p>
+
+<p>The Android L Developer Preview also supports these shared elements transitions:</p>
+
+<ul>
+<li><em>changeBounds</em> - Animates the changes in layout bounds of target views.</li>
+<li><em>changeClipBounds</em> - Animates the changes in clip bounds of target views.</li>
+<li><em>changeTransform</em> - Animates the changes in scale and rotation of target views.</li>
+<li><em>moveImage</em> - Animates changes in size and scale type for an image view.</li>
+</ul>
+
+<p>When you enable activity transitions in your app, the default cross-fading transition is
+activated between the entering and exiting activities.</p>
+
 <img src="/preview/material/images/SceneTransition.png" alt=""
      id="figure1" style="width:600px;margin-top:20px"/>
 <p class="img-caption">
@@ -125,7 +158,8 @@
 <h3>Specify custom transitions</h3>
 
 <p>First, enable window content transitions with the <code>android:windowContentTransitions</code>
-attribute when you define a style that inherits from the material theme:</p>
+attribute when you define a style that inherits from the material theme. You can also specify
+enter, exit, and shared element transitions in your style definition:</p>
 
 <pre>
 &lt;style name="BaseAppTheme" parent="android:Theme.Material">
@@ -144,21 +178,13 @@
 &lt;/style>
 </pre>
 
-<p>You can also specify enter, exit, and shared element transitions in your style definition.
-The <code>move_image</code> transition in this example is defined as follows:</p>
+<p>The <code>move_image</code> transition in this example is defined as follows:</p>
 
 <pre>
 &lt;!-- res/transition/move_image.xml -->
 &lt;!-- (see also Shared Transitions below) -->
 &lt;transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
-  &lt;moveImage>
-    &lt;targets>
-      &lt;!-- shared view in the first activity -->
-      &lt;target android:targetId="@id/image_small" />
-      &lt;!-- shared view in the second activity -->
-      &lt;target android:targetId="@id/image_big" />
-    &lt;/targets>
-  &lt;/moveImage>
+  &lt;moveImage/>
 &lt;/transitionSet>
 </pre>
 
@@ -170,7 +196,7 @@
 <code>Window.requestFeature</code> method:</p>
 
 <pre>
-// inside your activity
+// inside your activity (if you did not enable transitions in your theme)
 getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);
 
 // set an exit transition
@@ -187,6 +213,20 @@
   <li><code>Window.setSharedElementExitTransition</code></li>
 </ul>
 
+<p>The <code>setExitTransition</code> and <code>setSharedElementExitTransition</code> methods
+define the exit transition for the calling activity. The <code>setEnterTransition</code> and
+<code>setSharedElementEnterTransition</code> methods define the enter transition for the called
+activity.</p>
+
+<p>To get the full effect of a transition, you must enable window content transitions on both the
+calling and called activities. Otherwise, the calling activity will start the exit transition,
+but then you'll see a window transition (like scale or fade).</p>
+
+<p>To start an enter transition as soon as possible, use the
+<code>Window.setAllowEnterTransitionOverlap</code> method on the called activity. This lets you
+have more dramatic enter transitions. The same applies for the calling activity and exit
+transitions with the <code>Window.setAllowExitTransitionOverlap</code> method.</p>
+
 <h3>Start an activity using transitions</h3>
 
 <p>If you enable transitions and set an exit transition for an activity, the transition is activated
@@ -201,7 +241,7 @@
 <ol>
 <li>Enable window content transitions in your style.</li>
 <li>Specify a shared elements transition in your style.</li>
-<li>Define your transition as an XML resource specifying the IDs of the target views.</li>
+<li>Define your transition as an XML resource.</li>
 <li>Assign a common name to the shared elements in both layouts with the
     <code>android:viewName</code> attribute.</li>
 <li>Use the <code>ActivityOptions.makeSceneTransitionAnimation</code> method.</li>
@@ -212,7 +252,7 @@
 final View imgContainerView = findViewById(R.id.img_container);
 
 // get the common element for the transition in this activity
-final View androidRobotView = findViewById(R.id.android_robot_img);
+final View androidRobotView = findViewById(R.id.image_small);
 
 // define a click listener
 imgContainerView.setOnClickListener(new View.OnClickListener() {
@@ -232,6 +272,9 @@
 <p>For shared dynamic views that you generate in your code, use the <code>View.setViewName</code>
 method to specify a common element name in both activities.</p>
 
+<p>To reverse the scene transition animation when you finish the second activity, call the
+<code>Activity.finishAfterTransition</code> method instead of <code>Activity.finish</code>.</p>
+
 <h3>Multiple shared elements</h3>
 
 <p>To make a scene transition animation between two activities that have more than one shared
@@ -241,12 +284,8 @@
 
 <pre>
 ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
-    new Pair[] {
         Pair.create(view1, "agreedName1"),
-        Pair.create(view2, "agreedName2"),
-        ...
-    }
-);
+        Pair.create(view2, "agreedName2"));
 </pre>
 
 
@@ -279,7 +318,7 @@
 </ul>
 
 <p>You can pass a <code>PathInterpolator</code> object to the
-<code>Animation.setInterpolation</code> method.</p>
+<code>Animator.setInterpolation</code> method.</p>
 
 <p>The <code>ObjectAnimator</code> class has new constructors that enable you to animate
 coordinates along a path using two or more properties at once. For example, the following animator
@@ -293,20 +332,20 @@
 </pre>
 
 
-<h2 id="viewstate">View State Changes</h2>
+<h2 id="viewstate">Animating View State Changes</h2>
 
 <p>The new <code>StateListAnimator</code> class lets you define animators that run when the state
 of a view changes. The following example shows how to define an <code>StateListAnimator</code> as
 an XML resource:</p>
 
 <pre>
-&lt;!-- animate the elevation property of a view when pressed -->
+&lt;!-- animate the translationZ property of a view when pressed -->
 &lt;selector xmlns:android="http://schemas.android.com/apk/res/android">
   &lt;item android:state_pressed="true">
     &lt;set>
-      &lt;objectAnimator android:propertyName="elevation"
+      &lt;objectAnimator android:propertyName="translationZ"
         android:duration="100"
-        android:valueTo="60"
+        android:valueTo="2"
         android:valueType="floatType"/>
         &lt;!-- you could have other objectAnimator elements
              here for "x" and "y", or other properties -->
@@ -316,15 +355,19 @@
     android:state_pressed="false"
     android:state_focused="true">
     &lt;set>
-      &lt;objectAnimator android:propertyName="elevation"
+      &lt;objectAnimator android:propertyName="translationZ"
         android:duration="100"
-        android:valueTo="10"
+        android:valueTo="2"
         android:valueType="floatType"/>
     &lt;/set>
   &lt;/item>
 &lt;/selector>
 </pre>
 
+<p class="note"><strong>Note:</strong> There is a known issue in the L Developer Preview release
+that requires valueFrom values to be provided in StateListAnimator animations to get the correct
+behavior.</p>
+
 <p>The new <code>AnimatedStateListDrawable</code> class lets you create drawables that show
 animations between state changes of the associated view. Some of the system widgets in the
 Android L Developer Preview use these animations by default. The following example shows how
@@ -337,9 +380,9 @@
 
     &lt;!-- provide a different drawable for each state-->
     &lt;item android:id="@+id/pressed" android:drawable="@drawable/drawableP"
-        android:state-pressed="true"/>
+        android:state_pressed="true"/>
     &lt;item android:id="@+id/focused" android:drawable="@drawable/drawableF"
-        android:state-focused="true"/>
+        android:state_focused="true"/>
     &lt;item android:id="@id/default"
         android:drawable="@drawable/drawableD"/>
 
@@ -358,21 +401,41 @@
 
 <h2 id="drawabletint">Drawable Tinting</h2>
 
-<p>The Android L Developer Preview enables you to define bitmaps as an alpha mask and to tint
-them using a color resource or a theme attribute that resolves to a color resource. You can
-create these assets only once and color them automatically to match your theme.</p>
+<p>The Android L Developer Preview enables you to define bitmaps or nine-patches as alpha masks and
+to tint them using a color resource or a theme attribute that resolves to a color resource (for
+example, <code>?android:attr/colorPrimary</code>). You can create these assets only once and color them
+automatically to match your theme.</p>
 
-<p>To apply a tint to a bitmap in your code, use the <code>setTint</code> method in these
-classes:</p>
+<p>To apply a tint to a bitmap, use the <code>setTint</code> method or the <code>android:tint</code>
+attribute for <code>BitmapDrawable</code> and <code>NinePatchDrawable</code>.</p>
+
+<p>The <code>setTint</code> method also lets you set the Porter-Duff mode used to blend the
+tint color for <code>NinePatchDrawable</code> and <code>BitmapDrawable</code> objects in your code.
+To set the tint mode in your layouts, use the <code>android:tintMode</code> attribute.</p>
+
+
+<h2 id="colorextract">Extracting Prominent Colors from an Image</h2>
+
+<p>The Android L Developer Preview Support Library includes the <code>Palette</code> class,
+which lets you extract prominent colors from an image. This class extracts the following
+prominent colors:</p>
 
 <ul>
-<li><code>PaintDrawable</code></li>
-<li><code>NinePatchDrawable</code></li>
-<li><code>RippleDrawable</code></li>
+<li>Vibrant</li>
+<li>Vibrant dark</li>
+<li>Vibrant light</li>
+<li>Muted</li>
+<li>Muted dark</li>
+<li>Muted light</li>
 </ul>
 
-<p>In your layouts, use the <code>android:tint</code> attribute instead.</p>
+<p>To extract these colors, pass a <code>Bitmap</code> object to the
+<code>Palette.generate</code> static method in the background thread where you load your images.
+If you can't use that thread, call the <code>Palette.generateAsync</code> method instead and
+provide a listener.</p>
 
-<p>The <code>setTint</code> method also lets you set the tint blending mode for
-<code>NinePatchDrawable</code> and <code>RippleDrawable</code> objects in your code. To set the
-tint mode in your layouts, use the <code>android:tintMode</code> attribute.</p>
+<p>To retrieve the prominent colors from the image, use the getter methods in the
+<code>Palette</code> class, such as <code>Palette.getVibrantColor</code>.</p>
+
+<p>For more information, see the API reference for the
+<code>android.support.v7.graphics.Palette</code> class.</p>
\ No newline at end of file
diff --git a/docs/html/preview/material/compatibility.jd b/docs/html/preview/material/compatibility.jd
index ce04e9e..fb97112 100644
--- a/docs/html/preview/material/compatibility.jd
+++ b/docs/html/preview/material/compatibility.jd
@@ -14,7 +14,7 @@
 </div>
 </div>
 
-<p>The new material design features (like the material theme and custom animations) are only
+<p>The new material design features (like the material theme and activity transitions) are only
 available in the Android L Developer Preview. However, you can design your apps to make use of
 these features when running on devices with the Android L Developer Preview and still be
 compatible with previous releases of Android.</p>
@@ -49,15 +49,34 @@
 and your alternative layout files for earlier versions of Android inside <code>res/layout/</code>.
 Alternative layouts have the same file name.</p>
 
+<p>To avoid duplication of code, define your styles inside <code>res/values/</code> and modify the
+styles in <code>res/values-v21/</code> for the new APIs.</p>
+
 
 <h2 id="widgets">UI Widgets</h2>
 
 <p>The <code>RecyclerView</code> and <code>CardView</code> widgets are included in the Android L
-Developer Preview Support Library, so they are available in earlier versions of Android.</p>
+Developer Preview Support Library, so they are available in earlier versions of Android with
+these limitations:</p>
+
+<ul>
+<li><code>CardView</code> falls back to a programmatic shadow implementation using additional padding.</li>
+<li><code>CardView</code> does not clip its children views that intersect with rounded corners.</li>
+</ul>
+
+<p>These limitations do not apply to the Android L Developer Preview.</p>
 
 
 <h2 id="animation">Animation APIs</h2>
 
-<p>The new APIs for custom animations are only available in the Android L Developer Preview. To
-preserve compatibility with earlier verisons of Android, check the system version at runtime before
-you invoke these APIs.</p>
\ No newline at end of file
+<p>The following new APIs are only available in the Android L Developer Preview:</p>
+
+<ul>
+<li>Activity transitions</li>
+<li>Touch feedback</li>
+<li>Reveal animations</li>
+<li>Path-based animations</li>
+</ul>
+
+<p>To preserve compatibility with earlier verisons of Android, check the system version at
+runtime before you invoke these APIs.</p>
\ No newline at end of file
diff --git a/docs/html/preview/material/get-started.jd b/docs/html/preview/material/get-started.jd
index 9c0e55d..7d0625e 100644
--- a/docs/html/preview/material/get-started.jd
+++ b/docs/html/preview/material/get-started.jd
@@ -8,9 +8,9 @@
 <ol>
   <li><a href="#applytheme">Apply the Material Theme</a></li>
   <li><a href="#layouts">Design Your Layouts</a></li>
-  <li><a href="#depth">Specify Depth in Your Views</a></li>
+  <li><a href="#depth">Specify Elevation in Your Views</a></li>
   <li><a href="#widgets">Use the New UI Widgets</a></li>
-  <li><a href="#apis">Use the New APIs</a></li>
+  <li><a href="#animations">Customize Your Animations</a></li>
 </ol>
 </div>
 </div>
@@ -19,7 +19,8 @@
 
 <ol>
   <li style="margin-bottom:10px">
-    Take a look at the <a href="">material design specification</a>.</li>
+    Take a look at the <a href="http://www.google.com/design/spec">material design
+    specification</a>.</li>
   <li style="margin-bottom:10px">
     Apply the material <strong>theme</strong> to your app.</li>
   <li style="margin-bottom:10px">
@@ -27,11 +28,11 @@
   <li style="margin-bottom:10px">
     Create your <strong>layouts</strong> following material design guidelines.</li>
   <li style="margin-bottom:10px">
-    Specify the <strong>depth</strong> for views to cast appropriate shadows.</li>
+    Specify the <strong>elevation</strong> of your views to cast appropriate shadows.</li>
   <li style="margin-bottom:10px">
     Use the new <strong>widgets</strong> for complex views, such as lists and cards.</li>
   <li style="margin-bottom:10px">
-    Use the new <strong>APIs</strong> to customize the animations in your app.</li>
+    Use the new APIs to customize the <strong>animations</strong> in your app.</li>
 </ol>
 
 <h3>Update Your App for the Android L Developer Preview</h3>
@@ -42,15 +43,16 @@
 
 <h3>Create New Apps for the Android L Developer Preview</h3>
 
-<p>If you are creating a new app for the Android L Developer Preview, the material design
-guidelines provide you with a solid design framework for your app. Follow these guidelines and
+<p>If you are creating a new app for the Android L Developer Preview, the <a
+href="http://www.google.com/design/spec">material design guidelines</a> provide you with a
+cohesive design framework for your app. Follow these guidelines and
 use the new functionality in the Android framework to design and develop your app.</p>
 
 
 <h2 id="applytheme">Apply the Material Theme</h2>
 
 <p>To apply the material theme in your app, specify a style that inherits from
-<code>android:theme.Material</code>:</p>
+<code>android:Theme.Material</code>:</p>
 
 <pre>
 &lt;!-- res/values/styles.xml -->
@@ -70,8 +72,8 @@
 <h2 id="layouts">Design Your Layouts</h2>
 
 <p>In addition to applying and customizing the material theme, your layouts should conform to
-the material design guidelines. When you design your layouts, pay special attention to the
-following:</p>
+the <a href="http://www.google.com/design/spec">material design guidelines</a>. When you design
+your layouts, pay special attention to the following:</p>
 
 <ul>
 <li>Baseline grids</li>
@@ -81,37 +83,36 @@
 <li>Layout structure</li>
 </ul>
 
-<p>You still define layouts inside XML files using the standard tools from the Android framework.
-For details on the material design guidelines, see the <a href="">material design
-specification</a>.</p>
 
+<h2 id="depth">Specify Elevation in Your Views</h2>
 
-<h2 id="depth">Specify Depth in Your Views</h2>
-
-<p>In the Android L Developer Preview, views can cast shadows. The elevation value of a view
-determines the size of its shadow. To set the elevation of a view, use the
+<p>Views can cast shadows, and the elevation value of a view
+determines the size of its shadow and its drawing order. To set the elevation of a view, use the
 <code>android:elevation</code> attribute in your layouts:</p>
 
 <pre>
-&lt;Button
-    android:id="@+id/my_button"
+&lt;TextView
+    android:id="@+id/my_textview"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:text="@string/next"
-    <strong>android:elevation</strong>="10dp" />
+    android:background="@color/white"
+    <strong>android:elevation</strong>="5dp" />
 </pre>
 
+<p>The new <code>translationZ</code> property lets you create animations that reflect temporary
+changes in the elevation of a view. For example, this is useful to respond to touch gestures.</p>
+
 <p>For more details, see <a href="{@docRoot}preview/material/views-shadows.html">Views and
 Shadows</a>.</p>
 
 
 <h2 id="widgets">Use the New UI Widgets</h2>
 
-<p>The Android L Developer Preview includes two new UI widgets for complex views,
-<code>RecyclerView</code> and <code>CardView</code>. <code>RecyclerView</code> is a more advanced
-version of <code>ListView</code> that provides performance improvements and is easier to use.
-<code>CardView</code> lets you show pieces of information inside cards with a consistent look
-across apps. To include a <code>CardView</code> in your layout:</p>
+<p><code>RecyclerView</code> is a more advanced version of <code>ListView</code> that provides
+performance improvements and is easier to use. <code>CardView</code> lets you show pieces of
+information inside cards with a consistent look across apps. To include a <code>CardView</code>
+in your layout:</p>
 
 <pre>
 &lt;android.support.v7.widget.CardView
@@ -126,7 +127,7 @@
 <p>For more information, see <a href="{@docRoot}preview/material/ui-widgets.html">UI Widgets</a>.</p>
 
 
-<h2 id="apis">Use the APIs to Customize Your Animations</h2>
+<h2 id="animations">Customize Your Animations</h2>
 
 <p>The Android L Developer Preview includes new APIs to create custom animations in your app.
 For example, you can enable activity transitions and define an exit transition inside an
diff --git a/docs/html/preview/material/images/MaterialDark.png b/docs/html/preview/material/images/MaterialDark.png
index 6a72280..f1018af 100644
--- a/docs/html/preview/material/images/MaterialDark.png
+++ b/docs/html/preview/material/images/MaterialDark.png
Binary files differ
diff --git a/docs/html/preview/material/images/MaterialLight.png b/docs/html/preview/material/images/MaterialLight.png
index 0e85528..4ed7d5c 100644
--- a/docs/html/preview/material/images/MaterialLight.png
+++ b/docs/html/preview/material/images/MaterialLight.png
Binary files differ
diff --git a/docs/html/preview/material/images/card_travel.png b/docs/html/preview/material/images/card_travel.png
index a804ca0..19752a8 100644
--- a/docs/html/preview/material/images/card_travel.png
+++ b/docs/html/preview/material/images/card_travel.png
Binary files differ
diff --git a/docs/html/preview/material/images/list_mail.png b/docs/html/preview/material/images/list_mail.png
index ca53ee1..bd107ff 100644
--- a/docs/html/preview/material/images/list_mail.png
+++ b/docs/html/preview/material/images/list_mail.png
Binary files differ
diff --git a/docs/html/preview/material/index.jd b/docs/html/preview/material/index.jd
index b7abcb4..d9a276f 100644
--- a/docs/html/preview/material/index.jd
+++ b/docs/html/preview/material/index.jd
@@ -3,11 +3,11 @@
 
 @jd:body
 
-<p itemprop="description">The Android L Developer Preview includes support for material design apps. Material design
-is a comprehensive guide for visual, motion, and interaction design across platforms and devices.
-To use material design in your Android apps, follow the guidelines defined in the
-<a href="">material design specification</a> and use the new components and functionality
-available in the Android L Developer Preview.</p>
+<p itemprop="description">The Android L Developer Preview includes support for material design
+apps. Material design is a comprehensive guide for visual, motion, and interaction design across
+platforms and devices. To use material design in your Android apps, follow the guidelines defined
+in the <a href="http://www.google.com/design/spec">material design specification</a> and use the
+new components and functionality available in the Android L Developer Preview.</p>
 
 <p>The Android L Developer Preview provides the following elements for you to build material
 design apps:</p>
@@ -27,13 +27,13 @@
 <!-- two columns -->
 <div style="width:700px;margin-top:25px;margin-bottom:20px">
 <div style="float:left;width:250px;margin-left:40px;margin-right:60px;">
-  <img src="{@docRoot}preview/material/images/MaterialDark.png" style="width:250px;"/>
+  <img src="{@docRoot}preview/material/images/MaterialDark.png" width="500" height="238"/>
   <div style="width:140px;margin:0 auto">
   <p style="margin-top:8px">Dark Material theme</p>
   </div>
 </div>
 <div style="float:left;width:250px;margin-right:0px;">
-  <img src="{@docRoot}preview/material/images/MaterialLight.png" style="width:250px;"/>
+  <img src="{@docRoot}preview/material/images/MaterialLight.png" width="500" height="238"/>
   <div style="width:140px;margin:0 auto">
   <p style="margin-top:8px">Light Material theme</p>
   </div>
@@ -49,12 +49,12 @@
 <!-- two columns -->
 <div style="width:700px;margin-top:25px;margin-bottom:20px">
 <div style="float:left;width:250px;margin-left:40px;margin-right:60px;">
-  <img src="{@docRoot}preview/material/images/list_mail.png" style="width:250px;"/>
+  <img src="{@docRoot}preview/material/images/list_mail.png" width="500" height="426"/>
   <p>The new <code>RecyclerView</code> widget is a more advanced version of <code>ListView</code>
-  provides performance improvements for dynamic views and is easier to use.</p>
+  that provides performance improvements for dynamic views and is easier to use.</p>
 </div>
 <div style="float:left;width:250px;margin-right:0px;">
-  <img src="{@docRoot}preview/material/images/card_travel.png" style="width:250px;"/>
+  <img src="{@docRoot}preview/material/images/card_travel.png" width="500" height="426"/>
   <p>The new <code>CardView</code> widget lets you display important pieces of information inside
   cards that have a consistent look and feel.</p>
 </div>
@@ -64,9 +64,13 @@
 
 <h3>View Shadows</h3>
 
-<p>In addition to the X and Y components, views in the Android L Developer Preview have a Z
-component. This new component represents the elevation of a view, which determines the size of
-its shadow: views with higher Z values cast bigger shadows.</p>
+<p>In addition to the X and Y properties, views in the Android L Developer Preview have a Z
+property. This new property represents the elevation of a view, which determines:</p>
+
+<ul>
+<li>The size of the shadow - Views with higher Z values cast bigger shadows.</li>
+<li>The drawing order - Views with higher Z values appear on top of other views.</li>
+</ul>
 
 <div style="width:290px;margin-left:35px;float:right">
   <div class="framed-nexus5-port-span-5">
@@ -86,7 +90,7 @@
 <p>The Android L Developer Preview provides new APIs that let you create custom animations for
 touch feedback in UI controls, view state changes, and activity transitions.</p>
 
-<p>The new animation APIs in the Android L Developer Preview let you:</p>
+<p>The new animation APIs let you:</p>
 
 <ul>
 <li style="margin-bottom:15px">
@@ -99,7 +103,7 @@
 Switch between activities with custom <strong>activity transition</strong> animations.
 </li>
 <li style="margin-bottom:15px">
-Create custom animation patterns with <strong>curved motion</strong>.
+Create more natural animations with <strong>curved motion</strong>.
 </li>
 <li style="margin-bottom:15px">
 Animate changes in one or more view properties with <strong>view state change</strong> animations.
@@ -109,9 +113,16 @@
 </li>
 </ul>
 
+<p>Touch feedback animations are built into several standard views, such as buttons. The new APIs
+let you customize these animations and add animations to your custom views.</p>
+
 
 <h3>New Capabilities for Drawables</h3>
 
 <p>The Android L Developer Preview supports <strong>drawable tinting</strong>: you can define
-bitmaps as an alpha mask and tint them using a color resource. You can create these assets only
-once and color each instance to match your theme.</p>
+bitmaps as an alpha mask and tint them using a color resource. You create these assets only
+once and color each instance to match your theme. Drawables also now support specifying most XML
+properties as <strong>theme attributes</strong>.</p>
+
+<p>The Android L Developer Preview Support Library includes a <strong>color extraction</strong>
+library that lets you automatically extract prominent colors from a bitmap image.</p>
\ No newline at end of file
diff --git a/docs/html/preview/material/theme.jd b/docs/html/preview/material/theme.jd
index b954960..740bf56 100644
--- a/docs/html/preview/material/theme.jd
+++ b/docs/html/preview/material/theme.jd
@@ -8,7 +8,7 @@
 <ol>
   <li><a href="#colorpalette">Customize the Colot Palette</a></li>
   <li><a href="#statusbar">Customize the Status Bar</a></li>
-  <li><a href="#inheritance">Theme Inheritance</a></li>
+  <li><a href="#inheritance">Theme Individual Views</a></li>
 </ol>
 </div>
 </div>
@@ -21,18 +21,18 @@
   <li>Activity transition animations</li>
 </ul>
 
-<p>The Android L Developer Preview lets you easily customize the look of the material theme
-according to your brand identity with a color palette you control. You can tint the app bar and
+<p>You can customize the look of the material theme
+according to your brand identity with a color palette you control. You can tint the action bar and
 the status bar using theme attributes, as shown in Figure 1.</p>
 
-<div style="float:right;margin-left:25px;margin-top:-25px">
+<div style="float:right;margin-left:25px;margin-top:-50px">
 <img src="{@docRoot}preview/material/images/ThemeColors.png" style="width:250px"/>
-<p class="img-caption"><strong>Figure 1.</strong> Customizing the material theme.</p>
+<p class="img-caption" style="margin-bottom:0px">
+<strong>Figure 1.</strong> Customizing the material theme.</p>
 </div>
 
-<p>The system widgets have a new design and touch feedback animations. Activity transitions help
-users navigate your app by providing visual continuity. You can customize the color palette,
-the touch feedback animations, and the activity transitions for your app.</p>
+<p>The system widgets have a new design and touch feedback animations. You can customize the
+color palette, the touch feedback animations, and the activity transitions for your app.</p>
 
 <p>The material theme is defined as:</p>
 
@@ -43,7 +43,7 @@
 </ul>
 
 <p>For a list of material styles that you can use, see the API reference for
-<code>android.R.styles</code>.</p>
+<code>android.R.style</code>.</p>
 
 <p class="note">
 <strong>Note:</strong> The material theme is only available in the Android L Developer Preview.
@@ -53,8 +53,8 @@
 
 <h2 id="colorpalette">Customize the Color Palette</h2>
 
-<p>To customize the theme's base colors to fit your brand, define your custom colors using
-theme attributes when you inherit from the material theme:</p>
+<p style="margin-bottom:30px">To customize the theme's base colors to fit your brand, define
+your custom colors using theme attributes when you inherit from the material theme:</p>
 
 <pre>
 &lt;resources>
@@ -63,38 +63,40 @@
     &lt;!-- Main theme colors -->
     &lt;!--   your app's branding color (for the app bar) -->
     &lt;item name="android:colorPrimary">@color/primary&lt;/item>
-    &lt;!--   darker variant of colorPrimary (for contextual app bars) -->
+    &lt;!--   darker variant of colorPrimary (for status bar, contextual app bars) -->
     &lt;item name="android:colorPrimaryDark">@color/primary_dark&lt;/item>
-
-    &lt;!-- other theme colors -->
-    &lt;item name="android:colorButtonNormal">@color/button_normal&lt;/item>
-    &lt;item name="android:windowBackground">@color/wbackground&lt;/item>
+    &lt;!--   theme UI controls like checkboxes and text fields -->
+    &lt;item name="android:colorAccent">@color/accent&lt;/item>
   &lt;/style>
 &lt;/resources>
 </pre>
 
 
-<h2 id="statusbar">Customize the Status Bar</h2>
+<h2 id="statusbar">Customize the Status and Navigation Bar</h2>
 
 <p>The material theme lets you easily customize the status bar, so you can specify a
-color which fits your brand and provides enough contrast to show the white status icons. To
+color that fits your brand and provides enough contrast to show the white status icons. To
 set a custom color for the status bar, use the <code>android:statusBarColor</code> attribute when
-you extend the material theme.</p>
+you extend the material theme. By default, <code>android:statusBarColor</code> inherits the
+value of <code>android:colorPrimaryDark</code>.</p>
 
 <p>To handle the color of the status bar yourself (for example, by adding a gradient in the
 background), set the <code>android:statusBarColor</code> attribute to
-<code>&#64;android:color/transparent</code>. You can also use the
-<code>Window.setStatusBarColor</code> method for animations or fading.</p>
+<code>&#64;android:color/transparent</code> and adjust the window flags as required. You can
+also use the <code>Window.setStatusBarColor</code> method for animations or fading.</p>
 
 <p class="note"><strong>Note:</strong>
 The status bar should almost always have a clear delineation from the primary toolbar, except for
 full-bleed imagery cases and when you use a gradient as a protection.
 </p>
 
+<p>When customizing the navigation and status bars, make them both transparent or modify only
+the status bar. The navigation bar should remain black in all other cases.</p>
 
-<h2 id="inheritance">Theme Inheritance</h3>
 
-<p>In the Android L Developer Preview, elements in XML layout definitions can specify the
-<code>android:theme</code> attribute, which references a theme resource. This attribute modifies
-the theme for the element and any elements inflated below it, which is useful to alter theme
-color palettes in a specific portion of an interface.</p>
\ No newline at end of file
+<h2 id="inheritance">Theme Individual Views</h3>
+
+<p>Elements in XML layout definitions can specify the <code>android:theme</code> attribute,
+which references a theme resource. This attribute modifies the theme for the element and any
+elements inflated below it, which is useful to alter theme color palettes in a specific portion
+of an interface.</p>
\ No newline at end of file
diff --git a/docs/html/preview/material/ui-widgets.jd b/docs/html/preview/material/ui-widgets.jd
index f18bff9..31604d6 100644
--- a/docs/html/preview/material/ui-widgets.jd
+++ b/docs/html/preview/material/ui-widgets.jd
@@ -14,19 +14,20 @@
 
 <p>The support library in the Android L Developer Preview contains two new widgets,
 <code>RecyclerView</code> and <code>CardView</code>. Use these widgets to show complex lists
-and cards in your app. These widgets have material design styles and animations by default.</p>
+and cards in your app. These widgets have material design style by default.</p>
 
 
 <h2 id="recyclerview">RecyclerView</h2>
 
-<p><code>RecyclerView</code> is a more advanced version of <code>ListView</code>. This widget is
-a container for large sets of views that can be recycled and scrolled very efficiently. Use the
-<code>RecyclerView</code> widget when you have lists with elements that change dynamically.</p>
+<p><code>RecyclerView</code> is a more advanced and flexible version of <code>ListView</code>.
+This widget is a container for large sets of views that can be recycled and scrolled very
+efficiently. Use the <code>RecyclerView</code> widget when you have lists with elements that
+change dynamically.</p>
 
 <p><code>RecyclerView</code> is easy to use, because it provides:</p>
 
 <ul>
-  <li>A set of layout managers for positioning items</li>
+  <li>A layout manager for positioning items</li>
   <li>Default animations for common item operations</li>
 </ul>
 
@@ -34,20 +35,9 @@
 widget.</p>
 
 <p>To use the <code>RecyclerView</code> widget, you have to specify an adapter and a layout
-manager. An <strong>adapter</strong> provides a binding from a dataset to views that are displayed
-within a <code>RecyclerView</code>. For example, if your dataset is an array of strings displayed
-as <code>TextView</code> items, the layout manager asks the adapter to:
-</p>
-
-<ul>
-  <li>Set the text of an existing <code>TextView</code> to one of the strings in the dataset</li>
-  <li>Create new <code>TextView</code> objects</li>
-  <li>Determine the size of the dataset</li>
-</ul>
-
-<p>To create an adapter, you extend the <code>RecyclerView.Adapter</code> class. The details of
-the implementation depend on the specifics of your dataset and the type of views. Fore more
-information, see the examples below.</p>
+manager. To create an adapter, you extend the <code>RecyclerView.Adapter</code> class. The details
+of the implementation depend on the specifics of your dataset and the type of views. For more
+information, see the <a href="#rvexamples">examples</a> below.</p>
 
 <img src="/preview/material/images/RecyclerView.png" alt="" id="figure1" style="width:550px"/>
 <p class="img-caption">
@@ -62,16 +52,17 @@
 <code>findViewById</code> lookups.
 </p>
 
-<p><code>RecyclerView</code> provides two layout managers you can use:</p>
+<p><code>RecyclerView</code> provides <code>LinearLayoutManager</code>, which shows the items in a
+vertical or horizontal scrolling list. To create a custom layout, you extend the
+<code>RecyclerView.LayoutManager</code> class.</p>
 
-<ul>
-  <li><code>LinearLayoutManager</code> shows the items in a vertically scrolling list.</li>
-  <li><code>GridLayoutManager</code> shows the items in a rectangular grid.</li>
-</ul>
+<h3>Animations</h3>
 
-<p>To create a custom layout, you extend the <code>RecyclerView.LayoutManager</code> class.</p>
+<p>Animations for adding and removing items are enabled by default in <code>RecyclerView</code>.
+To customize these animations, extend the <code>RecyclerView.ItemAnimator</code> class and use
+the <code>RecyclerView.setItemAnimator</code> method.</p>
 
-<h3>Examples</h3>
+<h3 id="rvexamples">Examples</h3>
 
 <p>To include a <code>RecyclerView</code> in your layout:</p>
 
@@ -87,7 +78,7 @@
 <p>To get the <code>RecyclerView</code> object in your activity:</p>
 
 <pre>
-public class MyActivity extends ActionBarActivity {
+public class MyActivity extends Activity {
     private RecyclerView mRecyclerView;
     private RecyclerView.Adapter mAdapter;
     private RecyclerView.LayoutManager mLayoutManager;
@@ -98,7 +89,8 @@
         setContentView(R.layout.my_activity);
         mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
 
-        // improve performance if the size is fixed
+        // improve performance if you know that changes in content
+        // do not change the size of the RecyclerView
         mRecyclerView.setHasFixedSize(true);
 
         // use a linear layout manager
@@ -139,7 +131,8 @@
     public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                    int viewType) {
         // create a new view
-        View v = new TextView(parent.getContext());
+        View v = LayoutInflater.from(parent.getContext())
+                               .inflate(R.layout.my_text_view, null);
         // set the view's size, margins, paddings and layout parameters
         ...
         ViewHolder vh = new ViewHolder(v);
@@ -167,22 +160,30 @@
 <h2 id="cardview">CardView</h2>
 
 <p><code>CardView</code> extends the <code>FrameLayout</code> class and lets you show information
-inside a card with optional rounded corners:</p>
+inside cards that have a consistent look on any app. <code>CardView</code> widgets can have
+shadows and rounded corners.</p>
+
+<p>To create a card with a shadow, use the <code>android:elevation</code> attribute.
+<code>CardView</code> uses real elevation and dynamic shadows
+and falls back to a programmatic shadow implementation on earlier versions. For more information,
+see <a href="{@docRoot}preview/material/compatibility.html">Compatibility</a>.</p>
+
+<p>Here's how to specify properties of <code>CardView</code>:</p>
 
 <ul>
   <li>To set the corner radius in your layouts, use the <code>android:cardCornerRadius</code>
   attribute.</li>
   <li>To set the corner radius in your code, use the <code>CardView.setRadius</code> method.</li>
+  <li>To set the background color of a card, use the <code>android:cardBackgroundColor</code>
+attribute.</li>
 </ul>
 
-<p>To set the background color of a card, use the <code>android:cardBackgroundColor</code>
-attribute.</p>
-
 <p>To include a <code>CardView</code> in your layout:</p>
 
 <pre>
 &lt;!-- A CardView that contains a TextView -->
 &lt;android.support.v7.widget.CardView
+    xmlns:card_view="http://schemas.android.com/apk/res-auto"
     android:id="@+id/card_view"
     android:layout_gravity="center"
     android:layout_width="200dp"
diff --git a/docs/html/preview/material/views-shadows.jd b/docs/html/preview/material/views-shadows.jd
index c5884d6..f7682f5 100644
--- a/docs/html/preview/material/views-shadows.jd
+++ b/docs/html/preview/material/views-shadows.jd
@@ -13,10 +13,12 @@
 </div>
 </div>
 
-<p>In apps with material design, depth has meaning. You should assign higher elevation values to more
-important UI elements in your app. The elevation value of a view determines the size of its
-shadow: views with higher Z values cast bigger shadows. Views only cast shadows on the Z=0 plane
-under an orthographic projection (the views do not scale for different values of Z).</p>
+<p>The elevation of a view determines the size of its shadow:
+views with higher Z values cast bigger shadows. Views only cast shadows on the Z=0 plane under an
+orthographic projection (the views do not scale for different values of Z).</p>
+
+<p>Elevation is also useful to create animations where widgets temporarily rise above the
+view plane when performing some action.</p>
 
 
 <h2 id="elevation">View Elevation</h2>
@@ -35,52 +37,59 @@
 
 <p>To set the translation of a view, use the <code>View.setTranslationZ</code> method.</p>
 
-<p>The Z values are measured in the same units as the X and Y values (like <code>dp</code> or
-<code>px</code>).</p>
+<p>The new <code>ViewPropertyAnimator.z</code> and <code>ViewPropertyAnimator.translationZ</code>
+methods enable you to easily animate the elevation of views. For more information, see
+the API reference for <code>ViewPropertyAnimator</code> and the <a
+href="{@docRoot}guide/topics/graphics/prop-animation.html#object-animator">Property Animation</a>
+developer guide.</p>
+
+<p>The Z values are measured in the same units as the X and Y values.</p>
 
 
 <h2 id="shadows">Shadows and Outlines</h2>
 
-<p>The bounds of a view's background drawable determine the default shape of its shadow. To define
-a custom shape for a shadow, such as an oval, use the <code>View.setOutline</code> method:</p>
+<p>The bounds of a view's background drawable determine the default shape of its shadow.
+<strong>Outlines</strong> represent the outer shape of a graphics object and define the ripple
+area for touch feedback.</p>
+
+<p>For example, if you define a view with a background drawable:</p>
 
 <pre>
-View v = findViewById(R.id.my_view);
-
-// add 10px to the static elevation
-v.setTranslationZ(10);
-
-// set an oval shadow
-Outline outline = new Outline();
-outline.setOval(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
-myView.setOutline(outline);
+&lt;TextView
+    android:id="@+id/myview"
+    ...
+    android:elevation="2dp"
+    android:background="@drawable/myrect" />
 </pre>
 
-<p>An <code>Outline</code> represents the outer shape of a graphics object. You can create
-<code>Outline</code> objects as in this example, or you can obtain the outline from a
-<code>Drawable</code> object with the <code>getOutline</code> method.</p>
+<p>where the background drawable is defined as a rectangle with rounded corners:</p>
 
-<p>The outline of a view also defines the ripple area for touch feedback.</p>
+<pre>
+&lt;!-- res/drawable/myrect.xml -->
+&lt;shape xmlns:android="http://schemas.android.com/apk/res/android"
+       android:shape="rectangle">
+    &lt;solid android:color="#42000000" />
+    &lt;corners android:radius="5dp" />
+&lt;/shape>
+</pre>
+
+<p>Then this view and drawable cast the appropiate shadow.</p>
+
+<p>You can also create outlines in your code using the methods in the <code>Outline</code> class,
+and you can assign them to views with the <code>View.setOutline</code> method.</p>
 
 <p>To prevent a view from casting a shadow, set its outline to <code>null</code>.</p>
 
 
 <h2 id="clip">Clipping Views</h2>
 
-<p>The Android L Developer Preview lets you clip a view to its outline area using the
+<p>Clip a view to its outline area using the
 <code>View.setClipToOutline</code> method. Only rectangle, circle, and round rectangle outlines
 support clipping, as determined by the <code>Outline.canClip</code> method.</p>
 
-<p>To determine if a view has been clipped, use the <code>View.getClipToOutline</code> method.</p>
+<p>To clip a view to the shape of a drawable, set the drawable as the background of the view
+(as shown above) and call the <code>View.setClipToOutline</code> method.</p>
 
-<pre>
-// clip a view to an oval
-View v = findViewById(R.id.my_view);
-outline.setOval(v.getLeft(), v.getTop(), v.getRight(), v.getBottom());
-myView.setOutline(outline);
-
-// if the view is not already clipped
-if (v.getClipToOutline() == false) {
-    v.setClipToOutline(true);
-}
-</pre>
\ No newline at end of file
+<p>Because clipping views is an expensive operation, don't animate the shape you use to
+clip a view. To achieve this effect, use a <a
+href="{@docRoot}preview/material/animations.html#reveal">Reveal Effect</a> animation.</p>
\ No newline at end of file
diff --git a/docs/html/preview/preview_toc.cs b/docs/html/preview/preview_toc.cs
index ecbd0ec..a292146 100644
--- a/docs/html/preview/preview_toc.cs
+++ b/docs/html/preview/preview_toc.cs
@@ -2,11 +2,7 @@
 
 
   <li class="nav-section">
-    <div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/setup-sdk.html">Set up the Preview SDK
-      </a></div>
-  </li>
-  <li class="nav-section">
-    <div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/setup-devices.html">Set Up Hardware and AVDs
+    <div class="nav-section-header empty"><a href="<?cs var:toroot ?>preview/setup-sdk.html">Set up the SDK
       </a></div>
   </li>
   <li class="nav-section">
@@ -36,6 +32,19 @@
         Get Started</a></li>
       <li class="nav-section">
         <div class="nav-section-header">
+          <a href="<?cs var:toroot ?>preview/tv/design/index.html">
+          Design</a></div>
+        <ul>
+          <li><a href="<?cs var:toroot ?>preview/tv/design/principles.html">
+            Creative Vision</a></li>
+          <li><a href="<?cs var:toroot ?>preview/tv/design/patterns.html">
+            UI Patterns</a></li>
+          <li><a href="<?cs var:toroot ?>preview/tv/design/style.html">
+            Style</a></li>
+        </ul>
+      </li>
+      <li class="nav-section">
+        <div class="nav-section-header">
           <a href="<?cs var:toroot ?>preview/tv/ui/index.html">
           User Interface</a></div>
         <ul>
diff --git a/docs/html/preview/samples.jd b/docs/html/preview/samples.jd
index 9bccb31..635f49e 100644
--- a/docs/html/preview/samples.jd
+++ b/docs/html/preview/samples.jd
@@ -2,4 +2,247 @@
 
 @jd:body
 
-<p>&nbsp;</p>
\ No newline at end of file
+<p>The following code samples are provided for the L Developer Preview. You can
+download them with the Android SDK Manager.</p>
+
+<p>To import a downloaded project:<p>
+
+<div class="toggle-content closed">
+<p style="margin-top:5px"><a href="#" onclick="return toggleContent(this)">
+  <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img" alt=""
+  />Using Android Studio</a></p>
+
+  <div class="toggle-content-toggleme">
+
+  <ol>
+    <li>Unpack the downloaded project package.</li>
+    <li>In <a href="{@docRoot}sdk/installing/studio.html">Android Studio</a>, chose
+    <strong>File > Import Project</strong> and select the root folder of
+    the unpacked project.
+      <p>Android Studio may ask you to choose the type of project you are
+        importing. If it does, make sure to choose <strong>Import project from
+        external model</strong> and select the <strong>Gradle</strong> option.
+      </p>
+    </li>
+  </ol>
+
+  </div>
+</div>
+
+<p class="note">
+  <strong>Note:</strong> At this time, the downloadable projects are designed
+   for use with Gradle and Android Studio.
+</p>
+
+
+
+
+<h3 id="BasicManagedProfile">BasicManagedProfile</h3>
+<div class="figure" style="width:220px">
+  <img src="{@docRoot}preview/images/BasicManagedProfile.png"
+     srcset="{@docRoot}preview/images/hun-BasicManagedProfile@2x.png 2x"
+     alt="" height="375" />
+  <p class="img-caption">
+    <strong>Figure 1.</strong> The BasicManagedProfile sample app.
+  </p>
+</div>
+
+<p>This sample demonstrates how to create a managed profile. You can also:</p>
+<ul>
+  <li>Enable or disable other apps, and set restrictions on them.</li>
+  <li>Configure intents to be forwarded between the primary account and the
+   managed profile.</li>
+  <li>Wipe all the data associated with the managed profile.</li>
+</ul>
+
+<p class="note"><strong>Note:</strong> There can be only one managed profile on
+  a device at a time.</p>
+
+<h3 id="Camera2Basic">Camera2Basic</h3>
+
+<!--
+<div class="figure" style="width:220px">
+  <img src="" srcset="@2x.png 2x" alt="" height="375" />
+  <p class="img-caption">
+    <strong>Figure n.</strong> Single sentence summarizing the figure.
+  </p>
+</div>
+-->
+
+<p>This sample demonstrates the basic use of the Camera2 API. The sample code
+demonstrates how you can display camera preview and take pictures.</p>
+
+
+
+<h3 id="Camera2Video">Camera2Video</h3>
+<!--
+<div class="figure" style="width:220px">
+<img src="" srcset="@2x.png 2x" alt="" height="375" />
+    <p class="img-caption">
+    <strong>Figure n.</strong> Single sentence summarizing the figure.
+  </p>
+</div>
+-->
+<p>This sample demonstrates how to record video using the Camera2 API.</p>
+
+
+<h3 id="ActivitySceneTransitionBasic">ActivitySceneTransitionBasic</h3>
+<div class="figure" style="width:220px">
+  <img src="{@docRoot}preview/images/ActivitySceneTransitionBasic.png"
+      srcset="{@docRoot}preview/images/ActivitySceneTransitionBasic@2x.png 2x"
+      alt="" height="375" />
+  <p class="img-caption">
+    <strong>Figure 2.</strong> The ActivitySceneTransitionBasic sample app.
+  </p>
+  </div>
+
+<p> This sample demonstrates how to the use {@link android.app.Activity} scene
+transitions when transitioning from one activity to another. Uses a combination
+of <code>moveImage</code> and <code>changeBounds</code> to nicely transition
+from a grid of images to an activity with a large image and detail text. </p>
+
+
+<h3 id="ElevationBasic">ElevationBasic</h3>
+<!--
+<div class="figure" style="width:220px">
+<img src="" srcset="@2x.png 2x" alt="" height="375" />
+    <p class="img-caption">
+    <strong>Figure n.</strong> Single sentence summarizing the figure.
+  </p>
+</div>
+-->
+<p>
+This sample demonstrates two alternative ways to move a view in the z-axis:</p>
+
+<ul>
+  <li>With a fixed elevation, using XML.</li>
+  <li>Raising the elevation when the user taps on it, using
+      <code>setTranslationZ()</code>.</li>
+</ul>
+
+
+
+<h3 id="ElevationDrag">ElevationDrag</h3>
+<!--
+<div class="figure" style="width:220px">
+  <img src="" srcset="@2x.png 2x" alt="" height="375" />
+  <p class="img-caption">
+    <strong>Figure n.</strong> Single sentence summarizing the figure.
+  </p>
+</div>
+-->
+
+<p>This sample demonstrates a drag and drop action on different shapes.
+Elevation and z-translation are used to render the shadows. The views are
+clipped using different outlines.</p>
+
+
+
+<h3 id="ClippingBasic">ClippingBasic</h3>
+<!--
+<div class="figure" style="width:220px">
+  <img src="" srcset="@2x.png 2x" alt="" height="375" />
+  <p class="img-caption">
+    <strong>Figure n.</strong> Single sentence summarizing the figure.
+  </p>
+</div>
+-->
+<p>
+This sample demonstrates clipping on a {@link android.view.View}.
+</p>
+
+
+
+<h3 id="GameControllerSample">GameControllerSample</h3>
+<!--
+<div class="figure" style="width:220px">
+  <img src="" srcset="@2x.png 2x" alt="" height="375" />
+  <p class="img-caption">
+    <strong>Figure n.</strong> Single sentence summarizing the figure.
+  </p>
+</div>
+-->
+<p>
+This sample implements a multi-player game, demonstrating game controller input
+handling.
+</p>
+
+
+
+<h3 id="Visual-Game-Controller">Visual-Game-Controller</h3>
+<!--
+<div class="figure" style="width:220px">
+  <img src="" srcset="@2x.png 2x" alt="" height="375" />
+  <p class="img-caption">
+    <strong>Figure n.</strong> Single sentence summarizing the figure.
+  </p>
+</div>
+-->
+<p>
+This sample displays events received from a game controller shown on the screen.
+</p>
+
+
+
+<h3 id="AndroidTVLeanbackSample">AndroidTVLeanbackSample</h3>
+<!--
+<div class="figure" style="width:220px">
+  <img src="" srcset="@2x.png 2x" alt="" height="375" />
+  <p class="img-caption">
+    <strong>Figure n.</strong> Single sentence summarizing the figure.
+  </p>
+</div>
+-->
+<p>
+This sample demonstrates use of the Android TV Leanback Support Library.
+</p>
+
+
+
+<h3 id="JobSchedulerSample">JobSchedulerSample</h3>
+
+<div class="figure" style="width:220px">
+  <img src="{@docRoot}preview/images/JobSchedulerSample.png"
+      srcset="{@docRoot}preview/images/JobSchedulerSample@2x.png 2x"
+      alt="" height="375" />
+  <p class="img-caption">
+    <strong>Figure 3.</strong> The JobSchedulerSample sample app.
+  </p>
+</div>
+
+<p>
+This sample app allows the user to schedule jobs through the UI, and shows
+visual cues when the jobs are executed.
+</p>
+
+
+
+<h3 id="NavigationDrawerSample">NavigationDrawerSample</h3>
+<!--
+<div class="figure" style="width:220px">
+  <img src="" srcset="@2x.png 2x" alt="" height="375" />
+  <p class="img-caption">
+    <strong>Figure n.</strong> Single sentence summarizing the figure.
+  </p>
+</div>
+-->
+<p>
+This sample illustrates a common usage of the Android support library's
+{@link android.support.v4.widget.DrawerLayout} widget.
+</p>
+
+
+<!--
+<h3 id="">SampleName</h3>
+
+<div class="figure" style="width:220px">
+  <img src="" srcset="@2x.png 2x" alt="" height="375" />
+  <p class="img-caption">
+    <strong>Figure n.</strong> Single sentence summarizing the figure.
+  </p>
+</div>
+
+<p>
+**description**
+</p>
+-->
diff --git a/docs/html/preview/setup-devices.jd b/docs/html/preview/setup-devices.jd
deleted file mode 100644
index 86e4845..0000000
--- a/docs/html/preview/setup-devices.jd
+++ /dev/null
@@ -1,90 +0,0 @@
-page.title=Setting Up Hardware and AVDs
-@jd:body
-
-<p>The Android L developer preview provides you with 32-bit system images
-to flash the following devices:
-</p>
-
-<ul>
-  <li>Nexus 5</li>
-  <li>Nexus 7 Wi-Fi (version 2, released in 2013)</li>
-</ul>
-
-<p>In addition, you also get the emulator system images, which includes
-experimental 64-bit system images along with standard 32-bit system images.
-</p>
-
-<h2>Installing the L Preview System Image</h2>
-
-<!-- Will we get an official warning text from the lawyercats? Is this it? -->
-<p class="warning"><b>Warning</b>: This is a preview version of the Android
-system image, and is subject to change. Your use of this system image is
-governed by the Android SDK Preview License Agreement. The Android preview
-system image is not a stable release, and may contain errors and defects that
-can result in damage to your computer systems, devices, and data. The preview
-Android system image is not subject to the same testing as the factory OS and
-can cause your phone and installed services and applications to stop working.
-</p>
-
-
-<ol>
-  <li>Download and extract the Android Developer Preview package to a directory
-  (which we'll call <code>&lt;l_download_dir&gt;</code> in these
-  instructions).</li>
-  <li>Connect your powered-off Android device to your development machine. Put
-  the device in fastboot mode by pressing and holding the following buttons:
-    <ul>
-    <li><strong>Nexus 5:</strong> <i>volume down</i> + <i>volume up</i> +
-        <i>power</i></li>
-    <li><strong>Nexus 7:</strong> <i>volume down</i> + <i>power</i> </li>
-    </ul>
-    <p class="note">Alternatively, you can enter fastboot mode by booting up
-    the device and running <code>adb reboot bootloader</code> with USB debugging
-    turned on.</p>
-  </li>
-  <li>Follow the instructions at
-  <a href="https://developers.google.com/android/nexus/images#instructions">developers.google.com/android</a>
-  to set up your system for flashing devices.</li>
-  <li>Run the <code>&lt;l_download_dir&gt;/flash-all</code> script
-  corresponding to your platform. This script flashes all of the system data
-  onto the phone.</li> <!-- Confirm names of flash scripts -->
-  <li>(Optional) After flashing is complete, lock your device's bootloader by
-  putting it in   fastboot mode and running <code>fastboot oem lock</code>.
-  (This does not wipe   your device.) Once you do this,  you will not be able to
-  flash your device until you run   run <code>fastboot oem   unlock</code>,
-  which unlocks the bootloader and wipes your device. We recommend you leave the
-  bootloader unlocked until you are done with flashing the device.</li>
-</ol>
-
-<h3>Reverting a Device to Factory Specifications</h3>
-
-  <p>If you want to uninstall the L Preview and revert the device to factory
-specifications, go to <a href="http://developers.google.com/android
-/nexus/images">developers.google.com/android</a> and download the image you want
-to flash to for your device. Follow the instructions on that page to flash the
-image to your device.</p>
-
-
-<h2>Setting up an AVD</h2>
-
-<p>You can set up <a href="{@docRoot}tools/devices/">Android Virtual Devices
-(AVD)</a> and use the emulator to build and test apps with the L Preview.</p>
-
-<p>To create an AVD with the AVD Manager:</p>
-
-<ol>
-  <li>Install the L Preview SDK in your development environment, as described
-      in <a href="{@docRoot}preview/setup-sdk.html">Setting Up the Preview
-      SDK.</a></li>
-  <li>Follow the steps in
-      <a href="{@docRoot}tools/devices/managing-avds.html">Managing AVDs with AVD
-      Manager</a>. Use the following settings:
-    <ul>
-      <li><b>Device:</b> Either Nexus 5 or Nexus 7</li>
-      <li><b>Target:</b> <!-- Confirm exact text when we have final distro -->
-       Android L (Preview) - API Level L</li>
-    </ul>
-    <!-- Confirm this works when you can download image through SDK manager! -->
-  </li>
-</ol>
-
diff --git a/docs/html/preview/setup-sdk.jd b/docs/html/preview/setup-sdk.jd
index 32a33b6..876b348 100644
--- a/docs/html/preview/setup-sdk.jd
+++ b/docs/html/preview/setup-sdk.jd
@@ -7,7 +7,7 @@
 Android, see <a href="/training/basics/firstapp/index.html">Building Your First
 App</a> training lesson first.</a></p>
 
-<h2>Download the SDK</h2>
+<h2 id="downloadSdk">Download the SDK</h2>
 
 <ol>
   <li>Start the Android SDK Manager.</li>
@@ -20,17 +20,125 @@
     <b>Install</b>.</li>
 </ol>
 
-<h2>Set up your environment</h2>
+<p class="note"><strong>Note:</strong> The Eclipse ADT plug-in requires Java 7
+if your compilation target is the L developer preview.</p>
+
+<h2 id="setupHardware">Set Up Hardware and AVDs</h2>
+
+<p>The Android L developer preview provides you with 32-bit system images
+to flash the following devices:
+</p>
+
+<ul>
+  <li>Nexus 5</li>
+  <li>Nexus 7 Wi-Fi (version 2, released in 2013)</li>
+</ul>
+
+<p>In addition, you also get the emulator system images, which includes
+experimental 64-bit system images along with standard 32-bit system images.
+</p>
+
+<h3 id="installImage">Install the L Preview System Image</h3>
+
+<p class="warning"><b>Warning:</b> This is a preview version of the Android
+system image, and is subject to change. Your use of this system image is
+governed by the Android SDK Preview License Agreement. The Android preview
+system image is not a stable release, and may contain errors and defects that
+can result in damage to your computer systems, devices, and data. The preview
+Android system image is not subject to the same testing as the factory OS and
+can cause your phone and installed services and applications to stop working.
+</p>
+
 
 <ol>
-  <li>Create a new Android project with the following properties:
-    <ul>
-      <li>Minimum SDK Version: L</li>
-      <li>Target SDK Version: L</li>
-      <li>Build Target: L</li>
-    </ul>
+  <li>Download and uncompress the Android Developer Preview package.
+    <p class="table-caption" id="table1">
+      <strong>Table 1.</strong> L Developer Preview system images.</p>
+    <table>
+      <tr>
+        <th scope="col">Device</th>
+        <th scope="col">Download</th>
+        <th scope="col">MD5 Checksum</th>
+        <th scope="col">SHA-1 Checksum</th>
+      </tr>
+      <tr id="hammerhead">
+        <td>Nexus 5 (GSM/LTE) "hammerhead"</td>
+        <td><!-- TODO --></td>
+        <td><code>5a6ae77217978cb7b958a240c2e80b57</code></td>
+        <td><code>ac1d8a8e4f4a1dca5864dc733caa940bffc28616</code></td>
+      </tr>
+      <tr id="razor">
+        <td>Nexus 7 (Wifi) "razor"</td>
+        <td><!-- TODO --></td>
+        <td><code>b293a5d3a4e07beabebcc0be85ad68a2</code></td>
+        <td><code>d0ddf8ce733ba2a34279cdff8827fd604762c2342d</code></td>
+      </tr>
+    </table>
   </li>
-  <li>Choose the theme <code>Theme.Material</code>
-    <!-- put in name as it appears in Eclipse menu? -->
 
+  <li>Follow the instructions at
+  <a href="https://developers.google.com/android/nexus/images#instructions">developers.google.com/android</a>
+  to flash the image onto your device.</li>
 </ol>
+
+<h3 id="revertDevice">Revert a Device to Factory Specifications</h3>
+
+  <p>If you want to uninstall the L Preview and revert the device to factory
+specifications, go to <a href="http://developers.google.com/android
+/nexus/images">developers.google.com/android</a> and download the image you want
+to flash to for your device. Follow the instructions on that page to flash the
+image to your device.</p>
+
+<h3 id="setupAVD">Set up an AVD</h3>
+
+<p>You can set up <a href="{@docRoot}tools/devices/">Android Virtual Devices
+(AVD)</a> and use the emulator to build and test apps with the L Preview.</p>
+
+<p>To create an AVD with the AVD Manager:</p>
+
+<ol>
+  <li>Install the L Preview SDK in your development environment, as described
+      in <a href="{@docRoot}preview/setup-sdk.html">Setting Up the Preview
+      SDK.</a></li>
+  <li>Follow the steps in
+      <a href="{@docRoot}tools/devices/managing-avds.html">Managing AVDs with AVD
+      Manager</a>. Use the following settings:
+    <ul>
+      <li><b>Device:</b> Either Nexus 5 or Nexus 7</li>
+      <li><b>Target:</b> <!-- Confirm exact text when we have final distro -->
+       Android L (Preview) - API Level L</li>
+    </ul>
+    <!-- Confirm this works when you can download image through SDK manager! -->
+  </li>
+</ol>
+
+<h2 id="createProject">Create a Project</h2>
+
+<p>Android Studio makes it easy to create a project for the L Developer Preview. Follow
+the steps described in <a href="{@docRoot}sdk/installing/create-project.html">Creating a
+Project</a>. In the <strong>Form Factors</strong> screen:</p>
+
+<ul>
+  <li>Check <strong>Phone and Tablet</strong>.</li>
+  <li>Select <strong>API 20+: Android L (Preview)</strong> in <strong>Minimum SDK</strong>.</li>
+</ul>
+
+<p>On the development environment, open the <code>build.gradle</code> file for your module
+and make sure that:</p>
+
+<ul>
+  <li><code>compileSdkVersion</code> is set to <code>'android-L'</code></li>
+  <li><code>minSdkVersion</code> is set to <code>'L'</code></li>
+  <li><code>targetSdkVersion</code> is set to <code>'L'</code></li>
+</ul>
+
+<p>To use the material theme, open the <code>values/styles.xml</code> in your project and make
+sure that you theme extends the material theme:</p>
+
+<pre>
+&lt;resources>
+    &lt;style name="AppTheme" parent="android:Theme.Material">
+        &lt;!-- Customize your theme here -->
+    &lt;/style>
+&lt;/resources>
+</pre>
diff --git a/docs/html/preview/support.jd b/docs/html/preview/support.jd
index 15c0a99..8efc4bc 100644
--- a/docs/html/preview/support.jd
+++ b/docs/html/preview/support.jd
@@ -3,7 +3,13 @@
 @jd:body
 
 <p>If you've encountered bugs or have feedback about the L Developer Preview,
-create an issue on our bug tracker.</p>
+<a href="https://code.google.com/p/android-developer-preview/">create an issue</a> on
+our issue tracker.</p>
+
+<p>For more support,
+<a href="https://plus.google.com/communities/113159138894928487684">join
+the L Developer Preview Google+ community</a> to discuss your development experiences.
+
 
 <h2 id="ReleaseNotes">Release Notes</h2>
 <p>June 25, 2014 - Initial Release of the L Developer Preview</p>
@@ -28,7 +34,7 @@
 <li>On very tall or wide views, view shadows may appear with additional rough
 visual artifacts around the view edges. To minimize this, avoid using view
 shadows with very narrow views.</li>
-<li>The {@code android.graphics.drawable.RippableDrawable} class does not
+<li>The {@code android.graphics.drawable.RippleDrawable} class does not
 respond to pointer location changes, except when the drawable is set as a
 {@link android.view.View} background.</li>
 </ul>
@@ -48,11 +54,12 @@
 stillCaptureRequest.set(CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE,
         CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE_ON);
 </pre></li>
-<li>Portions of the internal audio pipeline do not support floating-point format.</li>
 <li>The {@code android.media.AudioTrack.write(float[], int, int, int)} method
 currently does not work. Use the
 {@link android.media.AudioTrack#write(short[], int, int)
 AudioTrack.write(short[], int, int)} method instead.</li>
+<li>Lockscreen security is currently not enforced when users start a Android
+mirroring session from the Quick Settings shade.</li>
 </ul>
 
 <h3 id="UserInput">User input</h3>
@@ -60,21 +67,42 @@
 	the locale is set to {@code fr} (FRENCH).</li></ul>
 
 <h3 id="Wireless">Wireless and Connectivity</h3>
-<ul><li>The {@code android.bluetooth.le} APIs are supported only on Nexus 5
-devices.</li></ul>
+<ul>
+<li>The {@code android.bluetooth.le} APIs are supported only on Nexus 5
+devices.</li>
+<li>You might encounter these issues while using Bluetooth LE scanning:
+	<ul>
+	<li><em>Settings</em> does not show all Bluetooth LE devices when a scan
+		filter is set.</li>
+	<li>System returns non-intuitive error messages during a Bluetooth LE scan,
+		when Bluetooth is off.</li>
+	<li>The {@code BluetoothLeScanner.startScan()} method starts failing after
+		six concurrent scans with different callbacks.</li>
+	</ul>
+</li>
+<li>You might encounter these issues while using Bluetooth LE advertising:
+	<ul>
+		<li>The device MAC address does not change for multiple advertising
+		when the application processor is asleep.</li>
+		<li>The TX Power Level is always 0 in advertising packets.</li>
+	</ul>
+</li>
+</ul>
 
 <h3 id="Enterprise">Enterprise</h3>
 <ul>
 <li>The device may crash unexpectedly in these situations when using
-Android for Work functionality:
+Android work functionality:
 <ul>
-<li>The user attempts to share a webpage (via <strong>Menu &gt; Share</strong>)
-from a non-managed Chrome app to a managed Gmail app.</li>
-<li>The user attempts to share a webpage via Bluetooth from a managed Chrome app.</li>
-<li>The user attempts to share a webpage via Android Beam from a managed Chrome app.</li>
+<li>The user attempts to share a web page (via <strong>Menu &gt; Share</strong>)
+from a non-Android work Chrome app to a Android work profile Gmail app.</li>
+<li>The user attempts to share a web page via Bluetooth from a
+Android work profile
+Chrome app.</li>
+<li>The user attempts to share a web page via Android Beam from a
+Android work profile Chrome app.</li>
 </ul>
 </li>
-<li>Deleting the managed work profile (profile owner) may take several minutes
-to complete. You cannot create a new managed profile until the deletion
-operation is over.</li>
+<li>Deleting a Android work profile may take several minutes to complete. You
+cannot create a new Android work profile until the deletion operation is over.</li>
 </ul>
diff --git a/docs/html/preview/tv/adt-1/index.jd b/docs/html/preview/tv/adt-1/index.jd
new file mode 100644
index 0000000..d83dd11
--- /dev/null
+++ b/docs/html/preview/tv/adt-1/index.jd
@@ -0,0 +1,282 @@
+page.title=ADT-1 Developer Kit
+page.tags="emote","e-mote","adt"
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+  <h2>In this document</h2>
+  <ol>
+    <li><a href="#faq">Frequently Asked Questions</a>
+      <ol>
+        <li><a href="#setup">Device Setup</a></li>
+        <li><a href="#input">User Input</a></li>
+        <li><a href="#cast">Google Cast</a></li>
+        <li><a href="#trouble">Troubleshooting</a></li>
+      </ol>
+    </li>
+    <li><a href="#emote">Android TV Remote Control App</a></li>
+    <li><a href="#reg-safety">Regulatory Disclosures and Safety</a></li>
+  </ol>
+</div>
+</div>
+
+<p>The ADT-1 Developer Kit is a streaming media player and game controller designed for running
+and testing apps built for Android TV. Supplies of ADT-1 are limited and it is intended for
+developers who are interested in building new apps or extending their existing apps to run on the
+Android TV platform.</p>
+
+<p class="note">
+  <strong>Note:</strong> The ADT-1 kit <em>is not required</em> for building and testing apps
+  for Android TV. You can build apps for TV and test them using an emulator for TV devices. The
+  L Developer Preview includes all the software needed to build TV apps and an emulator for running
+  and testing them. For more information, see the
+  <a href="{@docRoot}preview/tv/start/index.html">Get Started</a> guide for TV apps.
+</p>
+
+<h2 id="faq">ADT-1 Frequently Asked Questions</h2>
+
+<p>The following information is provided to help set up and use the ADT-1 device.</p>
+
+
+<h3 id="setup">Device Setup</h3>
+
+<p>
+  <strong>How do I turn my device on?</strong>
+</p>
+<p>Plug the included power cable into the back of ADT-1. The device does not have an on/off
+  switch.</p>
+
+<p>
+  <strong>How do I completely turn my device off? </strong>
+</p>
+<p>Unplug the included power cable from the back of ADT-1. The device does not have an on/off
+  switch. However, ADT-1 will begin sleeping (daydream) based on user settings in
+  <strong>Settings &gt; Display &gt; Daydream</strong>.
+  </p>
+
+<p>
+  <strong>How do I connect to the network?</strong>
+</p>
+<p>ADT-1 has both wireless and Ethernet for connecting to your network. To change your wireless
+  network, go to <strong>Settings -&gt; Wi-Fi</strong>. To use an Ethernet network connection,
+  simply plug an Ethernet cable (that is connected to your network) into the port on the back of
+  ADT-1.</p>
+
+<p>
+  <strong>How do I use the developer cable?</strong>
+</p>
+<p>The developer cable has three connectors: a small, male power connector that plugs into the
+  power port on the back of ADT-1, a standard male USB-A connector that connects your PC, and a
+  small, female power connector that the included power supply plugs into.</p>
+
+
+
+<h3 id="input">User Input</h3>
+
+<p>
+  <strong>How do I put the gamepad that came with my ADT-1 into pairing mode?</strong>
+</p>
+<p>Press and hold the Back and Home buttons together for about three seconds, until all four
+  blue LEDs flash together. When the LEDs are flashing, the gamepad is in pairing mode.</p>
+
+<p>
+  <strong>How do I use the gamepad with the on-screen keyboard?</strong>
+</p>
+<p>Use the D-pad or left joystick to move the cursor, and press A to select. Press X to delete a
+  character, and press Y to insert a space. Also, you can press the right joystick to toggle caps
+  lock, and press the left joystick to show additional symbols.</p>
+
+<p>
+  <strong>Can I control ADT-1 with my phone or tablet?</strong>
+</p>
+<p>Yes. In order to control the ADT-1 with Android phones or tablets, you can download a remote
+  control app from the Google Play store. For more information, see <a href="#emote">Android TV
+  Remote Control App</a>.
+  </p>
+
+<p>
+  <strong>Can I connect a USB keyboard or mouse to ADT-1?</strong>
+</p>
+<p>Yes, you can connect a USB keyboard or mouse to the USB port on the back of ADT-1.
+
+<p class="note">
+  <strong>Note:</strong> The ADT-1 device is not compatible with all manufacturers and models of
+  these devices. If a particular keyboard or mouse does not work, try a different model.
+</p>
+
+<p>
+  <strong>How do I connect a Bluetooth device without an input device already attached?</strong>
+</p>
+<p>You can put ADT-1 into Bluetooth pairing mode using a hardware button. Press the small, round
+  button on the back of ADT-1 to make it search for Bluetooth devices in pairing mode. If multiple
+  accessories are found, press the small, round button to select the device you want to pair.
+  Pairing will happen automatically after a few seconds.
+</p>
+
+<p>
+  <strong>How do I connect additional Bluetooth accessories?</strong>
+<p>
+<p>To pair Bluetooth devices to ADT-1 from the user interface, go to <strong>Settings &gt;
+  Remote &amp; Accessories &gt; Add accessory</strong>
+
+
+<h3 id="cast">Google Cast</h3>
+
+<p>
+  <strong>Can I cast to an ADT-1 device?</strong>
+<p>
+<p>Yes. The ADT-1 includes Google Cast receiver functionality, similar to Chromecast. Since the
+  ADT-1 is a developer device running a development software release, the Google Cast receiver is
+  open only to a limited number of apps.</p>
+
+<p>
+  <strong>Which Cast apps are supported on ADT-1?</strong>
+<p>
+<p>As a developer device, the ADT-1 supports casting from only the following apps/websites:</p>
+
+<ul>
+  <li>YouTube</li>
+  <li>Netflix</li>
+  <li>Google+ Photos</li>
+  <li>Google Play Movies and TV (Android only)</li>
+</ul>
+
+<p>Coming soon:</p>
+
+<ul>
+  <li>Google Play Music</li>
+  <li>Google Play Movies and TV (iOS and Chrome)</li>
+  <li>Mirror you Android device screen to ADT-1</li>
+</ul>
+
+<p class="note">
+  <strong>Note:</strong> When casting from a Chrome browser, you must use Chrome V.36 or higher.
+  Chrome V.36 is available in beta-channel and is planned to be released soon.
+</p>
+
+<p>
+  <strong>How do I cast to ADT-1?</strong>
+<p>
+<p>You cast to an ADT-1 device the same way you do with a Chromecast device. Open the supported
+  Cast apps or webpages, press the <strong>Cast</strong> button and you should see the ADT-1 as a
+  Cast target. For more infomation about on how to cast, see
+  <a href="http://www.google.com/intl/en/chrome/devices/chromecast/learn.html">Learn How to
+  Cast</a>.
+  </p>
+
+<p>
+  <strong>Will my Google Cast sender apps work on ADT-1 just like Chromecast?</strong>
+<p>
+<p>Yes. Your Cast app works on ADT-1 and Android TV products without additional work.<p>
+
+<p class="note">
+  <strong>Note:</strong> Your iOS sender app requires the Google Cast iOS API version 2.2.1
+  or later to work with the ADT-1 device.
+</p>
+
+<p>
+  <strong>How do I register my ADT-1 in order to run my apps?</strong>
+</p>
+<ol>
+  <li>Go to <strong>Settings &gt; Google Cast</strong> and turn on developer support, allowing the
+    ADT-1 device to send its serial number to Google.</li>
+  <li>Register your ADT-1 device in the Google Cast Developer Console, using the 12 character
+    serial number engraved on the back of the ADT-1.</li>
+</ol>
+
+<p>For more Google Cast developer information, see the
+  <a href="https://developers.google.com/cast/">Cast developer site</a>. Please use the Google Cast
+  SDK <a href="https://code.google.com/p/google-cast-sdk/issues/list">issue tracker</a> for filing
+  issues related to Cast. Make sure you mention the ADT-1 device when filing an issue.
+</p>
+
+<p>
+  <strong>How do I debug my Cast app on ADT-1?</strong>
+</p>
+<p>Connect your development platform using the power/USB cable, and using a Chrome browser,
+  navigate to <code>chrome://inspect/#devices</code> to debug the webview.</p>
+
+
+<h3 id="trouble">Troubleshooting</h3>
+
+<p>
+  <strong>Why doesn't the on-screen keyboard come up?</strong>
+</p>
+<p>Enable the keyboard in the device Settings. Go to <strong>Settings &gt; Keyboard &gt; Current
+  keyboard</strong> and choose <strong>Leanback keyboard</strong>.
+
+<p>
+  <strong>How do I perform a hardware reboot?</strong>
+</p>
+<p>Locked it up, huh? No worries. We've done that a few times ourselves. Unplug and replug the
+  included power cable from the back of ADT-1 to reboot it.
+</p>
+
+<p>
+  <strong>How do I perform a factory reset?</strong>
+</p>
+<p class="warning">
+  <strong>Warning:</strong> This procedure removes all data from the device, including system
+  data, downloaded apps, app data, and account settings.
+</p>
+
+<p>From the home screen, go to <strong>Settings &gt; Device &gt; Factory data reset</strong>, and
+  select <strong>Reset device</strong>.
+</p>
+
+<p>
+  <strong>How do I perform a hardware reset?</strong>
+</p>
+<p class="warning">
+  <strong>Warning:</strong> This procedure performs a factory data reset, removing all data from
+  the device, including system data, downloaded apps, app data, and account settings.
+</p>
+
+<p>Unplug the power cable from the back of ADT-1. Press and hold the small, round button on the
+  back of ADT-1 as you re-insert the power cable, and continue to hold the small round button. The
+  LED will begin flashing red for a few seconds, then change to multi-color cycle. When the LED
+  starts the multi-color cycle, release the small, round button, and ADT-1 boots up. If you release
+  the button while the LED is flashing red, the device will be in Fastboot mode.</p>
+
+<p>
+  <strong>There is a hardware problem with my ADT-1. How do I return it?</strong>
+</p>
+<p>You can request a return of the device using the
+  <a href="https://support.google.com/googleplay/android-developer/contact/adt_rma">return
+  merchandise authorization form</a>.
+</p>
+
+
+<h2 id="emote">Android TV Remote Control App</h2>
+
+<div class="figure" style="width:250px;margin-top:0">
+<img src="/preview/tv/images/android-tv-remote.png" alt="Android TV Remote Screenshots">
+</div>
+
+<p>A remote control app is available for Android phones and tablets that allows you to interact
+  with the ADT-1 device. This app allows you to switch between D-pad input mode or touchpad mode
+  to navigate content and play games on a Android TV device. You can also tap the mic button to
+  start a voice search, or use the keyboard to input text using this app.</p>
+
+<p>You download the remote control app from the Google Play store using
+  <a href="https://play.google.com/store/apps/details?id=com.google.android.tv.remote">this
+  link</a>.
+</p>
+
+<p class="note">
+  <strong>Note:</strong> your Android ​phone or tablet must be connected to the same local network
+  as ADT-1.
+</p>
+
+
+<h2 id="reg-safety">Regulatory Disclosures and Safety Information</h2>
+
+<p>The ADT-1 device comes with important regulatory disclosures and safety information. Please
+read this information before using the device:</p>
+
+<ul>
+  <li><a href="regulatory.html">Regulatory Disclosures</a></li>
+  <li><a href="safety.html">Important Safety Information</a></li>
+</ul>
+
diff --git a/docs/html/preview/tv/adt-1/regulatory.jd b/docs/html/preview/tv/adt-1/regulatory.jd
new file mode 100644
index 0000000..2f5bf7e
--- /dev/null
+++ b/docs/html/preview/tv/adt-1/regulatory.jd
@@ -0,0 +1,79 @@
+page.title=Regulatory Disclosures for ADT-1
+parent.title=ADT-1 Developer Kit
+parent.link=index.html
+
+@jd:body
+
+<p>Disclosures for the <a href="index.html">ADT-1</a> device.</p>
+
+<p>
+  Model: W2<br>
+  FCC ID: A4R-W2<br>
+  IC: 10395A-W2
+</p>
+
+<p>U.S. Federal Communications Commission Notices</p>
+<p>To satisfy FCC and IC exposure requirements, a separation distance of at least 20 cm should
+  be maintained between the antenna of this device and persons during device operation. Operations
+  at closer than this distance are not recommended.</p>
+<p>The antenna used for this transmitter must not be co-located in conjunction with any other
+  antenna or transmitter.</p>
+<p>This equipment has been tested and found to comply with the limits for a Class B digital
+  device, pursuant to part 15 of the FCC Rules. These limits are designed to provide reasonable
+  protection against harmful interference in a residential installation. This equipment generates,
+  uses and can radiate radio frequency energy and, if not installed and used in accordance with the
+  instructions, may cause harmful interference to radio communications. However, there is no
+  guarantee that interference will not occur in a particular installation. If this equipment does
+  cause harmful interference to radio or television reception, which can be determined by turning
+  the equipment off and on, the user is encouraged to try to correct the interference by one or more
+  of the following measures:</p>
+<p>—Reorient or relocate the receiving antenna.</p>
+<p>—Increase the separation between the equipment and receiver.</p>
+<p>—Connect the equipment into an outlet on a circuit different from that to which the receiver
+  is connected.</p>
+<p>—Consult the dealer or an experienced radio/ TV technician for help.</p>
+<p>This device complies with part 15 of the FCC Rules. Operation is subject to the following two
+  conditions: (1) This device may not cause harmful interference, and (2) this device must accept
+  any interference received, including interference that may cause undesired operation.</p>
+<p>Changes or modifications not expressly approved by Google Inc. could void the user's
+  authority to operate the equipment.</p>
+<p>Industry Canada Notices</p>
+<p>This device complies with Industry Canada licence-exempt RSS standard(s). Operation is
+  subject to the following two conditions: (1) this device may not cause interference, and (2) this
+  device must accept any interference, including interference that may cause undesired operation of
+  the device.</p>
+<p>Under Industry Canada regulations, this radio transmitter may only operate using an antenna
+  of a type and maximum (or lesser) gain approved for the transmitter by Industry Canada. To reduce
+  potential radio interference to other users, the antenna type and its gain should be so chosen
+  that the equivalent isotropically radiated power (e.i.r.p.) is not more than that necessary for
+  successful communication.</p>
+<p>The radiated output power of the Wireless Device is below the Industry Canada (IC) radio
+  frequency exposure limits. The Wireless Device should be used in such a manner such that the
+  potential for human contact during normal operation is minimized.</p>
+
+<hr />
+
+<p>CAN ICES-3 (B)/NMB-3(B)</p>
+<p>
+  <u>Avis d’<em>Industrie Canada</em></u>
+</p>
+<p>
+  Le présent appareil est conforme aux <em>CNR</em> d'Industrie Canada applicables aux appareils
+  radio exempts de licence. L'exploitation est autorisée aux deux conditions suivantes : (1)
+  l'appareil ne doit pas produire de brouillage, et (2) l'appareil doit accepter tout brouillage
+  radioélectrique subi, même si le brouillage est susceptible d'en compromettre le fonctionnement.
+</p>
+<p>
+  En vertu de la règlementation d’<em>Industrie Canada</em>, cet émetteur radio peut
+    fonctionner avec une antenne d'un type et d'un gain maximal (ou inférieur) approuvé pour
+    l'émetteur par <em>Industrie Canada</em>. Dans le but de réduire les risques de brouillage
+  radioélectrique à l'intention des autres utilisateurs, il faut choisir le type d'antenne et son
+  gain de sorte que la puissance isotrope rayonnée équivalente (p.i.r.e.) ne dépasse pas l'intensité
+  nécessaire à l'établissement d'une communication satisfaisante.
+</p>
+<p>
+  La puissance rayonnée en sortie de l'appareil sans fil est inférieure aux limites fixées par
+  <em>Industrie Canada</em> en matière d'exposition aux radiofréquences. L'appareil sans fil
+  doit être utilisé de sorte que la possibilité d'un contact humain pendant le fonctionnement
+  normal soit limitée.
+</p>
diff --git a/docs/html/preview/tv/adt-1/safety.jd b/docs/html/preview/tv/adt-1/safety.jd
new file mode 100644
index 0000000..1984853
--- /dev/null
+++ b/docs/html/preview/tv/adt-1/safety.jd
@@ -0,0 +1,140 @@
+page.title=Important Safety Instructions for ADT-1
+parent.title=ADT-1 Developer Kit
+parent.link=index.html
+
+@jd:body
+
+<p>Safety information for the <a href="index.html">ADT-1</a> device.</p>
+
+<p>
+  <strong>WARNING:</strong> Read all safety information below before using this device to avoid
+  injury.
+</p>
+<ul>
+  <li><p>Do not install near heat sources, such as heaters and other devices.</p></li>
+  <li><p>Use in a well-ventilated area and plug power adapter into an easily accessible
+      outlet. Only use this device with the provided power adapter.</p></li>
+  <li><p>The device has no on/off switch. To disconnect from power, you must unplug the
+      power adapter.</p></li>
+  <li><p>Only use indoors and do not expose to rain, liquid, moisture, excessive heat, or
+      naked flame.</p></li>
+  <li><p>Clean only with a dry cloth.</p></li>
+</ul>
+<p>
+  <strong>WARNING:</strong> Playing video games has been linked to injuries in some
+  users. Read all safety and health information below before using the gamepad to avoid possible
+  injury.
+</p>
+
+<p><u>Photosensitive Seizures</u></p>
+
+<p>
+  A very small percentage of people may experience a seizure when exposed to certain visual images,
+  including flashing lights or patterns that may appear in some video games, even people who have no
+  history of seizures or epilepsy. These seizures have a variety of symptoms, including
+  lightheadedness, altered vision, disorientation, loss of awareness, involuntary movements, loss of
+  consciousness, or convulsions. If you experience any of these symptoms, <u>stop gaming
+    immediately and consult your doctor</u>.
+</p>
+
+<p><u>Ergonomics</u></p>
+
+<p>Long periods of repetitive motion using incorrect body positioning may be associated with
+  physical discomfort and injuries to nerves, tendons, and muscles. If during or after gaming you
+  feel pain, numbness, weakness, swelling, burning, cramping, or stiffness, <u>stop gaming
+  and consult your doctor</u>.
+
+<p>
+  <strong>Healthy Gaming</strong>
+</p>
+
+<p>To reduce risk of seizures or injury, take the following precautions:</p>
+
+<ul>
+  <li><p>Sit as far away from the TV screen as possible.</p></li>
+  <li><p>Play in a well-lit room.</p></li>
+  <li><p>Do not play when you are drowsy or fatigued.</p></li>
+  <li><p>Take 10-15 minute breaks every hour if playing video games and avoid prolonged
+      gaming.</p></li>
+</ul>
+
+<p>
+  <strong>Do Not Attempt Repairs Yourself</strong>
+</p>
+
+<p>There are no user-serviceable parts inside. Do not attempt to open or disassemble.</p>
+
+<p>Failure to follow these safety instructions could result in fire, electric shock, damage to
+  the device or other property, or personal injury.</p>
+
+<hr />
+
+<p>
+  <strong>Importantes instructions concernant la sécurité</strong>
+</p>
+
+<p>
+  <strong>ATTENTION:</strong> Veuillez lire toutes les informations de sécurité énoncées ci-bas
+  avant d’utiliser l’appareil pour éviter des blessures.
+</p>
+
+<ul>
+  <li><p>Ne pas installer à proximité d’une source de chaleur telle une chaufferette ou un
+      autre appareil similaire.</p></li>
+  <li><p>Utiliser dans un endroit bien aéré et brancher l’adaptateur électrique dans une
+      prise de courant facilement accessible.</p></li>
+  <li><p>L’appareil ne possède aucun interrupteur marché/arrêt. Pour mettre l’appareil hors
+      tension, il faut débrancher l’appareil de la prise de courant.</p></li>
+  <li><p>Utiliser l’appareil uniquement à l’intérieur et ne pas l’exposer à la pluie, à des
+      substances liquides, à l’humidité, à la chaleur excessive ou à une flamme.</p></li>
+  <li><p>Nettoyer uniquement avec un linge sec.</p></li>
+</ul>
+
+<p>
+  <strong>ATTENTION:</strong> Le fait de jouer à des jeux vidéo a été relié à des blessures chez certains
+  utilisateurs. Afin d’éviter de possibles blessures, veuillez lire toutes les informations
+  concernant la sécurité et la santé énoncées ci-bas avant d’utiliser la tablette de jeu.
+</p>
+
+<p><u>Épilepsie photosensible</u></p>
+
+<p>L’exposition à certaines images visuelles, incluant les lumières ou motifs clignotants qui
+  peuvent apparaître dans certains jeux vidéo, peut provoquer chez un très faible pourcentage de
+  personnes une crise d’épilepsie, et ce, même si ces personnes n’ont aucun historique de crises ou
+  d’épilepsie. Ces crises comportent divers symptômes tels que des étourdissements, une vision
+  altérée, un sentiment de désorientation, la perte de conscience, des mouvements involontaires, la
+  perte de connaissance ou de conscience ou des convulsions. Si vous ressentez quelconque de ces
+  symptômes, <u>cessez de jouer immédiatement et consultez votre médecin</u>.</p>
+
+<p><u>Ergonomie</u></p>
+
+<p>Les longues périodes de mouvements répétitifs effectués dans une position corporelle
+  inadéquate peuvent mener à un inconfort physique et à des blessures aux nerfs, tendons et muscles.
+  Si durant ou après avoir joué à des jeux vidéo, vous ressentez de la douleur, de
+  l’engourdissement, une faiblesse, de l’inflammation, une sensation de brûlure, des crampes ou de
+  la rigidité, <u>cessez de jouer immédiatement et consultez votre médecin</u>.</p>
+
+<p>
+  <strong>Le jeu sécuritaire</strong>
+</p>
+
+<p>Afin de réduire les risques de crises d’épilepsie ou de blessures, veuillez prendre les
+  précautions suivantes :</p>
+
+<ul>
+  <li>Asseyez-vous aussi loin de l’écran de télévision que possible.</li>
+  <li>Jouez dans une pièce munie d’un éclairage adéquat.</li>
+  <li>Ne jouez pas lorsque vous êtes étourdi ou fatigué.</li>
+  <li>Prenez 10 à 15 minutes de pause après chaque heure de jeu et évitez les périodes de jeu
+  prolongées.</li>
+</ul>
+
+<p>
+  <strong>Ne pas tenter d’effectuer des réparations par vous-même</strong>
+</p>
+
+<p>L’Appareil ne contient aucune pièce pouvant être réparée par l’utilisateur. Ne pas tenter
+  d’ouvrir ou de désassembler l’Appareil.</p>
+
+<p>Le défaut de suivre ces instructions de sécurité pourrait provoquer un feu, un choc
+  électrique, un dommage à l’Appareil ou à d’autres objets ou des lésions corporelles.</p>
diff --git a/docs/html/preview/tv/design/images/apps-games-rows.jpg b/docs/html/preview/tv/design/images/apps-games-rows.jpg
new file mode 100644
index 0000000..5023655
--- /dev/null
+++ b/docs/html/preview/tv/design/images/apps-games-rows.jpg
Binary files differ
diff --git a/docs/html/preview/tv/design/images/atv-framed-med.png b/docs/html/preview/tv/design/images/atv-framed-med.png
new file mode 100644
index 0000000..e06f6e7
--- /dev/null
+++ b/docs/html/preview/tv/design/images/atv-framed-med.png
Binary files differ
diff --git a/docs/html/preview/tv/design/images/atv-home.jpg b/docs/html/preview/tv/design/images/atv-home.jpg
new file mode 100644
index 0000000..4b25bab
--- /dev/null
+++ b/docs/html/preview/tv/design/images/atv-home.jpg
Binary files differ
diff --git a/docs/html/preview/tv/design/images/focus.png b/docs/html/preview/tv/design/images/focus.png
new file mode 100644
index 0000000..df61f4d
--- /dev/null
+++ b/docs/html/preview/tv/design/images/focus.png
Binary files differ
diff --git a/docs/html/preview/tv/design/images/icon.png b/docs/html/preview/tv/design/images/icon.png
new file mode 100644
index 0000000..ae34e18
--- /dev/null
+++ b/docs/html/preview/tv/design/images/icon.png
Binary files differ
diff --git a/docs/html/preview/tv/design/images/overscan.png b/docs/html/preview/tv/design/images/overscan.png
new file mode 100644
index 0000000..fb7e4bc
--- /dev/null
+++ b/docs/html/preview/tv/design/images/overscan.png
Binary files differ
diff --git a/docs/html/preview/tv/design/images/recommendations.png b/docs/html/preview/tv/design/images/recommendations.png
new file mode 100644
index 0000000..942cd10
--- /dev/null
+++ b/docs/html/preview/tv/design/images/recommendations.png
Binary files differ
diff --git a/docs/html/preview/tv/design/images/search.jpg b/docs/html/preview/tv/design/images/search.jpg
new file mode 100644
index 0000000..c034939
--- /dev/null
+++ b/docs/html/preview/tv/design/images/search.jpg
Binary files differ
diff --git a/docs/html/preview/tv/design/images/settings.jpg b/docs/html/preview/tv/design/images/settings.jpg
new file mode 100644
index 0000000..1c5bf31
--- /dev/null
+++ b/docs/html/preview/tv/design/images/settings.jpg
Binary files differ
diff --git a/docs/html/preview/tv/design/index.jd b/docs/html/preview/tv/design/index.jd
new file mode 100644
index 0000000..b924a5c
--- /dev/null
+++ b/docs/html/preview/tv/design/index.jd
@@ -0,0 +1,65 @@
+page.title=Design for TV
+header.justLinks=1
+footer.hide=1
+@jd:body
+
+
+<p>The Android TV platform user interface provides the launch pad for your app's big screen
+  experience. It's important to understand how your app is presented in the main user interface and
+  how your app can help users get to the content they want quickly.</p>
+
+
+<h2>Home Screen</h2>
+
+<p>The Home Screen is the start of the user experience, providing search, content
+  recommendations, and access to apps and settings. This screen provides a rich and cinematic
+  overview of apps and content.</p>
+
+<img src="{@docRoot}preview/tv/design/images/atv-home.jpg" alt="TV Home screen" />
+
+
+<h2>Search</h2>
+
+<p>By bringing the power of Google search to the big screen, Android TV makes new, dynamic
+  connections between content. A favorite movie may lead to the discovery of a new music artist,
+  planning a trip to Paris might surface new YouTube content and photos.</p>
+
+<img src="{@docRoot}preview/tv/design/images/search.jpg" alt="Recommendations Row" />
+
+<p>To learn more about searching within your app, see
+  <a href="{@docRoot}preview/tv/ui/in-app-search.html">Searching in TV Apps</a>.
+
+<h2>Recommendations</h2>
+
+<p>The recommendations row on Android TV is a central feature of the Home Screen that allows
+  users quick access to dynamic and relevant content for their media-consumption activities. The
+  row is optimized for quick browsing of personalized content and activity resumption (on the
+  device and across devices), while also providing a way for users to act on meaningful new
+  content.</p>
+
+<img src="{@docRoot}preview/tv/design/images/recommendations.png" alt="Recommendations Row" />
+
+<p>
+  Recommendations are based on the user’s recent and frequent usage behaviors, as well as
+  expressed content preferences. They appear as cards that represent a system or app action,
+  notification, activity, or piece of actionable media. Your app can provide suggestions for the
+  recommendations row to help get your content noticed. To learn more, see
+  <a href="{@docRoot}preview/tv/ui/recommendations.html">Recommendations</a>.
+</p>
+
+
+<h2>Apps and Games</h2>
+
+<p>Apps and Games rows both have special areas on the Home Screen. Within their respective
+  areas, Apps and Games titles are ordered to reflect the user’s recent usage.</p>
+
+<img src="{@docRoot}preview/tv/design/images/apps-games-rows.jpg" alt="Apps and Games Rows" />
+
+
+<h2>Settings</h2>
+
+<p>Access to Settings is found at the bottom of the Home Screen. From here, the user can access
+  Android and device-specific settings.
+</p>
+
+<img src="{@docRoot}preview/tv/design/images/settings.jpg" alt="Settings Row" />
diff --git a/docs/html/preview/tv/design/patterns.jd b/docs/html/preview/tv/design/patterns.jd
new file mode 100644
index 0000000..cdba74c
--- /dev/null
+++ b/docs/html/preview/tv/design/patterns.jd
@@ -0,0 +1,86 @@
+page.title=Patterns for TV
+page.tags="design"
+@jd:body
+
+<p>As a developer of apps for TV, you should follow certain patterns to enable users to
+  quickly understand and operate your app. This section describes recommended design patterns
+  for TV apps.</p>
+
+<h2>Navigation, Focus and Selection</h2>
+
+<p>Users typically navigate TV devices using a directional pad (D-Pad). This type of controller
+  limits movement to up, down, left, and right. As you design your app for TV, make sure your
+  user interface has clear paths for two-axis navigation by aligning objects in lists and
+  grids.</p>
+
+<img src="{@docRoot}preview/tv/design/images/focus.png" alt="TV navigation and focus diagram" />
+
+<p>A key aspect of making your application work well with a D-Pad controller is to make sure
+  that there is always an object that is obviously in focus. Your app must clearly indicate
+  what object is focused, so users can easily see what action they can take. Use scale, shadow
+  brightness, opacity, animation or a combination of these attributes to help users see a focused
+  object.</p>
+
+
+<h2>Icons</h2>
+
+<p>Apps on TV devices require some additional icon images for presentation in the system
+  user interface, including home screen launcher images (banners) and recommendation icons.
+  The visual specifications for these icons are shown below.</p>
+
+
+<h3>Banners</h3>
+
+<p>App Banners represent your app on the home screen of TV devices and serve and as a way for
+  users to launch your app. Here are specific requirements for a banner image:
+</p>
+
+<ul>
+  <li>Size: 320 x 180 px, xhdpi resource</li>
+  <li>Text should be included in the image. If your app is available in more than one
+      language, you must provide versions of the banner image for each supported language.</li>
+</ul>
+
+
+<h3>Recommendation Icons</h3>
+
+<p>Recommendation cards include a small icon that is imposed over a colored background.
+  An example and specifications for the this icon are shown below:</p>
+
+<img src="{@docRoot}preview/tv/design/images/icon.png" alt="Recommendation icon examples" />
+
+<p>Here are the requirements for recommendation icons:</p>
+
+<ul>
+  <li>Monocolor: size 16x16dp, white (#fff) icon with transparent background, PNG format</li>
+  <li>Graphics should be centered within the icon image</li>
+</ul>
+
+<p class="note">
+  <strong>Note:</strong> Your app icon image may be desaturated and blended for some card
+  displays.
+</p>
+
+
+<h2>Background Images</h2>
+
+<p>Background images are displayed in the background of your app to provide additional visual
+  interest, information, or branding. The BrowseFragment and DetailsFragment classes in the Leanback
+  support library provide specific support for background images and for updating them as items gain
+  and lose focus. Here are the specific requirements for background images:</p>
+
+<ul>
+  <li>Full color, 1920 x 1080 pixels</li>
+</ul>
+
+<p class="note">
+  <strong>Note:</strong> If the image does not meet this requirement, it is scaled to fit.
+</p>
+
+<h2>Audio Feedback</h2>
+
+<p>Sounds on Android TV bring a cinematic quality to the interaction experience. You should
+  consider adding sounds for user actions or to provide feedback when a user is only partially
+  visually engaged with the screen (e.g., because they are distracted or multitasking).
+  You should also consider using sounds as alternatives to visual messages, for example to indicate
+  that a user has reached the end of a list or is trying to navigate to an undefined location.</p>
diff --git a/docs/html/design/tv/principles.jd b/docs/html/preview/tv/design/principles.jd
similarity index 66%
rename from docs/html/design/tv/principles.jd
rename to docs/html/preview/tv/design/principles.jd
index 5c0ce10..106fa96 100644
--- a/docs/html/design/tv/principles.jd
+++ b/docs/html/preview/tv/design/principles.jd
@@ -1,45 +1,33 @@
-page.title=Design Principles for TV
+page.title=Creative Vision for TV
 @jd:body
 
-<p>Users bring a specific set of expectations to the experience of watching TV, versus
-  interacting with a phone or tablet. These principles have been developed by the Android User
+<p>Users bring a specific set of expectations when watching TV, versus
+  interacting with a phone or tablet. These guidelines have been developed by the Android User
   Experience Team to guide creation of the Android TV platform and the apps that run on it.</p>
 
 <h2>Casual Consumption</h2>
 
 <p>The TV is an entertainment interface, not a computer or mobile device. Optimize for
   activities that put content at the center: from the casual posture of movie-watching, to
-  edge-of-seat, immersive gameplay, to hanging out with friends in a living room.</p>
+  immersive gameplay, to hanging out with friends in a living room.</p>
 
-<p>Users expect immediate access to to content when they turn on a TV. Get users into the action
+<p>Users expect immediate access to content when they turn on a TV. Get users into the action
   fast, be it the big game, their favorite show, or a game with friends. The next piece of content
   to watch or play should only be a click or two away.</p>
 
-<p>
-  [add a visual]
-</p>
-
 
 <h2>Cinematic Experience</h2>
 
 <p>Create immersive experiences for the user. Design for as little user interface and as much
-  content as possible on each screen. Use visual imagery, movement and sound to inform and delight
+  content as possible on each screen. Use visual imagery, movement, and sound to inform and delight
   users. Avoid using on-screen text to convey information and purpose. Tell your story with pictures
   and sound.</p>
 
-<p>
-  [add a visual]
-</p>
-
 
 <h2>Simplicity</h2>
 
-<p>An Android TV should be simple and magical. It’s all about finding and enjoying content and
+<p>Android TV is simple and magical. It’s all about finding and enjoying content and
   apps with the least amount of friction. Minimize the number of navigation steps required to
   perform actions. Build apps with the fewest screens possible between app entry and content
   immersion. Avoid making users enter text whenever possible, and use voice interfaces when you
   require text input.</p>
-
-<p>
-  [add a visual]
-</p>
diff --git a/docs/html/design/tv/style.jd b/docs/html/preview/tv/design/style.jd
similarity index 62%
rename from docs/html/design/tv/style.jd
rename to docs/html/preview/tv/design/style.jd
index 479ed91..67a7096 100644
--- a/docs/html/design/tv/style.jd
+++ b/docs/html/preview/tv/design/style.jd
@@ -9,13 +9,14 @@
 <h2>Layouts</h2>
 
 <p>The difference between a TV experience that feels right and one that does not greatly depends
-  on the number, spacing and size of on-screen elements. Although TV sizes and resolutions have
+  on the number, spacing, and size of on-screen elements. Although TV sizes and resolutions have
   steadily increased over time, users expect TV experiences to be relatively simple and
   uncluttered.</p>
 
 <p>The additional resolution and screen area afforded by modern displays is best used to display
   things at better quality, rather than greater quantity. For example, use your layouts to show
-  large, beautiful pieces of content, or resize type for both easy reading and generous spacing.</p>
+  large, beautiful pieces of content, or to resize type for both easy reading and generous spacing.
+</p>
 
 <p>If you are creating an app for browsing and playing content, use the prebuilt fragments in the
   Leanback support library. These layouts have been built specifically for use on TV devices with
@@ -23,33 +24,28 @@
   see the <a href="{@docRoot}preview/tv/build-ui/index.html">User Interfaces</a> guide.
 </p>
 
-<p>Here are some additional recommendations for creating functional and attractive layout for TV
+<p>Here are some additional recommendations for creating functional and attractive layouts for TV
   apps:</p>
 
 <ul>
-  <li><p>Build layouts designed for landscape orientation. TV screens always use in this
-      orientation.</p></li>
-  <li><p>Put on-screen navigational controls on the left or right side of the screen and
-      save the vertical space for content.</p></li>
-  <li><p>Create UIs that are divided into sections, by using Fragments and use view groups
-      like GridView instead of ListView to make better use of the horizontal screen space.</p></li>
-  <li><p>Add sufficient margins between layout controls to avoid a cluttered interface.</p></li>
+  <li>Design layouts for landscape orientation. TV screens always use this
+      orientation.</li>
+  <li>Design your artwork assets for best viewing at HD resolution (1920 x 1080 pixels).</li>
+  <li>Put on-screen navigational controls on the left or right side of the screen, and
+      save the vertical space for content.</li>
+  <li>Use Fragments to create UIs that are divided into sections, and use view groups
+      like GridView instead of ListView to make better use of the horizontal screen space.</li>
+  <li>Avoid a cluttered interface by adding sufficient margins between layout controls.</li>
 </ul>
 
 
-<h3>Screen Size</h3>
-
-<p>TV devices running Android are intended to operate at HD resolution (1920 x 1080 pixels) or
-  higher. Design your artwork assets for best viewing at this resolution.</p>
-
-
 <h3>Overscan</h3>
 
 <p>During the evolution of TV technology, overscan originally described an area of TV content
   outside of a safe zone that most TVs could reliably display. Even on some of today’s HDTV flat
   screens, areas outside that zone may not be visible.</p>
 
-<img src="{@docRoot}design/tv/images/overscan.png" alt="image alt text" />
+<img src="{@docRoot}preview/tv/design/images/overscan.png" alt="Overscan borders for TV" />
 
 <p>Build a 10% margin into your TV screen designs to account for overscan area the TV may not
   display correctly. On a 1920 x 1080 pixel screen, this margin should be a minimum of 27px from the
@@ -63,8 +59,9 @@
   not match what you see on a computer screen.</p>
 
 <p>Subtle hue or brightness differences between elements may disappear or be over-emphasized on
-  TV screens. Some color gradient combinations will show bands. You should avoid pure whites and
-  highly saturated colors in large areas of the screen (especially reds, greens and blues). You
+  TV screens. Some color gradient combinations will show bands. You should avoid pure whites on
+  large areas of the screen. For highly saturated colors (especially reds, greens and blues) you
+  should review them when used to fill significant areas of the screen.  You
   should also avoid using very dark or muddy colors, as TV settings may display these colors with
   exaggerated contrast, causing them to be indistinguishable.</p>
 
@@ -76,17 +73,14 @@
   be 18sp. We recommend the following guidelines for TV apps:</p>
 
 <ul>
-  <li>Browse Titles: Regular 44sp</li>
-  <li>Browse Menu Category Text: 20sp at 50% transparency</li>
-  <li>Browse Focused Menu Category Text: 24sp with no transparency</li>
-  <li>Row Category Titles focused: 20sp with no transparency</li>
-  <li>Row Category Titles focused: 20sp at 50% transparency</li>
-  <li>Details Content Titles: 34sp</li>
-  <li>Details Subtext: 14sp</li>
+  <li><strong>Card Titles:</strong> Roboto Condensed 16sp</li>
+  <li><strong>Card Subtext:</strong> Roboto Condensed 12sp</li>
+  <li><strong>Browse Screen Title:</strong> Roboto Regular 44sp</li>
+  <li><strong>Browse Category Title:</strong> Roboto Condensed 20sp</li>
+  <li><strong>Details Content Titles:</strong> Roboto Regular 34sp</li>
+  <li><strong>Details Subtext:</strong> Roboto Regular 14sp</li>
 </ul>
 
-<p>[visual showing text on a TV screen (sidebar position)]</p>
-
 <p>Some TVs have strong sharpness and contrast settings as their defaults. These picture
   settings make thin and light typefaces look jagged and make the text difficult for people to read.
   Therefore you should avoid thin or light typefaces on TV.</p>
@@ -94,15 +88,14 @@
 <h2>Text</h2>
 
 <p>Use text in TV apps sparingly. The position of users relative to a TV screen
-  (typically about 10 away) makes it harder for users to read text and the expectation of users in a
-  TV environment not conducive to reading. Follow these tips for the best handling of text in your
-  app:</p>
+  (typically about 10 feet away) makes it harder for users to read text. Users also don't expect to
+  read much in a TV environment. Follow these tips for the best handling of text in your app:</p>
 
 <ul>
   <li>Break text into small chunks that users can quickly scan.</li>
   <li>Use light text on a dark background. This style is easier to read on a TV.</li>
   <li>Avoid lightweight fonts or fonts that have both very narrow and very broad
-      strokes. Use simple sans-serif fonts and use anti-aliasing to increase readability.</li>
-  <li>Use layout-relative sizing rather than absolute sizing and density-independent
+      strokes. Use simple sans-serif fonts and anti-aliasing to increase readability.</li>
+  <li>Use layout-relative sizing rather than absolute sizing, and density-independent
       pixel units instead of absolute pixel units.</li>
-</ul>
\ No newline at end of file
+</ul>
diff --git a/docs/html/preview/tv/games/index.jd b/docs/html/preview/tv/games/index.jd
new file mode 100644
index 0000000..b9de3a4
--- /dev/null
+++ b/docs/html/preview/tv/games/index.jd
@@ -0,0 +1,70 @@
+page.title=Games on TV
+page.tags="controller"
+
+@jd:body
+
+<p>This section complements the [larger best-practices guidance for designing for Android TV](TODO, use formal name of referenced doc, and add link). It assumes that you have read that guidance, and seeks to minimize repetition.</p>
+
+<h2>Overview</h2>
+<p>Because of factors including its large size, its control scheme, and its nature as a shared display, the television screen presents a number of considerations that may be new to mobile developers. This document breaks these considerations down into five sections:</p>
+<ul>
+<li>Display</li>
+<li>Control</li>
+<li>Manifest</li>
+<li>Google Play Game Services</li>
+<li>Web</li>
+</ul>
+<h2>Display</h2>
+<p>Large and centrally situated, the television screen imposes limitations, but also opens up new opportunities for immersive gameplay.</p>
+<h3>A shared display</h3>
+<p>A living-room TV poses design challenges for multiplayer games, in that all players can see everything. This issue is especially germane to games (such as card games or strategy games) that rely on each player’s possession of hidden information.</p>
+<p>Some mechanisms you can implement to address the problem of one player’s “eavesdropping” on another’s information are:</p>
+<ul>
+<li>A player might place a "blinder" on the screen to help conceal information. For example, in a turn-based game like a word or card game, one player at a time might view the display. When the player finishes a move, the game allows him or her to cover the screen with a “blinder” that blocks anyone from viewing secret information. When the next player begins a turn, the blinder opens to reveal his or her own information.</li>
+<li>A second screen, such as a handset or larger device, can enable a player to conceal information. For information on implementing second-screen support, see <a href="http://developer.android.com/reference/android/app/Presentation.html">Presentation</a> on the Android developer site.</li>
+</ul>
+<h3>No touch interface</h3>
+<p>A television does not have a touch interface. Your game design, therefore, need not take into account the possibility that a player’s controlling fingers might block the on-screen action. You can assume constant visibility of the entire viewing area.</p>
+<p>See the <a href=#control>Control</a> section in this document and in [Design for TV](TODO, use formal name of referenced doc, and add link) for more implications of the lack of touch interface.</p>
+<h3>Landscape display</h3>
+<p>In mobile-device terms, a TV is always “sideways.” You can’t turn it, and there is no portrait orientation. You should always be designing your TV games to be displayed in landscape mode.</p>
+<a id=control><h2>Control</h2>
+<p>Without a touch interface, it's even more important than usual to get your controls right, so that players find them intuitive and fun to use. The separation of controller from device also introduces some other issues to pay attention to, like keeping track of multiple players' controllers, and handling disconnects gracefully.</p>
+<h3>D-pad</h3>
+<p>Because of the lack of touch interface, you should be planning your control scheme based on a D-pad. Some key points to keep in mind include:</p>
+<p>The player needs to use the gamepad in all aspects of the game&ndash;not just controlling core gameplay, but also navigating menus and ads. For this reason, you should also ensure that your Android TV game does not refer to a touch interface: for example, an Android TV game cannot tell a player to "Tap to skip".</p>
+<p>You can avoid unhappy surprises (and resulting low ratings) by using your Play Store description to communicate to the player any expectations about controllers. If a game is better suited to a gamepad with a joystick than one with only a D-pad, you should make this clear. A player who uses an ill-suited controller for a game is likely to have a subpar experience&ndash;and penalize your game in the ratings.</p>
+<p>You can also help ensure a good player experience by ensuring that button mapping is intuitive and flexible. For example, you can adhere to accepted custom by using the A button to <code>Accept</code>, and the B button to <code>Cancel</code>. You can also offer flexibility in the form of remappability. For more information on button mapping, see <a href="http://developer.android.com/training/game-controllers/controller-input.html">Handling Controller Actions</a>.</p>
+<p>Your game can also contribute to a good match between controller and game by querying the controller about its capabilities. For example, you may intend for a player to steer an object by waving the controller in the air. If a player's controller lacks accelerometer and gyroscope hardware, however, waving will not work. But when your game queries the controller and discovers that motion detection is not supported, it can switch over to an alternative, available control scheme.</p>
+<p>For more information on querying controller capabilities, see <a href="http://developer.android.com/training/game-controllers/compatibility.html">Supporting Controllers Across Android Versions</a>.</p>
+<h3>Back-button behavior</h3>
+<p>The Back button should never act as a toggle. For example, do not use it to both open and close a menu. Its behavior should only be linear. For example: Game play &gt; Game pause screen &gt; Game main screen &gt; Android home screen.</p>
+<p>With this principle of "linear navigation" in mind, you <b>may</b> use the back button to leave an in-game menu (opened by a different button) and return to gameplay.</p>
+<h3>Handling multiple controllers</h3>
+<p>When multiple players are playing a game, each with his or her own controller, it is important to map each player-controller pair. For information on how to implement controller-number identification, see <a href="http://developer.android.com/reference/android/view/InputDevice.html#getControllerNumber(">Input Devices</a>) on the Android developer site.</p>
+<h3>Handling disconnects</h3>
+<p>When a controller is disconnected in the middle of gameplay, the game should pause, and a dialog should appear prompting the disconnected player to reconnect his or her controller.</p>
+<p>The dialog should also offer troubleshooting tips (e.g., "Check your Bluetooth connection").</p>
+<h2>Manifest</h2>
+<p>Games are displayed in a separate row from regular apps in the launcher. Android TV uses the <code>android:isGame</code> flag to differentiate games from non-game apps. You can assign it a value of either <code>true</code> or <code>false</code>. For example:</p>
+<pre class="fragment">&lt;application&gt;
+ . . .
+ &lt;meta-data android:name="isGame" android:value=["true" | "false"]/&gt;
+android:isGame=["true" | "false"] &gt;
+ . . .
+&lt;/application&gt;
+</pre><h2>Google Play Game Services</h2>
+<p>If your game integrates Google Play Game Services, you should keep in mind a number of considerations pertaining to achievements, sign-on, saving games, and multiplayer play.</p>
+<h3>Achievements</h3>
+<p>Your game should include at least five (earnable) achievements. Only a user controlling gameplay from a supported input device should be able to earn achievements.</p>
+<h3>Sign-on</h3>
+<p>Your game should attempt to sign the user in on launch. If the player declines sign-in several times in a row, your game should stop asking.</p>
+<h3>Saving</h3>
+<p>We highly recommend using Play Services cloud save to store your game save. Your game should bind game saves to a specific Google account, so as to be uniquely identifiable even across devices: Whether the player is using a handset or a TV, the game should be able to pull the same game-save information from his or her account.</p>
+<p>You should also provide an option in your game's UI to prompt the player to destroy save data. You might put the option in the game's <code>Settings</code> screen.</p>
+<h3>Multiplayer experience</h3>
+<p>A game offering a multiplayer experience must allow at least two players to enter a room.</p>
+<h2>Web</h2>
+<p>Android TV games do not support a full web browser. You should therefore avoid using generic URLs in your game.</p>
+<p>Webviews will work for logins to services like Google+ and Facebook. </p>
+
diff --git a/docs/html/preview/tv/images/android-tv-remote.png b/docs/html/preview/tv/images/android-tv-remote.png
new file mode 100644
index 0000000..d15fbc5
--- /dev/null
+++ b/docs/html/preview/tv/images/android-tv-remote.png
Binary files differ
diff --git a/docs/html/preview/tv/images/home-recommendations.png b/docs/html/preview/tv/images/home-recommendations.png
new file mode 100644
index 0000000..ef97145
--- /dev/null
+++ b/docs/html/preview/tv/images/home-recommendations.png
Binary files differ
diff --git a/docs/html/preview/tv/index.jd b/docs/html/preview/tv/index.jd
new file mode 100644
index 0000000..dd35908
--- /dev/null
+++ b/docs/html/preview/tv/index.jd
@@ -0,0 +1,22 @@
+page.title=Android TV Apps
+
+@jd:body
+
+<p>Android offers a rich user experience that's optimized for apps running on large screen
+  devices, such as high-definition televisions. Apps on TV offer new opportunities to
+  delight your users from the comfort of their couch.</p>
+
+<p>This guide helps you build apps for TV devices, including:</p>
+
+<ul>
+  <li>How to set up your development environment</li>
+  <li>How to build user interfaces for TV</li>
+  <li>Guidelines for building games for TV</li>
+</ul>
+
+<p>Prepare your app for its big screen debut!</p>
+
+<p>
+  <strong><a href="{@docRoot}preview/tv/start/index.html">Get Started &gt;</a></strong>
+</p>
+
diff --git a/docs/html/preview/tv/start/hardware-features.jd b/docs/html/preview/tv/start/hardware-features.jd
new file mode 100644
index 0000000..ddec496
--- /dev/null
+++ b/docs/html/preview/tv/start/hardware-features.jd
@@ -0,0 +1,183 @@
+page.title=Hardware Features on TV
+page.tags="unsupported"
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+  <h2>In this document</h2>
+  <ol>
+    <li><a href="#unsupported-features">Unsupported Hardware Features</a></li>
+    <li><a href="#workaround-features">Handling Unsupported Features</a></li>
+    <li><a href="#check-features">Checking Available Features</a>
+      <ol>
+        <li><a href="#no-touchscreen">Touch screen</a></li>
+        <li><a href="#no-camera">Camera</a></li>
+        <li><a href="#no-gps">GPS</a></li>
+      </ol>
+
+    </li>
+  </ol>
+</div>
+</div>
+
+<p>TVs do not have some of the hardware features found on other Android devices.
+Touch screens, cameras, and GPS receivers are some of the most commonly used hardware features
+which are typically not available on a TV. When you build an app for TV, you must carefully
+consider if your app can handle not having these features and, if necessary, work around them.</p>
+
+<p>This guide discusses the hardware features not available on TV devices and shows you how to
+work around those limitations in your app. For more information on filtering and declaring
+features in the manifest, see the
+<a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">uses-feature</a> guide.</p>
+
+
+<h2 id="unsupported-features">Unsupported Hardware Features</h2>
+
+<p>TVs have a different purpose from other devices, and so they do not have hardware
+features that other Android-powered devices often have. For this reason, the Android system
+does not support the following features for a TV device:
+
+<table>
+<tr>
+<th>Hardware</th>
+<th>Android feature descriptor</th>
+</tr>
+<tr>
+<td>Camera</td>
+<td>android.hardware.camera</td>
+</tr>
+<tr>
+<td>GPS</td>
+<td>android.hardware.location.gps</td>
+</tr>
+<tr>
+<td>Microphone</td>
+<td>android.hardware.microphone</td>
+</tr>
+<tr>
+<td>Near Field Communications (NFC)</td>
+<td>android.hardware.nfc</td>
+</tr>
+<tr>
+<td>Telephony</td>
+<td>android.hardware.telephony</td>
+</tr>
+<tr>
+<td>Touchscreen</td>
+<td>android.hardware.touchscreen</td>
+</tr>
+</table>
+</p>
+
+
+<h2 id="check-features">Checking Available Features</h2>
+
+<p>To check if a feature is available at runtime, call {@link
+  android.content.pm.PackageManager#hasSystemFeature(String)}. This method takes a single string
+  argument that specifies the feature you want to check. For example, to check for a touch screen,
+  use {@link android.content.pm.PackageManager#hasSystemFeature(String)} with the argument
+  {@link android.content.pm.PackageManager#FEATURE_TOUCHSCREEN}.</p>
+
+<p>The following code example demonstrates how to detect the availability of a hardware features
+  at runtime:</p>
+
+<pre>
+// Check if the telephony hardware feature is available.
+if (getPackageManager().hasSystemFeature("android.hardware.telephony")) {
+    Log.d("Mobile Test", "Running on phone");
+// Check if android.hardware.touchscreen feature is available.
+} else if (getPackageManager().hasSystemFeature("android.hardware.touchscreen")) {
+    Log.d("Tablet Test", "Running on devices that don't support telephony but "+
+            "do have a touch screen.");
+} else {
+    Log.d("TV Test", "Running on a TV!");
+}
+</pre>
+
+<p class="note">
+  <strong>Note:</strong> You can also use the {@link android.app.UiModeManager#getCurrentModeType
+  UiModeManager.getCurrentModeType()} method to detect the current platform type. For TV devices,
+  this method returns a value of {@link android.content.res.Configuration#UI_MODE_TYPE_TELEVISION
+  Configuration.UI_MODE_TYPE_TELEVISION}.
+</p>
+
+
+<h2 id="workaround-features">Handling Unsupported Features</h2>
+
+<p>Depending on the design and functionality of your app, you may be able to work around certain
+  hardware features being unavailable. This section discusses how to work around specific hardware
+  features.</p>
+
+
+<h3 id="no-touchscreen">Touch screen</h3>
+
+<p>Android doesn't support touch screen interaction for TV devices, since most TVs don't have touch
+  screens, and using a touch screen is not consistent with a viewing environment where the user is
+  seated 10 feet away from the display.</p>
+
+<p>On TV devices, you should work around this limitation by supporting navigation using a directional
+  pad (D-pad) on TV remote control. For more information on properly supporting navigation using
+  TV-friendly controls, see <a href="{@docRoot}preview/tv/ui/navigation.html">Navigation for
+  TV</a>.</p>
+
+<p>You can explicitly declare if your application requires (or does not require) a touch screen
+  by including the following entry in your manifest:</p>
+
+<pre>
+&lt;uses-feature android:name="android.hardware.touchscreen"
+        android:required="false"/&gt;
+</pre>
+
+
+<h3 id="no-camera">Camera</h3>
+
+<p>Although a TV typically does not have a camera, you can still provide a photography-related
+  application on a TV. For example, if you have an app that takes, views and edits photos, you can
+  disable its picture-taking functionality for TVs and still allow users to view and even edit
+  photos. If you decide that you want to enable your camera-related application to work on a
+  TV device without a camera, you can add an attribute to your app manifest declaring that
+  a camera is not required by your app:</p>
+
+<pre>
+&lt;uses-feature android:name="android.hardware.camera" android:required="false" /&gt;
+</pre>
+
+<p>If you enable your application to run without a camera, you should add code to your application
+that detects if the camera feature is available and makes adjustments to the operation of your app.
+The following code example demonstrates how to detect the presence of a camera:</p>
+
+<pre>
+// Check if the camera hardware feature is available.
+if (getPackageManager().hasSystemFeature("android.hardware.camera")) {
+    Log.d("Camera test", "Camera available!");
+} else {
+    Log.d("Camera test", "No camera available. View and edit features only.");
+}
+</pre>
+
+
+<h3 id="no-gps">GPS</h3>
+
+<p>TVs are stationary, indoor devices, and do not have built-in global positioning system (GPS)
+  receivers. If your application uses location information, you can still allow users to search
+  for a location, or use a static location provider such as a zip code configured during the
+  TV device setup.</p>
+
+<pre>
+LocationManager locationManager = (LocationManager) this.getSystemService(
+        Context.LOCATION_SERVICE);
+Location location = locationManager.getLastKnownLocation("static");
+Geocoder geocoder = new Geocoder(this);
+Address address = null;
+
+try {
+  address = geocoder.getFromLocation(location.getLatitude(),
+          location.getLongitude(), 1).get(0);
+  Log.d("Zip code", address.getPostalCode());
+
+} catch (IOException e) {
+  Log.e(TAG, "Geocoder error", e);
+}
+</pre>
+
diff --git a/docs/html/preview/tv/start/index.jd b/docs/html/preview/tv/start/index.jd
new file mode 100644
index 0000000..11d6ad3
--- /dev/null
+++ b/docs/html/preview/tv/start/index.jd
@@ -0,0 +1,233 @@
+page.title=Get Started with TV Apps
+page.tags="leanback","recyclerview","launcher"
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+  <h2>In this document</h2>
+  <ol>
+    <li><a href="#prerequisites">Prerequisites</a></li>
+    <li><a href="#dev-project">Setup a TV Project</a>
+      <ul>
+        <li><a href="#tv-activity">Create a TV Activity</a></li>
+        <li><a href="#tv-libraries">Add TV Support Libraries</a></li>
+      </ul>
+    </li>
+    <li><a href="#build-it">Build TV Apps</a></li>
+    <li><a href="#run">Run TV Apps</a></li>
+
+  </ol>
+</div>
+</div>
+
+<p>This guide describes how to prepare your development environment and projects for building
+  TV apps, including updating your existing app to run on TV devices.</p>
+
+
+<h2 id="prerequisites">Prerequisites</h2>
+
+<p>Before you begin setting up to build apps for TV, you must:</p>
+
+<ul>
+  <li><strong><a href="{@docRoot}preview/setup-sdk.html">
+    Set up the Preview SDK</a></strong>
+    <br>
+    The preview SDK provides the developer tools needed to build and test apps for TV.
+  </li>
+  <li><strong><a href="{@docRoot}preview/setup-sdk.html#project">
+    Create a Preview SDK Project</a></strong>
+    <br>
+    In order to access new APIs for TV devices, you must create a project that targets the preview
+    release level or modify an existing project to target the preview release.
+  </li>
+</ul>
+
+
+<h2 id="dev-project">Set up a TV Project</h2>
+
+<p>TV apps use the same structure as those for phones and tablets. This means you can modify
+  your existing apps to also run on TV devices or create new apps based on what you already know
+  about building apps for Android. This section discusses how to modify an existing app, or create a
+  new one, to run on TV devices.</p>
+
+<p>These are the main steps to creating an app that runs on TV devices. Only the first
+  is required:</p>
+
+<ul>
+  <li><strong>Activity for TV</strong> - (Required) In your application manifest, you must
+    declare an activity that is intended to run on TV devices.</li>
+  <li><strong>TV Support Libraries</strong> - (Optional) There are several Support Libraries
+    available for TV devices that provide widgets for building user interfaces.</li>
+</ul>
+
+
+<h3 id="tv-activity">Create a TV Activity</h3>
+
+<p>An application intended to run on TV devices must declare a launcher activity for TV
+  in its manifest using a {@code android.intent.category.LEANBACK_LAUNCHER} intent filter.
+  This filter identifies your app as being built for TV, enabling it to be displayed in the
+  Google Play store app running on TV devices. Declaring this intent also identifies which activity
+  in your app should be launched when a user selects its icon on the TV home screen.</p>
+
+<p class="caution">
+  <strong>Caution:</strong> If you do not include the {@code LEANBACK_LAUNCHER} intent filter in
+  your app, it is not visible to users running the Google Play store on TV devices. Also, if your
+  app does not have this filter when you load it onto a TV device using developer tools, the app
+  does not appear in the TV user interface.
+</p>
+
+<p>The following code snippet shows how to include this intent filter in your manifest:</p>
+
+<pre>
+&lt;application&gt;
+  ...
+  &lt;activity
+    android:name=&quot;com.example.android.MainActivity&quot;
+    android:label=&quot;@string/app_name&quot; &gt;
+
+    &lt;intent-filter&gt;
+      &lt;action android:name=&quot;android.intent.action.MAIN&quot; /&gt;
+      &lt;category android:name=&quot;android.intent.category.LAUNCHER&quot; /&gt;
+    &lt;/intent-filter&gt;
+  &lt;/activity&gt;
+
+  &lt;activity
+    android:name=&quot;com.example.android.<strong>TvActivity</strong>&quot;
+    android:label=&quot;&#64;string/app_name&quot;
+    android:theme=&quot;&#64;android:style/Theme.Leanback&quot;&gt;
+
+    &lt;intent-filter&gt;
+      &lt;action android:name=&quot;android.intent.action.MAIN&quot; /&gt;
+      &lt;category android:name="<strong>android.intent.category.LEANBACK_LAUNCHER</strong>" /&gt;
+    &lt;/intent-filter&gt;
+
+  &lt;/activity&gt;
+&lt;/application&gt;
+</pre>
+
+<p>The second activity manifest entry in the example above specifies that activity as
+  the main one when your app launches on an TV device.</p>
+
+<p>If you have an existing app that you are modifying for TV use, your app should not use the same
+  activity layout for TV that it does for phones and tablets. The user interface of your TV app (or
+  TV portion of your existing app) should provide a simpler interface that can be easily navigated
+  using a remote control from a couch. For guidelines on designing an app for TV, see the
+  <a href="{@docRoot}design/tv/index.html">TV Design</a> guide.  For more instructions on
+  developing a user interface appropriate to TV, see the
+  <a href="{@docRoot}preview/tv/ui/index.html">TV User Interface</a> guide.
+</p>
+
+
+<h3 id="tv-libraries">Add TV Support Libraries</h3>
+
+<p>The Preview SDK includes support libraries that are intended for use with TV apps. These
+  libraries provide APIs and user interface widgets for use on TV devices. The libraries are
+  located in the {@code &lt;sdk&gt;/extras/android/support/} directory where you installed the
+  Preview SDK. Here is a list of the libraries and their general purpose:</p>
+
+<ul>
+  <li><strong>v17 leanback library</strong> - Provides user interface widgets for TV, including
+    {@code BrowseFragment}, {@code DetailsFragment}, and {@code SearchFragment}.
+    <ul>
+      <li>SDK location: {@code &lt;sdk&gt;/extras/android/support/v17/leanback}</li>
+      <li>Gradle dependency: {@code com.android.support:leanback-v17:20.0.+}</li>
+      <li>Contains resources: Yes</li>
+    </ul>
+  </li>
+  <li><strong>v7 recyclerview library</strong> - Provides classes for managing display of long
+  lists in a memory efficient manner. Several classes in the v17 leanback library depend on the
+  classes in this library.
+    <ul>
+      <li>SDK location: {@code &lt;sdk&gt;/extras/android/support/v7/recyclerview}</li>
+      <li>Gradle dependency: {@code com.android.support:recyclerview-v7:20.0.+}</li>
+      <li>Contains resources: No</li>
+    </ul>
+  </li>
+</ul>
+
+<p class="note">
+  <strong>Note:</strong> You are not required to use these support libraries for your TV app.
+  However, we strongly recommend using them, particularly for apps that provide a media catalog
+  browsing interface.
+</p>
+
+<p>If you decide to use the v17 leanback library for your app, you should note that it is
+  dependent on the <a href="{@docRoot}tools/support-library/features.html#v7-appcompat">v7
+  appcompat library</a>, which is, in turn, dependent on the
+  <a href="{@docRoot}tools/support-library/features.html#v4">v4 support library</a>. This means
+  that apps that use the leanback support library should include all of these support
+  libraries:</p>
+
+<ul>
+  <li>v17 leanback support library</li>
+  <li>v7 recyclerview support library</li>
+  <li>v7 appcompat support library</li>
+  <li>v4 support library</li>
+</ul>
+
+<p>Two of these libraries (v17 leanback and v7 appcompat) contain resources, which require
+  you to take specific steps to include them in app projects. For instructions on
+  importing a support library with resources, see
+  <a href="http://developer.android.com/tools/support-library/setup.html#libs-with-res">
+  Support Library Setup</a>.
+</p>
+
+
+<h2 id="build-it">Build TV Apps</h2>
+
+<p>After you have completed the steps described above, it's time to start building apps for
+  the big screen! Check out these additional topics to help you build your app for TV:
+
+<ul>
+  <li><a href="{@docRoot}preview/tv/ui/index.html">User Interface</a> - The user interface of
+    TV devices is different from those of other Android devices. See this topic to find out how
+    to build TV user interfaces and to learn about the widgets provided to simplify that task.
+  </li>
+  <li><a href="{@docRoot}preview/tv/games/index.html">Games for TV</a> - TV devices are great
+    platforms for games. See this topic for information on building great game experiences for
+    TV.</li>
+  <li><a href="{@docRoot}preview/tv/start/hardware-features.html">Hardware features</a> - TV
+    devices do not contain hardware features normally found on other Android devices. See this
+    topic for information on unsupported hardware features and what to do about them.
+  </li>
+</ul>
+
+
+<h2 id="run">Run TV Apps</h2>
+
+<p>Running your app is an important part of the development process. The AVD Manager in the
+  Android SDK provides the device definitions that allows you to create virtual TV devices for
+  running and testing your applications.</p>
+
+<p>To create an virtual TV device:</p>
+
+<ol>
+  <li>Start the AVD Manager. For more information, see the
+    <a href="{@docRoot}tools/help/avd-manager.html">AVD Manager</a> help.</li>
+  <li>In the AVD Manager dialog, click the <strong>Device Definitions</strong> tab.</li>
+  <li>Select one of the Android TV device definitions, such as
+    <strong>Large Android TV</strong>, and click <strong>Create AVD</strong>.</li>
+  <li>Select the emulator options and click <strong>OK</strong> to create the AVD.
+    <p class="note">
+      <strong>Note:</strong> For best performance of the TV emulator device, enable the <strong>Use
+      Host GPU</strong> option and CPU platform image that supports hardware acceleration. For
+      more information on hardware acceleration of the emulator, see
+      <a href="{@docRoot}tools/devices/emulator.html#acceleration">Using the Emulator</a>.
+    </p>
+  </li>
+</ol>
+
+<p>To test your application on the virtual TV device:</p>
+
+<ol>
+  <li>Compile your TV application in your development environment.</li>
+  <li>Run the application from your development environment and choose the TV virtual device as
+  the target.</li>
+</ol>
+
+<p>For more information about using emulators see, <a href="{@docRoot}tools/devices/emulator.html">
+Using the Emulator</a>. For more information about deploying apps to emulators from
+Eclipse with ADT, see <a href="{@docRoot}http://developer.android.com/tools/building/building-eclipse.html">
+Building and Running from Eclipse with ADT</a>.</p>
+
diff --git a/docs/html/preview/tv/ui/browse.jd b/docs/html/preview/tv/ui/browse.jd
new file mode 100644
index 0000000..d7a1fb6
--- /dev/null
+++ b/docs/html/preview/tv/ui/browse.jd
@@ -0,0 +1,199 @@
+page.title=BrowseFragment
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+  <h2>In this document</h2>
+  <ol>
+    <li><a href="#layout">Media Browse Layout</a></li>
+    <li><a href="#lists">Displaying Media Lists</a></li>
+    <li><a href="#background">Updating the Background</a></li>
+  </ol>
+
+</div>
+</div>
+
+<p>The <a href="{@docRoot}preview/tv/start/index.html#tv-libraries">Leanback support library</a>
+  provides several APIs for displaying and browsing media catalogs
+  on the TV devices. This guide discusses how to use the classes provided by this library to
+  implement a user interface for browsing music or videos from your app's media catalog.</p>
+
+
+<h2 id="layout">Media Browse Layout</h2>
+
+<p>The {@code BrowseFragment} class in the Leanback support library allows you to create a primary
+  layout for browsing categories and rows of media items with a minimum of code. The following
+  example shows how to create a layout that contains a {@code BrowseFragment}:</p>
+
+<pre>
+&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+  android:layout_width=&quot;match_parent&quot;
+  android:layout_height=&quot;match_parent&quot;
+  android:orientation=&quot;vertical&quot;
+  &gt;
+
+  &lt;fragment
+      <strong>android:name="android.support.v17.leanback.app.BrowseFragment"</strong>
+      android:id=&quot;@+id/browse_fragment&quot;
+      android:layout_width=&quot;match_parent&quot;
+      android:layout_height=&quot;match_parent&quot;
+      /&gt;
+&lt;/LinearLayout&gt;
+</pre>
+
+<p>In order to work with this layout in an activity, retrieve the {@code BrowseFragment} element
+  from the layout. Use the methods in {@code BrowseFragment} to set display parameters such as the
+  icon, title and whether category headers are enabled. The following code sample demonstrates how
+  to set the layout parameters for a {@code BrowseFragment} in a layout:</p>
+
+<pre>
+public class BrowseMediaActivity extends Activity {
+
+    public static final String TAG ="BrowseActivity";
+
+    protected BrowseFragment mBrowseFragment;
+
+    &#64;Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.browse_fragment);
+
+        final FragmentManager fragmentManager = getFragmentManager();
+        <strong>mBrowseFragment = (BrowseFragment) fragmentManager.findFragmentById(
+                R.id.browse_fragment);</strong>
+
+        // Set display parameters for the BrowseFragment
+        mBrowseFragment.setHeadersState(BrowseFragment.HEADERS_ENABLED);
+        mBrowseFragment.setTitle(getString(R.string.app_name));
+        mBrowseFragment.setBadgeDrawable(getResources().getDrawable(R.drawable.ic_launcher));
+        mBrowseFragment.setBrowseParams(params);
+
+    }
+}
+</pre>
+
+
+<h2 id="lists">Displaying Media Lists</h2>
+
+<p>The {@code BrowseFragment} allows you to define and display browsable media content categories and
+  media items from a media catalog using adapters and presenters. Adapters enable you to connect to
+  local or online data sources that contain your media catalog information. Presenter classes hold
+  data about media items and provide layout information for displaying an item on screen.</p>
+
+<p>The following example code shows an implementation of a presenter for displaying string
+  data:</p>
+
+<pre>
+public class StringPresenter extends Presenter {
+    private static final String TAG = "StringPresenter";
+
+    public ViewHolder onCreateViewHolder(ViewGroup parent) {
+        TextView textView = new TextView(parent.getContext());
+        textView.setFocusable(true);
+        textView.setFocusableInTouchMode(true);
+        textView.setBackground(
+                parent.getContext().getResources().getDrawable(R.drawable.text_bg));
+        return new ViewHolder(textView);
+    }
+
+    public void onBindViewHolder(ViewHolder viewHolder, Object item) {
+        ((TextView) viewHolder.view).setText(item.toString());
+    }
+
+    public void onUnbindViewHolder(ViewHolder viewHolder) {
+        // no op
+    }
+}
+</pre>
+
+<p>Once you have constructed a presenter class for your media items, you can build and attach an
+  adapter to the {@code BrowseFragment} to display those items on screen for browsing by the user. The
+  following example code demonstrates how to construct an adapter to display categories and items
+  in those categories using the StringPresenter class shown in the previous code example:</p>
+
+<pre>
+private ArrayObjectAdapter mRowsAdapter;
+private static final int NUM_ROWS = 4;
+
+&#64;Override
+protected void onCreate(Bundle savedInstanceState) {
+    ...
+
+    buildRowsAdapter();
+}
+
+private void buildRowsAdapter() {
+    mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
+
+    for (int i = 0; i &lt; NUM_ROWS; ++i) {
+        ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(
+                new StringPresenter());
+        listRowAdapter.add("Media Item 1");
+        listRowAdapter.add("Media Item 2");
+        listRowAdapter.add("Media Item 3");
+        HeaderItem header = new HeaderItem(i, "Category " + i, null);
+        mRowsAdapter.add(new ListRow(header, listRowAdapter));
+    }
+
+    mBrowseFragment.setAdapter(mRowsAdapter);
+}
+</pre>
+
+<p>This example shows a static implementation of the adapters. A typical media browsing
+  application uses data from an online database or web service. For an example of a browsing
+  application that uses data retrieved from the web, see the
+  <a href="http://github.com/googlesamples/androidtv-leanback">Android TV</a> sample app.</p>
+
+
+<h2 id="background">Updating the Background</h2>
+
+<p>In order to add visual interest to a media-browsing app on TV, you can update the background
+  image as users browse through content. This technique can make interaction with your app feel more
+  cinematic and enjoyable for users.</p>
+
+<p>The Leanback support library provides a {@link
+  android.support.v17.leanback.app.BackgroundManager} class for changing the background of your TV
+  app activity. The following example shows how to create a simple method for updating the
+  background within your TV app activity:</p>
+
+<pre>
+protected void updateBackground(Drawable drawable) {
+    BackgroundManager.getInstance(this).setDrawable(drawable);
+}
+</pre>
+
+<p>Many of the existing media-browse apps automatically update the background as the user
+  navigates through media listings. In order to do this, you can set up a selection listener to
+  automatically update the background based on the user's current selection. The following example
+  shows you how to set up an {@link android.support.v17.leanback.widget.OnItemSelectedListener}
+  class to catch selection events and update the background:</p>
+
+<pre>
+protected void clearBackground() {
+    BackgroundManager.getInstance(this).setDrawable(mDefaultBackground);
+}
+
+protected OnItemSelectedListener getDefaultItemSelectedListener() {
+    return new OnItemSelectedListener() {
+        &#64;Override
+        public void onItemSelected(Object item, Row row) {
+            if (item instanceof Movie ) {
+                URI uri = ((Movie)item).getBackdropURI();
+                updateBackground(uri);
+            } else {
+                clearBackground();
+            }
+        }
+    };
+}
+</pre>
+
+<p class="note">
+  <strong>Note:</strong> The implementation above is a simple example shown for purposes of
+  illustration. When creating this function in your own app, you should consider running the
+  background update action in a separate thread for better performance. In addition, if you are
+  planning on updating the background in response to users scrolling through items, consider adding
+  a time to delay a background image update until the user settles on an item. This technique avoids
+  excessive background image updates.
+</p>
diff --git a/docs/html/preview/tv/ui/details.jd b/docs/html/preview/tv/ui/details.jd
new file mode 100644
index 0000000..8b8fa8b5
--- /dev/null
+++ b/docs/html/preview/tv/ui/details.jd
@@ -0,0 +1,214 @@
+page.title=DetailFragment
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+  <h2>In this document</h2>
+  <ol>
+    <li><a href="#details-presenter">Build a Details Presenter</a></li>
+    <li><a href="#details-fragment">Extend the Details Fragment</a>
+      <li><a href="#activity">Creating a Details Activity</a></li>
+      <li><a href="#item-listener">Listener for Clicked Items</a></li>
+    </li>
+  </ol>
+</div>
+</div>
+
+<p>The media browsing interface classes provided by the
+  <a href="{@docRoot}preview/tv/start/index.html#tv-libraries">Leanback support library</a>
+  include classes for displaying additional information about a media item, such as a description
+  or reviews, and for taking action on that item, such as purchasing it or playing its content. This
+  section discusses how to create a presenter class for media item details and extend the
+  {@code DetailsFragment} class to implement a details view for a media item when it
+  is selected by a user.
+</p>
+
+<p class="note">
+  <strong>Note:</strong> The implementation example shown here uses an additional activity to
+  contain the {@code DetailsFragment}. However, it is possible to avoid creating a second activity
+  by replacing the current {@code BrowseFragment} with a {@code DetailsFragment} within the <em>same</em>
+  activity using fragment transactions. For more information on using fragment transactions, see the
+  <a href="{@docRoot}training/basics/fragments/fragment-ui.html#Replace">Building a Dynamic
+    UI with Fragments</a> training.
+</p>
+
+
+<h2 id="details-presenter">Build a Details Presenter</h2>
+
+<p>In the media browsing framework provided for by the leanback support library, you use
+  presenter objects to control the display of data on screen, including media item details. The
+  framework provides the {@code AbstractDetailsDescriptionPresenter} class for this purpose, which
+  is a nearly complete implementation of the presenter for media item details. All you have to do is
+  implement the {@code onBindDescription()} method to bind the view fields to your data objects, as shown in
+  the following code sample:</p>
+
+<pre>
+public class DetailsDescriptionPresenter
+        extends AbstractDetailsDescriptionPresenter {
+
+    &#64;Override
+    protected void onBindDescription(ViewHolder viewHolder, Object itemData) {
+        MyMediaItemDetails details = (MyMediaItemDetails) itemData;
+        // In a production app, the itemData object contains the information
+        // needed to display details for the media item:
+        // viewHolder.getTitle().setText(details.getShortTitle());
+
+        // Here we provide static data for testing purposes:
+        viewHolder.getTitle().setText(itemData.toString());
+        viewHolder.getSubtitle().setText("2014   Drama   TV-14");
+        viewHolder.getBody().setText("Lorem ipsum dolor sit amet, consectetur "
+                + "adipisicing elit, sed do eiusmod tempor incididunt ut labore "
+                + " et dolore magna aliqua. Ut enim ad minim veniam, quis "
+                + "nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
+                + "commodo consequat.");
+    }
+}
+</pre>
+
+
+<h2 id="details-fragment">Extend the Details Fragment</h2>
+
+<p>When you use the {@code DetailsFragment} class for displaying your media item details, you
+  extend that class to provide additional content such as a preview image and actions for the media
+  item. You can also provide additional content, such as a list of related media items.</p>
+
+<p>The following example code demonstrates how to use the presenter class you created in the
+  previous section, add a preview image and actions for the media item being viewed. This example
+  also shows the addition of a related media items row, which appears below the details listing.</p>
+
+<pre>
+public class MediaItemDetailsFragment extends DetailsFragment {
+    private static final String TAG = "MediaItemDetailsFragment";
+    private ArrayObjectAdapter mRowsAdapter;
+
+    &#64;Override
+    public void onCreate(Bundle savedInstanceState) {
+        Log.i(TAG, "onCreate");
+        super.onCreate(savedInstanceState);
+
+        buildDetails();
+    }
+
+    private void buildDetails() {
+        ClassPresenterSelector selector = new ClassPresenterSelector();
+        // Attach your media item details presenter to the row presenter:
+        DetailsOverviewRowPresenter rowPresenter =
+            new DetailsOverviewRowPresenter(new DetailsDescriptionPresenter());
+
+        selector.addClassPresenter(DetailsOverviewRow.class, rowPresenter);
+        selector.addClassPresenter(ListRow.class,
+                new ListRowPresenter());
+        mRowsAdapter = new ArrayObjectAdapter(selector);
+
+        Resources res = getActivity().getResources();
+        DetailsOverviewRow detailsOverview = new DetailsOverviewRow(
+                "Media Item Details");
+
+        // Add images and action buttons to the details view
+        detailsOverview.setImageDrawable(res.getDrawable(R.drawable.jelly_beans));
+        detailsOverview.addAction(new Action(1, "Buy $9.99"));
+        detailsOverview.addAction(new Action(2, "Rent $2.99"));
+        mRowsAdapter.add(detailsOverview);
+
+        // Add a Related items row
+        ArrayObjectAdapter listRowAdapter = new ArrayObjectAdapter(
+                new StringPresenter());
+        listRowAdapter.add("Media Item 1");
+        listRowAdapter.add("Media Item 2");
+        listRowAdapter.add("Media Item 3");
+        HeaderItem header = new HeaderItem(0, "Related Items", null);
+        mRowsAdapter.add(new ListRow(header, listRowAdapter));
+
+        setAdapter(mRowsAdapter);
+    }
+}
+</pre>
+
+
+<h3 id="activity">Creating a Details Activity</h3>
+
+<p>Fragments such as the {@code DetailsFragment} must be contained within an activity in order
+  to be used for display. Creating an activity for your details view, separate from the browse
+  activity, enables you to invoke your details view using an Intent. This section explains how to
+  build an activity to contain your implementation of the detail view for your media items.</p>
+
+<p>Start creating the details activity by building a layout that references your implementation
+  of the {@code DetailsFragment}:</p>
+
+<pre>
+&lt;!-- file: res/layout/details.xml --&gt;
+
+&lt;fragment xmlns:android="http://schemas.android.com/apk/res/android"
+    <strong>android:name="com.example.android.mediabrowser.MediaItemDetailsFragment"</strong>
+    android:id="&#64;+id/details_fragment"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+/&gt;
+</pre>
+
+<p>Next, create an activity class that uses the layout shown in the previous code example:</p>
+
+<pre>
+public class DetailsActivity extends Activity
+{
+    &#64;Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        <strong>setContentView(R.layout.details);</strong>
+    }
+}
+</pre>
+
+<p>Finally, add this new activity to the manifest. Remember to apply the Leanback theme to
+  ensure that the user interface is consistent with the media browse activity:</p>
+
+<pre>
+&lt;application&gt;
+  ...
+
+  &lt;activity android:name=".DetailsActivity"
+    android:exported="true"
+    <strong>android:theme="@style/Theme.Leanback"/&gt;</strong>
+
+&lt;/application&gt;
+</pre>
+
+
+<h3 id="item-listener">Listener for Clicked Items</h3>
+
+<p>After you have implemented the {@code DetailsFragment}, you must modify your main media
+  browsing view to move to your details view when a user clicks on a media item. In order to enable
+  this behavior, add an {@code OnItemClickedListener} object to the BrowseFragment that fires an
+  intent to start the item details activity.</p>
+
+<p>The following example shows how to implement a listener to start the details view when a user
+  clicks a media item in the main media browsing activity:</p>
+
+<pre>
+public class BrowseMediaActivity extends Activity {
+    ...
+
+    &#64;Override
+    protected void onCreate(Bundle savedInstanceState) {
+        ...
+
+        // create the media item rows
+        buildRowsAdapter();
+
+        // add a listener for selected items
+        mBrowseFragment.setOnItemClickedListener(
+            new OnItemClickedListener() {
+                &#64;Override
+                public void onItemClicked(Object item, Row row) {
+                    System.out.println("Media Item clicked: " + item.toString());
+                    Intent intent = new Intent(BrowseMediaActivity.this,
+                            DetailsActivity.class);
+                    // pass the item information
+                    intent.getExtras().putLong("id", item.getId());
+                    startActivity(intent);
+                }
+            });
+    }
+}
+</pre>
diff --git a/docs/html/preview/tv/ui/in-app-search.jd b/docs/html/preview/tv/ui/in-app-search.jd
new file mode 100644
index 0000000..3dbfcd2
--- /dev/null
+++ b/docs/html/preview/tv/ui/in-app-search.jd
@@ -0,0 +1,111 @@
+page.title=Adding Search to TV Apps
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+  <h2>In this document</h2>
+  <ol>
+    <li><a href="#add-search-ui">Add Search User Interface</a></li>
+  </ol>
+
+</div>
+</div>
+
+
+<p>Users frequently have specific content in mind when using a media app. A search interface can
+  help your users get to the content they want faster than browsing. The Leanback library provides a
+  set of classes to enable a standard search interface within your app that is consistent with other
+  search functions on TV and provides features such as voice input.</p>
+
+<h2 id="add-search-ui">Add Search User Interface</h2>
+<p>When you use the BrowseFragment class for your media browsing interface, you can enable the
+  search icon by setting an OnClickListener to the BrowseFragment object. The following sample code
+  demonstrates this technique.</p>
+
+<pre>
+&#64;Override
+public void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+    setContentView(R.layout.browse_activity);
+
+    mBrowseFragment = (BrowseFragment)
+            getFragmentManager().findFragmentById(R.id.browse_fragment);
+
+    ...
+
+    mBrowseFragment.setOnSearchClickedListener(new View.OnClickListener() {
+        &#64;Override
+        public void onClick(View view) {
+            Intent intent = new Intent(BrowseActivity.this, SearchActivity.class);
+            startActivity(intent);
+        }
+    });
+
+    mBrowseFragment.setAdapter(buildAdapter());
+}
+</pre>
+
+<p class="note">
+  <strong>Note:</strong> You can set the color of the search icon using the
+  {@code setSearchAffordanceColor()} method of {@code BrowseFragment}.
+</p>
+
+<p>When a user selects the search icon, the system invokes a search activity via the defined
+  Intent. Your search activity should use a linear layout containing a SearchFragment. This fragment
+  must also implement the SearchFragment.SearchResultProvider interface in order to display the
+  results of a search. The following code sample shows how to extend the SearchFragment class to
+  provide a search interface and results:</p>
+
+<pre>
+public class MySearchFragment extends SearchFragment
+        implements SearchFragment.SearchResultProvider {
+
+    private static final int SEARCH_DELAY_MS = 300;
+    private ArrayObjectAdapter mRowsAdapter;
+    private Handler mHandler = new Handler();
+    private SearchRunnable mDelayedLoad;
+
+    &#64;Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        mRowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
+        setSearchResultProvider(this);
+        setOnItemClickedListener(getDefaultItemClickedListener());
+        mDelayedLoad = new SearchRunnable();
+    }
+
+    &#64;Override
+    public ObjectAdapter getResultsAdapter() {
+        return mRowsAdapter;
+    }
+
+    &#64;Override
+    public boolean onQueryTextChange(String newQuery) {
+        mRowsAdapter.clear();
+        if (!TextUtils.isEmpty(newQuery)) {
+            mDelayedLoad.setSearchQuery(newQuery);
+            mHandler.removeCallbacks(mDelayedLoad);
+            mHandler.postDelayed(mDelayedLoad, SEARCH_DELAY_MS);
+        }
+        return true;
+    }
+
+    &#64;Override
+    public boolean onQueryTextSubmit(String query) {
+        mRowsAdapter.clear();
+        if (!TextUtils.isEmpty(query)) {
+            mDelayedLoad.setSearchQuery(query);
+            mHandler.removeCallbacks(mDelayedLoad);
+            mHandler.postDelayed(mDelayedLoad, SEARCH_DELAY_MS);
+        }
+        return true;
+    }
+}
+</pre>
+
+<p>This example code shown above is meant to be used with a separate {@code SearchRunnable}
+  class that runs the search query on a separate thread. This technique keeps potentially
+  slow-running queries from blocking the main user interface thread.</p>
+
diff --git a/docs/html/preview/tv/ui/index.jd b/docs/html/preview/tv/ui/index.jd
new file mode 100644
index 0000000..c861ec2
--- /dev/null
+++ b/docs/html/preview/tv/ui/index.jd
@@ -0,0 +1,40 @@
+page.title=User Interfaces for TV
+
+@jd:body
+
+
+<p>
+  Building an effective and engaging user interface for TV devices requires a firm understanding of what works well
+  in the context of a living room. Imagine a large screen that can be seen by many people at the
+  same time, controlled with a few buttons by users with limited attention, and you start to see the
+  challenges and opportunities of building an app for TV. Building apps for this environment
+  requires a different approach and different tools.</p>
+
+<p>This section discusses how to build a living room experience with your app, including
+  implementation instructions and creating user interface widgets built for TV. Also check out
+  <a href="{@docRoot}design/tv/index.html">Design for TV</a> for information and inspiration
+  on creating engaging user interfaces for TV devices.</p>
+
+<h2>Topics</h2>
+
+<dl>
+  <dt><b><a href="layouts.html">Layouts</a></b></dt>
+    <dd>Learn how to build app layouts for TV screens.</dd>
+
+  <dt><b><a href="navigation.html">Navigation</a></b></dt>
+    <dd>Learn how to build navigation for TV devices.</dd>
+
+  <dt><b><a href="browse.html">BrowseFragment</a></b></dt>
+    <dd>Learn how to use this fragment to build a browsing interface for media catalogs.</dd>
+
+  <dt><b><a href="details.html">DetailsFragment</a></b></dt>
+    <dd>Learn how to use this fragment to build a details page for media items.</dd>
+
+  <dt><b><a href="in-app-search.html">In-App Search</a></b></dt>
+    <dd>Learn how to use a built-for-TV user interface for searching within your app.</dd>
+
+  <dt><b><a href="recommendations.html">Recommendations</a></b></dt>
+    <dd>Learn how your app can contribute to the list of recommendations appearing on the home
+      screen and get your content noticed by users.</dd>
+</dl>
+
diff --git a/docs/html/preview/tv/ui/layouts.jd b/docs/html/preview/tv/ui/layouts.jd
new file mode 100644
index 0000000..0659826
--- /dev/null
+++ b/docs/html/preview/tv/ui/layouts.jd
@@ -0,0 +1,298 @@
+page.title=Layouts for TV
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+  <h2>In this document</h2>
+  <ol>
+    <li><a href="#themes">Themes</a>
+      <ol>
+        <li><a href="#leanback-theme">Leanback Theme</a></li>
+        <li><a href="#notitle-theme">NoTitleBar Theme</a></li>
+      </ol>
+    </li>
+    <li><a href="#structure">Layout Structure</a>
+      <ol>
+        <li><a href="#overscan">Overscan</a></li>
+      </ol>
+    </li>
+    <li><a href="#visibility">Text and Controls Visibility</a></li>
+    <li><a href="#density-resources">Screen Density and Image Resources</a></li>
+    <li><a href="#anti-patterns">Layout Anti-Patterns</a></li>
+    <li><a href="#large-bitmaps">Handling Large Bitmaps</a></li>
+  </ol>
+
+</div>
+</div>
+
+<p>
+  A TV screen is typically viewed from about 10 feet away, and while it is much larger than most
+  other Android device displays, this type of screen does not provide the same level of precise
+  detail and color as a smaller device. These factors require that you create app layouts with
+  TV devices in mind in order to create a useful and enjoyable user experience.</p>
+
+<p>This guide provides direction and implementation details for building effective layouts inN
+  TV apps.</p>
+
+
+<h2 id="themes">Themes</h2>
+
+<p>Android <a href="{@docRoot}guide/topics/ui/themes.html">Themes</a> can provide a basis for
+  layouts in your TV apps. You should use a theme to modify the display of your app activities
+  that are meant to run on a TV device. This section explains which themes you should use.</p>
+
+
+<h3 id="leanback-theme">Leanback Theme</h3>
+
+<p>The Leanback library provides a standard theme for TV activities, called {@code
+  Leanback.Theme}, which establishes a consistent visual style for TV apps. Use of this theme is
+  recommended for most apps. This theme is recommended for any TV app that uses the Leanback
+  library classes. The following code sample shows how to apply this theme to a given
+  activity within an app:</p>
+
+<pre>
+&lt;activity
+  android:name="com.example.android.TvActivity"
+  android:label="&#64;string/app_name"
+  <strong>android:theme="&#64;style/Theme.Leanback"</strong>&gt;
+</pre>
+
+
+<h3 id="notitle-theme">NoTitleBar Theme</h3>
+
+<p>The title bar is a standard user interface element for Android apps on phones and tablets,
+  but it is not appropriate for TV apps. If you are not using the Leanback library classes,
+  you should apply this theme to your TV activities. The following code example from a TV app
+  manifest demonstrates how to apply this theme to remove the display of a title bar:
+</p>
+
+<pre>
+&lt;application&gt;
+  ...
+
+  &lt;activity
+    android:name="com.example.android.TvActivity"
+    android:label="&#64;string/app_name"
+    <strong>android:theme="&#64;android:style/Theme.NoTitleBar"</strong>&gt;
+    ...
+
+  &lt;/activity&gt;
+&lt;/application&gt;
+</pre>
+
+
+<h2 id="structure">Layout Structure</h2>
+
+<p>Layouts for TV devices should follow some basic guidelines to ensure they are usable and
+  effective on large screens. Follow these tips to build landscape layouts optimized for TV screens:
+</p>
+
+<ul>
+  <li>Build layouts with a landscape orientation. TV screens always display in landscape.</li>
+  <li>Put on-screen navigation controls on the left or right side of the screen and save the
+    vertical space for content.</li>
+  <li>Create UIs that are divided into sections, using <a
+    href="{@docRoot}guide/components/fragments.html"
+  >Fragments</a>, and use view groups like {@link android.widget.GridView} instead of {@link
+    android.widget.ListView} to make better use of the horizontal screen space.
+  </li>
+  <li>Use view groups such as {@link android.widget.RelativeLayout} or {@link
+    android.widget.LinearLayout} to arrange views. This approach allows the system to adjust the
+    position of the views to the size, alignment, aspect ratio, and pixel density of a TV screen.</li>
+  <li>Add sufficient margins between layout controls to avoid a cluttered UI.</li>
+</ul>
+
+
+<h3 id="overscan">Overscan</h3>
+
+<p>Layouts for TV have some unique requirements due to the evolution of TV standards and the
+  desire to always present a full screen picture to viewers. For this reason, TV devices may
+  clip the outside edge of an app layout in order to ensure that the entire display is filled.
+  This behavior is generally referred to as Overscan.</p>
+
+<p>In order to account for the impact of overscan and make sure that all the user interface
+  elements you place in a layout are actually shown on screen, you should incorporate a 10% margin
+  on all sides of your layout. This translates into a 27dp margin on the left and right edges and
+  a 48dp margin on the top and bottom of your base layouts for activities. The following
+  example layout demonstrates how to set these margins in the root layout for a TV app:
+</p>
+
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+  android:id="@+id/base_layout"
+  android:layout_width="match_parent"
+  android:layout_height="match_parent"
+  android:orientation="vertical"
+  android:layout_marginTop="27dp"
+  android:layout_marginLeft="48dp"
+  android:layout_marginRight="48dp"
+  android:layout_marginBottom="27dp" &gt;
+&lt;/LinearLayout&gt;
+</pre>
+
+<p class="caution">
+  <strong>Caution:</strong> Do not apply overscan margins to your layout if you are using the
+  Leanback Support Library {@code BrowseFragment} or related widgets, as those layouts already
+  incorporate overscan-safe margins.
+</p>
+
+
+<h2 id="visibility">Text and Controls Visibility</h2>
+
+<p>
+The text and controls in a TV app layout should be easily visible and navigable from a distance.
+Follow these tips to make them easier to see from a distance :
+</p>
+
+<ul>
+  <li>Break text into small chunks that users can quickly scan.</li>
+  <li>Use light text on a dark background. This style is easier to read on a TV.</li>
+  <li>Avoid lightweight fonts or fonts that have both very narrow and very broad strokes.
+  Use simple sans-serif fonts and anti-aliasing to increase readability.</li>
+  <li>Use Android's standard font sizes:
+<pre>
+&lt;TextView
+      android:id="@+id/atext"
+      android:layout_width="wrap_content"
+      android:layout_height="wrap_content"
+      android:gravity="center_vertical"
+      android:singleLine="true"
+      android:textAppearance="?android:attr/textAppearanceMedium"/&gt;
+</pre>
+  </li>
+  <li>Ensure that all your view widgets are large enough to be clearly visible to someone
+    sitting 10 feet away from the screen (this distance is greater for very large screens). The
+    best way to do this is to use layout-relative sizing rather than absolute sizing, and
+    density-independent pixel units instead of absolute pixel units. For example, to set the
+    width of a widget, use wrap_content instead of a pixel measurement, and to set the margin
+    for a widget, use dip instead of px values.</li>
+</ul>
+
+
+<h2 id="density-resources">Screen Density and Image Resources</h2>
+
+<p>The common high-definition TV display resolutions are 720p, 1080i, and 1080p.
+  Your TV layout should target a screen size of 1920 x 1080 pixels, and then allow the Android
+  system to downscale your layout elements to 720p if necessary. In general, downscaling
+  (removing pixels) does not degrade your layout presentation quality. However, upscaling can
+  cause display artifacts that degrade the quality of your layout and have a negative impact on
+  the user experience of your app.</p>
+
+<p>
+  To get the best scaling results for images, provide them as
+  <a href="{@docRoot}tools/help/draw9patch.html">9-patch image</a> elements if possible. If you
+  provide low quality or small images in your layouts, they will appear pixelated, fuzzy, or
+  grainy. This is not a good experience for the user. Instead, use high-quality images.
+</p>
+
+<p>
+  For more information on optimizing layouts and resources for large screens see
+  <a href="{@docRoot}training/multiscreen/index.html">Designing for multiple screens</a>.
+</p>
+
+
+<h2 id="anti-patterns">Layout Anti-Patterns</h2>
+
+<p>There are a few approaches to building layouts for TV that you should avoid because they do not
+work well and lead to bad user experiences. Here are some user interface approaches you
+should specifically <em>not</em> use when developing a layout for TV.
+</p>
+
+<ul>
+  <li><strong>Re-using phone or tablet layouts</strong> - Do not reuse layouts from a phone or
+    tablet app without modification. Layouts built for other Android device form factors are not
+    well suited for TV devices and should be simplified for operation on a TV.</li>
+  <li><strong>ActionBar</strong> - While this user interface convention is recommended for use
+    on phones and tablets, it is not appropriate for a TV interface. In particular, using an
+    action bar options menu (or any pull-down menu for that matter) is strongly discouraged, due
+    to the difficulty in navigating such a menu with a remote control.</li>
+  <li><strong>ViewPager</strong> - Sliding between screens can work great on a phone or tablet,
+    but don't try this on a TV!</li>
+
+</ul>
+
+<p>For more information on designing layouts that are appropriate to TV, see the
+  <a href="{@docRoot}design/tv/index.html">TV Design</a> guide.</p>
+
+
+<h2 id="large-bitmaps">Handling Large Bitmaps</h2>
+
+<p>TV devices, like any other Android device, have a limited amount of memory. If you build your
+  app layout with very high-resolution images or use many high-resolution images in the operation
+  of your app, it can quickly run into memory limits and cause out of memory errors.
+  To avoid these types of problems, follow these tips:</p>
+
+<ul>
+  <li>Load images only when they're displayed on the screen. For example, when displaying multiple images in
+      a {@link android.widget.GridView} or
+      {@link android.widget.Gallery}, only load an image when
+      {@link android.widget.Adapter#getView(int, View, ViewGroup) getView()}
+      is called on the View's {@link android.widget.Adapter}.
+  </li>
+  <li>Call {@link android.graphics.Bitmap#recycle()} on
+      {@link android.graphics.Bitmap} views that are no longer needed.
+  </li>
+  <li>Use {@link java.lang.ref.WeakReference} for storing references
+      to {@link android.graphics.Bitmap} objects in an in-memory
+      {@link java.util.Collection}.</li>
+  <li>If you fetch images from the network, use {@link android.os.AsyncTask}
+      to fetch and store them on the device for faster access.
+      Never do network transactions on the application's UI thread.
+  </li>
+  <li>Scale down large images to a more appropriate size as you download them;
+    otherwise, downloading the image itself may cause an out of memory exception.
+    The following sample code demonstrates how to scale down images while downloading:
+<pre>
+  // Get the source image's dimensions
+  BitmapFactory.Options options = new BitmapFactory.Options();
+  // This does not download the actual image, just downloads headers.
+  options.inJustDecodeBounds = true;
+  BitmapFactory.decodeFile(IMAGE_FILE_URL, options);
+  // The actual width of the image.
+  int srcWidth = options.outWidth;
+  // The actual height of the image.
+  int srcHeight = options.outHeight;
+
+  // Only scale if the source is bigger than the width of the destination view.
+  if(desiredWidth > srcWidth)
+    desiredWidth = srcWidth;
+
+  // Calculate the correct inSampleSize/scale value. This approach helps reduce
+  // memory use. This value should be a power of 2.
+  int inSampleSize = 1;
+  while(srcWidth / 2 > desiredWidth){
+    srcWidth /= 2;
+    srcHeight /= 2;
+    inSampleSize *= 2;
+  }
+
+  float desiredScale = (float) desiredWidth / srcWidth;
+
+  // Decode with inSampleSize
+  options.inJustDecodeBounds = false;
+  options.inDither = false;
+  options.inSampleSize = inSampleSize;
+  options.inScaled = false;
+  // Ensures the image stays as a 32-bit ARGB_8888 image.
+  // This preserves image quality.
+  options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+
+  Bitmap sampledSrcBitmap = BitmapFactory.decodeFile(IMAGE_FILE_URL, options);
+
+  // Resize
+  Matrix matrix = new Matrix();
+  matrix.postScale(desiredScale, desiredScale);
+  Bitmap scaledBitmap = Bitmap.createBitmap(sampledSrcBitmap, 0, 0,
+      sampledSrcBitmap.getWidth(), sampledSrcBitmap.getHeight(), matrix, true);
+  sampledSrcBitmap = null;
+
+  // Save
+  FileOutputStream out = new FileOutputStream(LOCAL_PATH_TO_STORE_IMAGE);
+  scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
+  scaledBitmap = null;
+</pre>
+  </li>
+</ul>
+
diff --git a/docs/html/preview/tv/ui/navigation.jd b/docs/html/preview/tv/ui/navigation.jd
new file mode 100644
index 0000000..92b34cf
--- /dev/null
+++ b/docs/html/preview/tv/ui/navigation.jd
@@ -0,0 +1,136 @@
+page.title=Navigation for TV
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+  <h2>In this document</h2>
+  <ol>
+    <li><a href="#d-pad-navigation">D-pad Navigation</a></li>
+    <li><a href="#focus-selection">Focus and Selection</a></li>
+  </ol>
+
+</div>
+</div>
+
+<p>TV devices provide a limited set of navigation controls for apps. Creating an effective
+  navigation scheme for your TV app depends on understanding these limited controls and the limits
+  of users' perception while operating your app. As you build your Android app for TVs,
+  you should pay special attention to how the user actually navigates around your app
+  when using remote control buttons instead of a touch screen.</p>
+
+<p>This guide shows you how to build an effective navigation scheme for your TV app.</p>
+
+
+<h2 id="d-pad-navigation">D-pad Navigation</h2>
+
+<p>On a TV device, users navigate with controls on a remote control device, using either a
+  directional pad (D-pad) or arrow keys. This type of control limits movement to up, down, left,
+  and right. To build a great TV-optimized app, you must provide a navigation scheme where
+  the user can quickly learn how to navigate your app using these limited controls.</p>
+
+<p>Follow these guidelines to build a navigation system that works well with a D-pad on a TV device:
+</p>
+
+<ul>
+  <li>Ensure that the D-pad can navigate to all the visible controls on the screen.</li>
+  <li>For scrolling lists with focus, D-pad up/down keys scroll the list, and the Enter key selects
+    an item in the list. Ensure that users can select an element in the list and that the list still
+    scrolls when an element is selected.</li>
+  <li>Ensure that movement between controls is straightforward and predictable.</li>
+</ul>
+
+<p>The Android framework handles directional navigation between layout elements automatically, so
+  you typically do not need to do anything extra for your app. However, you should thoroughly test
+  navigation with a D-pad control to discover any navigation problems. If you discover that your
+  screen layout makes navigation difficult, or if you want users to move through the layout in a
+  specific way, you can set up explicit directional navigation for your controls. The following
+  code sample shows how to define the next control to receive focus for a
+  {@link android.widget.TextView} layout object:</p>
+
+<pre>
+&lt;TextView android:id="&#64;+id/Category1"
+             android:nextFocusDown="&#64;+id/Category2"\&gt;
+</pre>
+
+<p>The following table lists all of the available navigation attributes for Android user interface
+widgets:</p>
+
+<table>
+  <tr>
+    <th>Attribute</th>
+    <th>Function</th>
+  </tr>
+  <tr>
+    <td>{@link android.R.attr#nextFocusDown}</td>
+    <td>Defines the next view to receive focus when the user navigates down.</td>
+  </tr>
+  <tr>
+    <td>{@link android.R.attr#nextFocusLeft}</td>
+    <td>Defines the next view to receive focus when the user navigates left.</td>
+  </tr>
+  <tr>
+    <td>{@link android.R.attr#nextFocusRight}</td>
+    <td>Defines the next view to receive focus when the user navigates right.</td>
+  </tr>
+  <tr>
+    <td>{@link android.R.attr#nextFocusUp}</td>
+    <td>Defines the next view to receive focus when the user navigates up.</td>
+  </tr>
+</table>
+
+<p>To use one of these explicit navigation attributes, set the value to the ID ({@code android:id}
+  value) of another widget in the layout. You should set up the navigation order as a loop, so that
+  the last control directs focus back to the first one.</p>
+
+<p class="note">
+  <strong>Note:</strong> You should only use these attributes to modify the navigation order if the
+  default order that the system applies does not work well.
+</p>
+
+
+<h2 id="focus-selection">Focus and Selection</h2>
+
+<p>The success of a navigation scheme on TV devices is strongly dependent on how easy it is for a
+  user to determine what user interface element is in focus on screen. If you do not provide clear
+  indications of what is in focus on screen (and therefore what item they can take action on),
+  users can quickly become frustrated and exit your app. By the same token, it is important
+  to always have an item in focus that a user can take action on immediately after your app starts,
+  and any time your app is not playing content.</p>
+
+<p>Your app layout and implementation should use color, size, animation, or a combination of
+  these attributes to help users easily determine what actions they can take next. Use a uniform
+  scheme for indicating focus across your application.</p>
+
+<p>Android provides <a href="{@docRoot}guide/topics/resources/drawable-resource.html#StateList">
+Drawable State List Resources</a> to implement highlights for selected and focused controls. The
+following code example demonstates how to indicate selection of a button object:
+</p>
+
+<pre>
+&lt;!-- res/drawable/button.xml --&gt;
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;selector xmlns:android="http://schemas.android.com/apk/res/android"&gt;
+    &lt;item android:state_pressed="true"
+          android:drawable="@drawable/button_pressed" /&gt; &lt;!-- pressed --&gt;
+    &lt;item android:state_focused="true"
+          android:drawable="@drawable/button_focused" /&gt; &lt;!-- focused --&gt;
+    &lt;item android:state_hovered="true"
+          android:drawable="@drawable/button_focused" /&gt; &lt;!-- hovered --&gt;
+    &lt;item android:drawable="@drawable/button_normal" /&gt; &lt;!-- default --&gt;
+&lt;/selector&gt;
+</pre>
+
+<p>
+This layout XML applies the above state list drawable to a {@link android.widget.Button}:
+</p>
+<pre>
+&lt;Button
+    android:layout_height="wrap_content"
+    android:layout_width="wrap_content"
+    android:background="@drawable/button" /&gt;
+</pre>
+
+<p>Make sure to provide sufficient padding within the focusable and selectable controls so that
+  the highlights around them are clearly visible.</p>
+
diff --git a/docs/html/preview/tv/ui/recommendations.jd b/docs/html/preview/tv/ui/recommendations.jd
new file mode 100644
index 0000000..2c78064
--- /dev/null
+++ b/docs/html/preview/tv/ui/recommendations.jd
@@ -0,0 +1,209 @@
+page.title=Making Recommendations
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+  <h2>In this document</h2>
+  <ol>
+    <li><a href="#service">Create a Recommendations Service</a></li>
+    <li><a href="#build">Build Recommendations</a></li>
+    <li><a href="#run-service">Run Recommendations Service</a></li>
+    <li><a href="#DesignLandscapeLayouts">Design Landscape Layouts</a></li>
+  </ol>
+
+</div>
+</div>
+
+
+<p>Content recommendations appear as the first row of the TV launch screen after the first use
+  of the device. This row is intended to help users quickly find content they enjoy. Contributing
+  recommendations from your apps content catalog can help bring users back to your app.</p>
+
+
+<img src="{@docRoot}preview/tv/images/home-recommendations.png" alt="" id="figure1" />
+<p class="img-caption">
+  <strong>Figure 1.</strong> An example of the recommendations row.
+</p>
+
+
+<h2 id="service">Create a Recommendations Service</h2>
+
+<p>Content recommendations are created with background processing. In order for your application
+  to contribute to recommendations, you create a service that periodically adds listings from your
+  app's catalog to the system list of recommendations.</p>
+
+<p>The following code example illustrates how to extend the {@link android.app.IntentService} to
+  create a recommendation service for your application.</p>
+
+<pre>
+public class RecommendationsService extends IntentService {
+    private static final int MAX_RECOMMENDATIONS = 3;
+
+    public RecommendationsService() {
+        super("RecommendationService");
+    }
+
+    &#64;Override
+    protected void onHandleIntent(Intent intent) {
+        MovieDatabase database = MovieDatabase.instance(getApplicationContext());
+        List<Movie> recommendations = database.recommendations();
+
+        int count = 0;
+
+        try {
+            for (Movie movie : recommendations) {
+                // build the individual content recommendations
+                buildRecommendation(getApplicationContext(), movie);
+
+                if (++count >= MAX_RECOMMENDATIONS) {
+                    break;
+                }
+            }
+        } catch (IOException e) {
+            Log.e(TAG, "Unable to update recommendation", e);
+        }
+    }
+}
+</pre>
+
+<p>In order for this class to be recognized and run as a service, you must register this service
+  using your app manifest. The following code snippet illustrates how to add this class as a
+  service:</p>
+
+<pre>
+&lt;manifest ... &gt;
+  &lt;application ... &gt;
+    ...
+
+    &lt;service android:name=&quot;.RecommendationsService&quot;
+             android:enabled=&quot;true&quot; android:exported=&quot;true&quot;/&gt;
+  &lt;/application&gt;
+&lt;/manifest&gt;
+</pre>
+
+<h2 id="build">Build Recommendations</h2>
+
+<p>Once it starts running, your service must create recommendations and pass them to the Android
+  framework. The framework receives the recommendations as {@link android.app.Notification} objects
+  that use a specific style and are marked with a specific category.</p>
+
+<p>The following code example demonstrates how to get an instance of the {@link
+  android.app.NotificationManager}, build a recommendation, and post it to the manager:</p>
+
+<pre>
+public class RecommendationsService extends IntentService {
+
+    ...
+
+    public Notification buildRecommendation(Context context, Movie movie)
+            throws IOException {
+
+        if (mNotificationManager == null) {
+            mNotificationManager = (NotificationManager)
+                    mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+        }
+
+        Bundle extras = new Bundle();
+        if (mBackgroundUri != movie.getBackgroundUri()) {
+            extras.putString(EXTRA_BACKGROUND_IMAGE_URL, movie.getBackgroundUri());
+        }
+
+        // build the recommendation as a Notification object
+        Notification notification = new NotificationCompat.BigPictureStyle(
+                new NotificationCompat.Builder(context)
+                        .setContentTitle(movie.getTitle())
+                        .setContentText(movie.getDescription())
+                        .setPriority(movie.getPriority())
+                        .setOngoing(true)
+                        .setCategory("recommendation")
+                        .setLargeIcon(movie.getImage())
+                        .setSmallIcon(movie.getSmallIcon())
+                        .setContentIntent(buildPendingIntent(movie.getId()))
+                        .setExtras(extras))
+                .build();
+
+        // post the recommendation to the NotificationManager
+        mNotificationManager.notify(movie.getId(), notification);
+        mNotificationManager = null;
+        return notification;
+    }
+
+    private PendingIntent buildPendingIntent(long id) {
+        Intent detailsIntent = new Intent(this, DetailsActivity.class);
+        detailsIntent.putExtra("id", id);
+
+        TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
+        stackBuilder.addParentStack(DetailsActivity.class);
+        stackBuilder.addNextIntent(detailsIntent);
+        // Ensure each PendingIntent is unique
+        detailsIntent.setAction(Long.toString(id));
+
+        PendingIntent intent = stackBuilder.getPendingIntent(
+                0, PendingIntent.FLAG_UPDATE_CURRENT);
+        return intent;
+    }
+}
+</pre>
+
+
+<h3 id="run-service">Run Recommendations Service</h3>
+
+<p>Your app's recommendation service must run periodically in order to create current
+  recommendations. In order to run your service, you should create a class that runs a timer and
+  invokes it at regular intervals. The following code example extends the {@link
+  android.content.BroadcastReceiver} class to start periodic execution of a recommendation service
+  every 12 hours:</p>
+
+<pre>
+public class BootupReceiver extends BroadcastReceiver {
+    private static final String TAG = "BootupActivity";
+
+    private static final long INITIAL_DELAY = 5000;
+
+    &#64;Override
+    public void onReceive(Context context, Intent intent) {
+        if (intent.getAction().endsWith(Intent.ACTION_BOOT_COMPLETED)) {
+            scheduleRecommendationUpdate(context);
+        }
+    }
+
+    private void scheduleRecommendationUpdate(Context context) {
+        AlarmManager alarmManager = (AlarmManager)context.getSystemService(
+                Context.ALARM_SERVICE);
+        Intent recommendationIntent = new Intent(context,
+                UpdateRecommendationsService.class);
+        PendingIntent alarmIntent = PendingIntent.getService(context, 0,
+                recommendationIntent, 0);
+
+        alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
+                INITIAL_DELAY,
+                AlarmManager.INTERVAL_HALF_DAY,
+                alarmIntent);
+    }
+}
+</pre>
+
+<p>In order for the {@link android.content.BroadcastReceiver} class to execute after a TV
+  device starts up, you must register this class in your app manifest and attach an intent filter
+  in order for the device boot process to complete. This sample code demonstrates how to add this
+  configuration to the manifest:</p>
+
+<pre>
+&lt;manifest ... &gt;
+  &lt;application ... &gt;
+    &lt;receiver android:name=&quot;.BootupReceiver&quot; android:enabled=&quot;true&quot;
+              android:exported=&quot;false&quot;&gt;
+      &lt;intent-filter&gt;
+        &lt;action android:name=&quot;android.intent.action.BOOT_COMPLETED&quot;/&gt;
+      &lt;/intent-filter&gt;
+    &lt;/receiver&gt;
+  &lt;/application&gt;
+&lt;/manifest&gt;
+</pre>
+
+<p class="important">
+  <strong>Important:</strong> Receiving a boot completed notification requires that your app
+  request the {@link android.Manifest.permission#RECEIVE_BOOT_COMPLETED} permission.
+  For more information, see {@link android.content.Intent#ACTION_BOOT_COMPLETED}.
+</p>
diff --git a/docs/html/sdk/installing/create-project.jd b/docs/html/sdk/installing/create-project.jd
new file mode 100644
index 0000000..c0d523a
--- /dev/null
+++ b/docs/html/sdk/installing/create-project.jd
@@ -0,0 +1,86 @@
+page.title=Creating a Project
+
+@jd:body
+
+<p>Android Studio makes it easy to create Android apps for several form factors, such as phone,
+tablet, TV, Wear, and Google Glass. The <em>New Project</em> wizard lets you choose the form factors
+for your app and populates the project structure with everything you need to get started.</p>
+
+<p>Follow the steps in this section to create a project in Android Studio.</p>
+
+<h2>Step 1: Create a New Project</h2>
+
+<p>If you didn't have a project opened, Android Studio shows the Welcome screen.
+To create a new project, click <strong>New Project</strong>.</p>
+
+<p>If you had a project opened, Android Studio shows the development environment.
+To create a new project, click <strong>File</strong> > <strong>New Project</strong>.</p>
+
+<p>The next window lets you configure the name of your app, the package name, and the location
+of your project.</p>
+
+<img src="{@docRoot}images/tools/wizard2.png" alt="" width="500" height="381">
+<p class="img-caption"><strong>Figure 1.</strong> Choose a name for your project.</p>
+
+<p>Enter the values for your project and click <strong>Next</strong>.</p>
+
+
+<h2>Step 2: Select Form Factors and API Level</h2>
+
+<p>The next window lets you select the form factors supported by your app, such as phone, tablet,
+TV, Wear, and Google Glass. For each form factor, you can also select the API
+Level that your app requires. To get more information, click <strong>Help me choose</strong>.</p>
+
+<img src="{@docRoot}images/tools/wizard4.png" alt="" width="750" height="510">
+<p class="img-caption"><strong>Figure 2.</strong> Select the API Level.</p>
+
+<p>The API Level window shows the distribution of mobile devices running each version of Android,
+as shown in Figure 2. Click on an API level to see a list of features introduced in the corresponding
+version of Android. This helps you choose the minimum API Level that has all the features that
+your apps needs, so you can reach as many devices as possible. Then click <strong>OK</strong>.</p>
+
+<img src="{@docRoot}images/tools/wizard3.png" alt="" width="500" height="480">
+<p class="img-caption"><strong>Figure 3.</strong> Choose form factors for your app.</p>
+
+<p>Then, on the Form Factors Window, click <strong>Next</strong>.</p>
+
+
+<h2>Step 3: Add an Activity</h2>
+
+<p>The next screen lets you select an activity type to add to your app, as shown in Figure 4.
+This screen depends on the form factors you selected earlier.</p>
+
+<img src="{@docRoot}images/tools/wizard5.png" alt="" width="720" height="504">
+<p class="img-caption"><strong>Figure 4.</strong> Add an activity to your app.</p>
+
+<p>Choose an activity type and click <strong>Next</strong>.</p>
+
+
+<h2>Step 4: Configure Your Activity</h2>
+
+<p>The next screen lets you configure the activity to add to your app, as shown in Figure 6.</p>
+
+<img src="{@docRoot}images/tools/wizard6.png" alt="" width="450" height="385">
+<p class="img-caption"><strong>Figure 6.</strong> Choose a name for your activity.</p>
+
+<p>Enter the activity name, the layout name, and the activity title. Then click
+<strong>Finish</strong>.</p>
+
+
+<h2>Step 5: Develop Your App</h2>
+
+<p>Android Studio creates the default structure for your project and opens the development
+environment. If your app supports more than one form factor, Android Studio creates a module for
+each of them, as shown in Figure 7.</p>
+
+<img src="{@docRoot}images/tools/wizard7.png" alt="" width="750" height="509">
+<p class="img-caption"><strong>Figure 7.</strong> The default project structure for a mobile app.</p>
+
+<p>Now you are ready to develop your app. Fore more information, see the following links:</p>
+
+<ul>
+<li><a href="{@docRoot}training/">Training Lessons</a></li>
+<li><a href="{@docRoot}training/building-wearables.html">Building Apps for Wearables</a></li>
+<li><a href="{@docRoot}tv/">Android TV</a></li>
+<li><a href="https://developers.google.com/glass/">Google Glass</a></li>
+</ul>
diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs
index fb4659f..93e5976 100644
--- a/docs/html/tools/tools_toc.cs
+++ b/docs/html/tools/tools_toc.cs
@@ -11,7 +11,7 @@
           <span class="en">Adding SDK Packages</span></a></li>
     </ul>
   </li>
-  
+
 
   <li class="nav-section">
     <div class="nav-section-header">
@@ -20,6 +20,8 @@
     <ul>
       <li><a href="<?cs var:toroot ?>sdk/installing/migrate.html">
           Migrating from Eclipse</a></li>
+      <li><a href="<?cs var:toroot ?>sdk/installing/create-project.html">
+          Creating a Project</a></li>
       <li><a href="<?cs var:toroot ?>sdk/installing/studio-tips.html">
           Tips and Tricks</a></li>
       <li><a href="<?cs var:toroot ?>sdk/installing/studio-layout.html">
diff --git a/docs/html/training/app-indexing/index.jd b/docs/html/training/app-indexing/index.jd
index cb4135f..7e7241b 100644
--- a/docs/html/training/app-indexing/index.jd
+++ b/docs/html/training/app-indexing/index.jd
@@ -59,14 +59,6 @@
 </li>
 </ol>
 
-<p class="note"><strong>Note: </strong>
-Currently, the Google Search app indexing capability is restricted to
-English-only Android apps from developers participating in the early adopter
-program. You can sign up to be a participant by submitting the <a
-href="https://docs.google.com/a/google.com/forms/d/1itcqPAQqggJ6e4m8aejWLM8Dc5O8P6qybgGbKCNxGV0/viewform"
-class="external-link" target="_blank">App Indexing Expression of Interest</a> form.
-</p>
-
 <p>This class shows how to enable deep linking and indexing of your application
 content so that users can open this content directly from mobile search
 results.</p>
diff --git a/docs/html/training/tv/index.jd b/docs/html/training/tv/index.jd
new file mode 100644
index 0000000..54f7016
--- /dev/null
+++ b/docs/html/training/tv/index.jd
@@ -0,0 +1,59 @@
+page.title=Designing for TV
+page.tags="input","screens"
+
+trainingnavtop=true
+startpage=true
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<!-- Required platform, tools, add-ons, devices, knowledge, etc. -->
+<h2>Dependencies and prerequisites</h2>
+<ul>
+  <li>Android 2.0 (API Level 5) or higher</li>
+</ul>
+
+</div>
+</div>
+
+<a class="notice-developers-video wide" href="http://www.youtube.com/watch?v=zsRnRLh-O34">
+<div>
+    <h3>Video</h3>
+    <p>DevBytes: Design for Large Displays - Part 1</p>
+</div>
+</a>
+
+<p> 
+  Smart TVs powered by Android bring your favorite Android apps to the best screen in your house. 
+  Thousands of apps in the Google Play Store are already optimized for TVs. This class shows how 
+  you can optimize your Android app for TVs, including how to build a layout that 
+  works great when the user is ten feet away and navigating with a remote control. 
+</p> 
+
+<h2>Lessons</h2> 
+ 
+<dl> 
+  <dt><b><a href="optimizing-layouts-tv.html">Optimizing Layouts for TV</a></b></dt>
+    <dd>Shows you how to optimize app layouts for TV screens, which have some unique characteristics such as:
+    <ul>
+      <li>permanent "landscape" mode</li>
+      <li>high-resolution displays</li>
+      <li>"10 foot UI" environment.</li>
+    </ul>
+    </dd>
+ 
+  <dt><b><a href="optimizing-navigation-tv.html">Optimizing Navigation for TV</a></b></dt>
+    <dd>Shows you how to design navigation for TVs, including: 
+    <ul>
+      <li>handling D-pad navigation</li>
+      <li>providing navigational feedback</li>
+      <li>providing easily-accessible controls on the screen.</li>
+    </ul>
+    </dd>
+
+  <dt><b><a href="unsupported-features-tv.html">Handling features not supported on TV</a></b></dt>
+    <dd>Lists the hardware features that are usually not available on TVs. This lesson also shows you how to 
+    provide alternatives for missing features or check for missing features and disable code at run time.</dd>
+</dl> 
diff --git a/docs/html/training/tv/optimizing-layouts-tv.jd b/docs/html/training/tv/optimizing-layouts-tv.jd
new file mode 100644
index 0000000..a6db052
--- /dev/null
+++ b/docs/html/training/tv/optimizing-layouts-tv.jd
@@ -0,0 +1,246 @@
+page.title=Optimizing Layouts for TV
+parent.title=Designing for TV
+parent.link=index.html
+
+trainingnavtop=true
+next.title=Optimizing Navigation for TV
+next.link=optimizing-navigation-tv.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#DesignLandscapeLayouts">Design Landscape Layouts</a></li>
+  <li><a href="#MakeTextControlsEasyToSee">Make Text and Controls Easy to See</a></li>
+  <li><a href="#DesignForLargeScreens">Design for High-Density Large Screens</a></li>
+  <li><a href="#HandleLargeBitmaps">Design to Handle Large Bitmaps</a></li>
+</ol>
+
+<h2>You should also read</h2>
+<ul>
+  <li><a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a></li>
+</ul>
+
+</div>
+</div>
+
+<p>
+When your application is running on a television set, you should assume that the user is sitting about 
+ten feet away from the screen. This user environment is referred to as the 
+<a href="http://en.wikipedia.org/wiki/10-foot_user_interface">10-foot UI</a>. To provide your 
+users with a usable and enjoyable experience, you should style and lay out your UI accordingly..
+</p>
+<p>
+This lesson shows you how to optimize layouts for TV by:
+</p>
+<ul>
+  <li>Providing appropriate layout resources for landscape mode.</li>
+  <li>Ensuring that text and controls are large enough to be visible from a distance.</li>
+  <li>Providing high resolution bitmaps and icons for HD TV screens.</li>
+</ul>
+
+<h2 id="DesignLandscapeLayouts">Design Landscape Layouts</h2> 
+
+<p>
+TV screens are always in landscape orientation. Follow these tips to build landscape layouts optimized for TV screens:
+</p> 
+<ul>
+  <li>Put on-screen navigational controls on the left or right side of the screen and save the 
+  vertical space for content.</li>
+  <li>Create UIs that are divided into sections, by using <a href="{@docRoot}guide/components/fragments.html">Fragments</a> 
+  and use view groups like {@link android.widget.GridView} instead 
+  of {@link android.widget.ListView} to make better use of the 
+  horizontal screen space.</li>
+  <li>Use view groups such as {@link android.widget.RelativeLayout} 
+  or {@link android.widget.LinearLayout} to arrange views. 
+  This allows the Android system to adjust the position of the views to the size, alignment, 
+  aspect ratio, and pixel density of the TV screen.</li>
+  <li>Add sufficient margins between layout controls to avoid a cluttered UI.</li>
+</ul> 
+ 
+<p>
+For example, the following layout is optimized for TV:
+</p>
+
+<img src="{@docRoot}images/training/panoramio-grid.png" />
+
+<p>
+In this layout, the controls are on the lefthand side. The UI is displayed within a 
+{@link android.widget.GridView}, which is well-suited to landscape orientation.
+In this layout both GridView and Fragment have the width and height set 
+dynamically, so they can adjust to the screen resolution. Controls are added to the left side Fragment programatically at runtime.
+The layout file for this UI is {@code res/layout-land-large/photogrid_tv.xml}.
+(This layout file is placed in {@code layout-land-large} because TVs have large screens with landscape orientation. For details refer to 
+<a href="{@docRoot}guide/practices/screens_support.html">Supporting Multiple Screens</a>.)</p>
+
+res/layout-land-large/photogrid_tv.xml
+<pre>
+&lt;RelativeLayout
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent" &gt;
+
+    &lt;fragment
+        android:id="@+id/leftsidecontrols"
+        android:layout_width="0dip"
+        android:layout_marginLeft="5dip"
+        android:layout_height="match_parent" /&gt;
+
+    &lt;GridView        
+        android:id="@+id/gridview"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content" /&gt;
+
+&lt;/RelativeLayout>
+</pre>
+
+<p>
+To set up action bar items on the left side of the screen, you can also include the <a
+href="http://code.google.com/p/googletv-android-samples/source/browse/#git%2FLeftNavBarLibrary">
+Left navigation bar library</a> in your application to set up action items on the left side 
+of the screen, instead of creating a custom Fragment to add controls:
+</p>
+
+<pre>
+LeftNavBar bar = (LeftNavBarService.instance()).getLeftNavBar(this);
+</pre>
+
+<p>
+When you have an activity in which the content scrolls vertically, always use a left navigation bar; 
+otherwise, your users have to scroll to the top of the content to switch between the content view and 
+the ActionBar. Look at the  
+<a href="http://code.google.com/p/googletv-android-samples/source/browse/#git%2FLeftNavBarDemo">
+Left navigation bar sample app</a> to see how to simple it is to include the left navigation bar in your app.
+</p>
+
+<h2 id="MakeTextControlsEasyToSee">Make Text and Controls Easy to See</h2>
+<p>
+The text and controls in a TV application's UI should be easily visible and navigable from a distance.
+Follow these tips to make them easier to see from a distance :
+</p>
+
+<ul>
+  <li>Break text into small chunks that users can quickly scan.</li>
+  <li>Use light text on a dark background. This style is easier to read on a TV.</li>
+  <li>Avoid lightweight fonts or fonts that have both very narrow and very broad strokes. Use simple sans-serif 
+  fonts and use anti-aliasing to increase readability.</li>
+  <li>Use Android's standard font sizes:
+  <pre>
+  &lt;TextView
+        android:id="@+id/atext"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:gravity="center_vertical"
+        android:singleLine="true"
+        android:textAppearance="?android:attr/textAppearanceMedium"/&gt;
+  </pre></li>
+  <li>Ensure that all your view widgets are large enough to be clearly visible to someone sitting 10 feet away 
+  from the screen (this distance is greater for very large screens).  The best way to do this is to use 
+  layout-relative sizing rather than absolute sizing, and density-independent pixel units instead of absolute 
+  pixel units. For example, to set the width of a widget, use wrap_content instead of a pixel measurement, 
+  and to set the margin for a widget, use dip instead of px values.
+  </li>
+</ul>
+<p>
+
+</p>
+
+<h2 id="DesignForLargeScreens">Design for High-Density Large Screens</h2>
+
+<p>
+The common HDTV display resolutions are 720p, 1080i, and 1080p. Design your UI for 1080p, and then 
+allow the Android system to downscale your UI to 720p if necessary. In general, downscaling (removing pixels) 
+does not degrade the UI (Notice that the converse is not true; you should avoid upscaling because it degrades 
+UI quality).
+</p>
+
+<p>
+To get the best scaling results for images, provide them as <a href="{@docRoot}tools/help/draw9patch.html">
+9-patch image</a> elements if possible.
+If you provide low quality or small images in your layouts, they will appear pixelated, fuzzy, or grainy. This 
+is not a good experience for the user. Instead, use high-quality images. 
+</p>
+
+<p>
+For more information on optimizing apps for large screens see <a href="{@docRoot}training/multiscreen/index.html">
+Designing for multiple screens</a>.
+</p>
+
+<h2 id="HandleLargeBitmaps">Design to Handle Large Bitmaps</h2>
+
+<p>
+The Android system has a limited amount of memory, so downloading and storing high-resolution images can often 
+cause out-of-memory errors in your app. To avoid this, follow these tips:
+</p>
+
+<ul>
+  <li>Load images only when they're displayed on the screen. For example, when displaying multiple images in 
+      a {@link android.widget.GridView} or 
+      {@link android.widget.Gallery}, only load an image when 
+      {@link android.widget.Adapter#getView(int, View, ViewGroup) getView()} 
+      is called on the View's {@link android.widget.Adapter}.
+  </li>
+  <li>Call {@link android.graphics.Bitmap#recycle()} on 
+      {@link android.graphics.Bitmap} views that are no longer needed.
+  </li>
+  <li>Use {@link java.lang.ref.WeakReference} for storing references 
+      to {@link android.graphics.Bitmap} objects in an in-memory 
+      {@link java.util.Collection}.</li>
+  <li>If you fetch images from the network, use {@link android.os.AsyncTask} 
+      to fetch them and store them on the SD card for faster access.
+      Never do network transactions on the application's UI thread.
+  </li>
+  <li>Scale down really large images to a more appropriate size as you download them; otherwise, downloading the image 
+  itself may cause an "Out of Memory" exception. Here is sample code that scales down images while downloading:
+  
+  <pre>
+  // Get the source image's dimensions
+  BitmapFactory.Options options = new BitmapFactory.Options();
+  // This does not download the actual image, just downloads headers.
+  options.inJustDecodeBounds = true; 
+  BitmapFactory.decodeFile(IMAGE_FILE_URL, options);
+  // The actual width of the image.
+  int srcWidth = options.outWidth;  
+  // The actual height of the image.
+  int srcHeight = options.outHeight;  
+
+  // Only scale if the source is bigger than the width of the destination view.
+  if(desiredWidth > srcWidth)
+    desiredWidth = srcWidth;
+
+  // Calculate the correct inSampleSize/scale value. This helps reduce memory use. It should be a power of 2.
+  int inSampleSize = 1;
+  while(srcWidth / 2 > desiredWidth){
+    srcWidth /= 2;
+    srcHeight /= 2;
+    inSampleSize *= 2;
+  }
+
+  float desiredScale = (float) desiredWidth / srcWidth;
+
+  // Decode with inSampleSize
+  options.inJustDecodeBounds = false;
+  options.inDither = false;
+  options.inSampleSize = inSampleSize;
+  options.inScaled = false;
+  // Ensures the image stays as a 32-bit ARGB_8888 image.
+  // This preserves image quality.
+  options.inPreferredConfig = Bitmap.Config.ARGB_8888;  
+                                                	
+  Bitmap sampledSrcBitmap = BitmapFactory.decodeFile(IMAGE_FILE_URL, options);
+
+  // Resize
+  Matrix matrix = new Matrix();
+  matrix.postScale(desiredScale, desiredScale);
+  Bitmap scaledBitmap = Bitmap.createBitmap(sampledSrcBitmap, 0, 0,
+      sampledSrcBitmap.getWidth(), sampledSrcBitmap.getHeight(), matrix, true);
+  sampledSrcBitmap = null;
+
+  // Save
+  FileOutputStream out = new FileOutputStream(LOCAL_PATH_TO_STORE_IMAGE);
+  scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
+  scaledBitmap = null;
+   </pre>
+  </li> </ul>
\ No newline at end of file
diff --git a/docs/html/training/tv/optimizing-navigation-tv.jd b/docs/html/training/tv/optimizing-navigation-tv.jd
new file mode 100644
index 0000000..bb78258
--- /dev/null
+++ b/docs/html/training/tv/optimizing-navigation-tv.jd
@@ -0,0 +1,206 @@
+page.title=Optimizing Navigation for TV
+parent.title=Designing for TV
+parent.link=index.html
+
+trainingnavtop=true
+previous.title=Optimizing Layouts for TV
+previous.link=optimizing-layouts-tv.html
+next.title=Handling Features Not Supported on TV
+next.link=unsupported-features-tv.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#HandleDpadNavigation">Handle D-pad Navigation</a></li>
+  <li><a href="#HandleFocusSelection">Provide Clear Visual Indication for Focus and Selection</a></li>
+  <li><a href="#DesignForEasyNavigation">Design for Easy Navigation</a></li>
+</ol>
+
+<h2>You should also read</h2>
+<ul>
+  <li><a href="{@docRoot}training/design-navigation/index.html">Designing Effective Navigation</a></li>
+</ul>
+
+</div>
+</div>
+
+<p>
+An important aspect of the user experience when operating a TV is the direct human interface: a remote control. 
+As you optimize your Android application for TVs, you should pay special attention to how the user actually navigates 
+around your application when using a remote control instead of a touchscreen.
+</p>
+<p>
+This lesson shows you how to optimize navigation for TV by:
+</p>
+
+<ul>
+  <li>Ensuring all layout controls are D-pad navigable.</li>
+  <li>Providing highly obvious feedback for UI navigation.</li>
+  <li>Placing layout controls for easy access.</li>
+</ul>
+
+<h2 id="HandleDpadNavigation">Handle D-pad Navigation</h2> 
+
+<p>
+On a TV, users navigate with controls on a TV remote, using either a D-pad or arrow keys. 
+This limits movement to up, down, left, and right. 
+To build a great TV-optimized app, you must provide a navigation scheme in which the user can 
+quickly learn how to navigate your app using the remote.
+</p>
+
+<p>
+When you design navigation for D-pad, follow these guidelines:
+</p>
+
+<ul>
+  <li>Ensure that the D-pad  can navigate to all the visible controls on the screen.</li>
+  <li>For scrolling lists with focus, D-pad up/down keys scroll the list and Enter key selects an item in the list. Ensure that users can 
+  select an element in the list and that the list still scrolls when an element is selected.</li> 
+  <li>Ensure that movement between controls is straightforward and predictable.</li>
+</ul>
+
+<p>
+Android usually handles navigation order between layout elements automatically, so you don't need to do anything extra. If the screen layout 
+makes navigation difficult, or if you want users to move through the layout in a specific way, you can set up explicit navigation for your 
+controls.  
+For example, for an {@code android.widget.EditText}, to define the next control to receive focus, use:
+<pre>
+&lt;EditText android:id="@+id/LastNameField" android:nextFocusDown="@+id/FirstNameField"\&gt;
+</pre>
+The following table lists all of the available navigation attributes:
+</p>
+
+<table>
+<tr>
+<th>Attribute</th>
+<th>Function</th>
+</tr>
+<tr>
+<td>{@link android.R.attr#nextFocusDown}</td>
+<td>Defines the next view to receive focus when the user navigates down.</td>
+</tr>
+<tr>
+<td>{@link android.R.attr#nextFocusLeft}</td>
+<td>Defines the next view to receive focus when the user navigates left.</td>
+</tr>
+<tr>
+<td>{@link android.R.attr#nextFocusRight}</td>
+<td>Defines the next view to receive focus when the user navigates right.</td>
+</tr>
+<tr>
+<td>{@link android.R.attr#nextFocusUp}</td>
+<td>Defines the next view to receive focus when the user navigates up.</td>
+</tr>
+</table>
+
+<p>
+To use one of these explicit navigation attributes, set the value to the ID (android:id value) of another widget in the layout. You should set 
+up the navigation order as a loop, so that the last control directs focus back to the first one.
+</p>
+
+<p>
+Note: You should only use these attributes to modify the navigation order if the default order that the system applies does not work well.
+</p>
+
+<h2 id="HandleFocusSelection">Provide Clear Visual Indication for Focus and Selection</h2>
+
+<p>
+Use appropriate color highlights for all navigable and selectable elements in the UI. This makes it easy for users to know whether the control 
+is currently focused or selected when they navigate with a D-pad. Also, use uniform highlight scheme across your application.
+</p>
+
+<p>
+Android provides <a href="{@docRoot}guide/topics/resources/drawable-resource.html#StateList">Drawable State List Resources</a> to implement highlights 
+for selected and focused controls. For example:
+</p>
+
+res/drawable/button.xml:
+<pre>
+&lt;?xml version="1.0" encoding="utf-8"?&gt;
+&lt;selector xmlns:android="http://schemas.android.com/apk/res/android"&gt;
+    &lt;item android:state_pressed="true"
+          android:drawable="@drawable/button_pressed" /&gt; &lt;!-- pressed --&gt;
+    &lt;item android:state_focused="true"
+          android:drawable="@drawable/button_focused" /&gt; &lt;!-- focused --&gt;
+    &lt;item android:state_hovered="true"
+          android:drawable="@drawable/button_focused" /&gt; &lt;!-- hovered --&gt;
+    &lt;item android:drawable="@drawable/button_normal" /&gt; &lt;!-- default --&gt;
+&lt;/selector&gt;
+</pre>
+
+<p>
+This layout XML applies the above state list drawable to a {@link android.widget.Button}:
+</p>
+<pre>
+&lt;Button
+    android:layout_height="wrap_content"
+    android:layout_width="wrap_content"
+    android:background="@drawable/button" /&gt;
+</pre>
+
+<p>
+Provide sufficient padding within the focusable and selectable controls so that the highlights around them are clearly visible. 
+</p>
+
+<h2 id="DesignForEasyNavigation">Design for Easy Navigation</h2>
+
+<p>
+Users should be able to navigate to any UI control with a couple of D-pad clicks. Navigation should be easy and  intuitive to 
+understand.  For any non-intuitive actions, provide users with written help, using a dialog triggered by a help button or action bar icon. 
+</p>
+
+<p>
+Predict the next screen that the user will want to navigate to and provide one click navigation to it. If the current screen UI is very sparse, 
+consider making it a multi pane screen. Use fragments for making multi-pane screens. For example, consider the multi-pane UI below with continent names 
+on the left and list of cool places in each continent on the right. 
+</p>
+
+<img src="{@docRoot}images/training/cool-places.png" alt="" />
+
+<p>
+The above UI consists of three Fragments - <code>left_side_action_controls</code>, <code>continents</code> and 
+<code>places</code> - as shown in its layout 
+xml file below. Such multi-pane UIs make D-pad navigation easier and make good use of the horizontal screen space for 
+TVs.
+</p>
+res/layout/cool_places.xml
+<pre>
+&lt;LinearLayout   
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="horizontal"
+   &gt;
+   &lt;fragment
+        android:id="@+id/left_side_action_controls"
+        android:layout_width="0px"
+        android:layout_height="match_parent"
+        android:layout_marginLeft="10dip"
+        android:layout_weight="0.2"/&gt;
+    &lt;fragment
+        android:id="@+id/continents"
+        android:layout_width="0px"
+        android:layout_height="match_parent"
+        android:layout_marginLeft="10dip"
+        android:layout_weight="0.2"/&gt;
+
+    &lt;fragment
+        android:id="@+id/places"
+        android:layout_width="0px"
+        android:layout_height="match_parent"
+        android:layout_marginLeft="10dip"
+        android:layout_weight="0.6"/&gt;
+
+&lt;/LinearLayout&gt;
+</pre>
+
+<p>
+Also, notice in the UI layout above action controls are on the left hand side of a vertically scrolling list to make 
+them easily accessible using D-pad. 
+In general, for layouts with horizontally scrolling components, place action controls on left or right hand side and 
+vice versa for vertically scrolling components.
+</p>
+
diff --git a/docs/html/training/tv/unsupported-features-tv.jd b/docs/html/training/tv/unsupported-features-tv.jd
new file mode 100644
index 0000000..a9f090b
--- /dev/null
+++ b/docs/html/training/tv/unsupported-features-tv.jd
@@ -0,0 +1,157 @@
+page.title=Handling Features Not Supported on TV
+parent.title=Designing for TV
+parent.link=index.html
+
+trainingnavtop=true
+previous.title=Optimizing Navigation for TV
+previous.link=optimizing-navigation-tv.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+  <li><a href="#WorkaroundUnsupportedFeatures">Work Around Features Not Supported on TV</a></li>
+  <li><a href="#CheckAvailableFeatures">Check for Available Features at Runtime</a></li>
+</ol>
+
+</div>
+</div>
+
+<p>
+TVs are much different from other Android-powered devices:
+</p>
+<ul>
+  <li>They're not mobile.</li>
+  <li>Out of habit, people use them for watching media with little or no interaction.</li>
+  <li>People interact with them from a distance.</li>
+</ul>
+
+<p>
+Because TVs have a different purpose from other devices, they usually don't have hardware features 
+that other Android-powered devices often have. For this reason, the Android system does not 
+support the following features for a TV device:
+<table>
+<tr>
+<th>Hardware</th>
+<th>Android feature descriptor</th>
+</tr>
+<tr>
+<td>Camera</td>
+<td>android.hardware.camera</td>
+</tr>
+<tr>
+<td>GPS</td>
+<td>android.hardware.location.gps</td>
+</tr>
+<tr>
+<td>Microphone</td>
+<td>android.hardware.microphone</td>
+</tr>
+<tr>
+<td>Near Field Communications (NFC)</td>
+<td>android.hardware.nfc</td>
+</tr>
+<tr>
+<td>Telephony</td>
+<td>android.hardware.telephony</td>
+</tr>
+<tr>
+<td>Touchscreen</td>
+<td>android.hardware.touchscreen</td>
+</tr>
+</table>
+</p>
+
+<p>
+This lesson shows you how to work around features that are not available on TV by:
+<ul>
+  <li>Providing work arounds for some non-supported features.</li>
+  <li>Checking for available features at runtime and conditionally activating/deactivating certain code 
+  paths based on availability of those features.</li>
+</ul>
+</p>
+
+
+<h2 id="WorkaroundUnsupportedFeatures">Work Around Features Not Supported on TV</h2> 
+
+<p>
+Android doesn't support touchscreen interaction for TV devices, most TVs don't have touch screens, 
+and interacting with a TV using a touchscreen is not consistent with the 10 foot environment. For 
+these reasons, users interact with Android-powered TVs using a remote. In consideration of this, 
+ensure that every control in your app can be accessed with the D-pad. Refer back to the previous two lessons 
+<a href="{@docRoot}training/tv/optimizing-layouts-tv.html">Optimizing Layouts for TV</a> and 
+<a href="{@docRoot}training/tv/optimizing-navigation-tv.html">Optimize Navigation for TV</a> for
+more details 
+on this topic. The Android system assumes that a device has a touchscreen, so if you want your application 
+to run on a TV, you must <strong>explicitly</strong> disable the touchscreen requirement in your manifest file:
+<pre>
+&lt;uses-feature android:name="android.hardware.touchscreen" android:required="false"/&gt;
+</pre>
+</p> 
+
+<p>
+Although a TV doesn't have a camera, you can still provide a photography-related application on a TV. 
+For example, if you have an app that takes, views and edits photos, you can disable its picture-taking 
+functionality for TVs and still allow users to view and even edit photos. The next section talks about how to 
+deactivate or activate specific functions in the application based on runtime device type detection.
+</p>
+
+<p>
+Because TVs are stationary, indoor devices, they don't have built-in GPS. If your application uses location 
+information, allow users to search for a location or use a "static" location provider to get 
+a location from the zip code configured during the TV setup.
+<pre>
+LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
+Location location = locationManager.getLastKnownLocation("static");
+Geocoder geocoder = new Geocoder(this);
+Address address = null;
+
+try {
+  address = geocoder.getFromLocation(location.getLatitude(), location.getLongitude(), 1).get(0);
+  Log.d("Zip code", address.getPostalCode());
+
+} catch (IOException e) {
+  Log.e(TAG, "Geocoder error", e);
+}
+</pre>
+</p>
+
+<p>
+TVs usually don't support microphones, but if you have an application that uses voice control, 
+you can create a mobile device app that takes voice input and then acts as a remote control for a TV.
+</p>
+
+<h2 id="CheckAvailableFeatures">Check for Available Features at Runtime</h2>
+
+<p>
+To check if a feature is available at runtime, call 
+{@link android.content.pm.PackageManager#hasSystemFeature(String)}.
+ This method takes a single argument : a string corresponding to the 
+feature you want to check. For example, to check for touchscreen, use 
+{@link android.content.pm.PackageManager#hasSystemFeature(String)} with the argument 
+{@link android.content.pm.PackageManager#FEATURE_TOUCHSCREEN}.
+</p>
+
+<p>
+The following code snippet demonstrates how to detect device type at runtime based on supported features:
+
+<pre>
+// Check if android.hardware.telephony feature is available.
+if (getPackageManager().hasSystemFeature("android.hardware.telephony")) {
+   Log.d("Mobile Test", "Running on phone");
+// Check if android.hardware.touchscreen feature is available.
+} else if (getPackageManager().hasSystemFeature("android.hardware.touchscreen")) {
+   Log.d("Tablet Test", "Running on devices that don't support telphony but have a touchscreen.");
+} else {
+    Log.d("TV Test", "Running on a TV!");
+}
+</pre>
+</p>
+
+<p>
+This is just one example of using runtime checks to deactivate app functionality that depends on features 
+that aren't available on TVs.
+</p>
\ No newline at end of file
diff --git a/docs/html/wear/images/hero.jpg b/docs/html/wear/images/hero.jpg
index 7850a81..0b4debb 100644
--- a/docs/html/wear/images/hero.jpg
+++ b/docs/html/wear/images/hero.jpg
Binary files differ
diff --git a/docs/html/wear/index.jd b/docs/html/wear/index.jd
index 1de09ee..bc08aa0 100644
--- a/docs/html/wear/index.jd
+++ b/docs/html/wear/index.jd
@@ -84,9 +84,8 @@
             <div class="landing-breakout cols">
               <div class="col-3-wide">
 
-                <div class="landing-inset-video-container">
-                  <img class="landing-bezel-only" src="{@docRoot}wear/images/screens/bezel.png" alt="">
-                  <img class="gif" src="{@docRoot}wear/images/screens/reservation_animated.gif">
+                <div class="framed-wear-square">
+                  <img src="{@docRoot}wear/images/screens/reservation_animated.gif">
                 </div>
 
                 <p class="landing-small">
@@ -189,7 +188,7 @@
             <div class="landing-h2">Building an Ecosystem</div>
             <div class="landing-body landing-align-center">
               <p class="landing-small">
-                We’re working with several partners to bring you watches powered by Android Wear later this year!
+                We’re working with partners around the world to build watches powered by Android Wear!
               </p>
             </div>
           </div>
@@ -286,7 +285,7 @@
                   </p>
                   <br>
                     <p class="landing-small">
-                    <a target="_blank" href="http://android-developers.blogspot.com/2014/03/android-wear-developer-preview.html">Android Developers Blog</a>
+                    <a target="_blank" href="http://android-developers.blogspot.com">Android Developers Blog</a>
                     </p>
                   <p></p>
                 </div>
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 968c0ec..c787fb0 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -34,10 +34,91 @@
 import java.util.ArrayList;
 
 /**
- * AnimatedVectorDrawable can use ObjectAnimator and AnimatorSet to animate
- * the property of the VectorDrawable.
+ * This class uses {@link android.animation.ObjectAnimator} and
+ * {@link android.animation.AnimatorSet} to animate the properties of a
+ * {@link android.graphics.drawable.VectorDrawable} to create an animated drawable.
+ * <p>
+ * AnimatedVectorDrawable are normally defined as 3 separate XML files.
+ * </p>
+ * <p>
+ * First is the XML file for {@link android.graphics.drawable.VectorDrawable}.
+ * Note that we allow the animation happen on the group's attributes and path's
+ * attributes, which requires they are uniquely named in this xml file. Groups
+ * and paths without animations do not need names.
+ * </p>
+ * <li>Here is a simple VectorDrawable in this vectordrawable.xml file.
+ * <pre>
+ * &lt;vector xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot; &gt;
+ *     &lt;size
+ *         android:height=&quot;64dp&quot;
+ *         android:width=&quot;64dp&quot; /&gt;
+ *     &lt;viewport
+ *         android:viewportHeight=&quot;600&quot;
+ *         android:viewportWidth=&quot;600&quot; /&gt;
+ *     &lt;group
+ *         android:name=&quot;rotationGroup&quot;
+ *         android:pivotX=&quot;300.0&quot;
+ *         android:pivotY=&quot;300.0&quot;
+ *         android:rotation=&quot;45.0&quot; &gt;
+ *         &lt;path
+ *             android:name=&quot;v&quot;
+ *             android:fill=&quot;#000000&quot;
+ *             android:pathData=&quot;M300,70 l 0,-70 70,70 0,0 -70,70z&quot; /&gt;
+ *     &lt;/group&gt;
+ * &lt;/vector&gt;
+ * </pre></li>
+ * <p>
+ * Second is the AnimatedVectorDrawable's xml file, which defines the target
+ * VectorDrawable, the target paths and groups to animate, the properties of the
+ * path and group to animate and the animations defined as the ObjectAnimators
+ * or AnimatorSets.
+ * </p>
+ * <li>Here is a simple AnimatedVectorDrawable defined in this avd.xml file.
+ * Note how we use the names to refer to the groups and paths in the vectordrawable.xml.
+ * <pre>
+ * &lt;animated-vector xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
+ *   android:drawable=&quot;@drawable/vectordrawable&quot; &gt;
+ *     &lt;target
+ *         android:name=&quot;rotationGroup&quot;
+ *         android:animation=&quot;@anim/rotation&quot; /&gt;
+ *     &lt;target
+ *         android:name=&quot;v&quot;
+ *         android:animation=&quot;@anim/path_morph&quot; /&gt;
+ * &lt;/animated-vector&gt;
+ * </pre></li>
+ * <p>
+ * Last is the Animator xml file, which is the same as a normal ObjectAnimator
+ * or AnimatorSet.
+ * To complete this example, here are the 2 animator files used in avd.xml:
+ * rotation.xml and path_morph.xml.
+ * </p>
+ * <li>Here is the rotation.xml, which will rotate the target group for 360 degrees.
+ * <pre>
+ * &lt;objectAnimator
+ *     android:duration=&quot;6000&quot;
+ *     android:propertyName=&quot;rotation&quot;
+ *     android:valueFrom=&quot;0&quot;
+ *     android:valueTo=&quot;360&quot; /&gt;
+ * </pre></li>
+ * <li>Here is the path_morph.xml, which will morph the path from one shape to
+ * the other. Note that the paths must be compatible for morphing.
+ * In more details, the paths should have exact same length of commands , and
+ * exact same length of parameters for each commands.
+ * Note that the path string are better stored in strings.xml for reusing.
+ * <pre>
+ * &lt;set xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;&gt;
+ *     &lt;objectAnimator
+ *         android:duration=&quot;3000&quot;
+ *         android:propertyName=&quot;pathData&quot;
+ *         android:valueFrom=&quot;M300,70 l 0,-70 70,70 0,0   -70,70z&quot;
+ *         android:valueTo=&quot;M300,70 l 0,-70 70,0  0,140 -70,0 z&quot;
+ *         android:valueType=&quot;pathType&quot;/&gt;
+ * &lt;/set&gt;
+ * </pre></li>
  *
- * @hide
+ * @attr ref android.R.styleable#AnimatedVectorDrawable_drawable
+ * @attr ref android.R.styleable#AnimatedVectorDrawableTarget_name
+ * @attr ref android.R.styleable#AnimatedVectorDrawableTarget_animation
  */
 public class AnimatedVectorDrawable extends Drawable implements Animatable {
     private static final String LOGTAG = AnimatedVectorDrawable.class.getSimpleName();
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 0a394d5..e080375 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -757,7 +757,18 @@
 
         final int tileMode = a.getInt(R.styleable.BitmapDrawable_tileMode, TILE_MODE_UNDEFINED);
         if (tileMode != TILE_MODE_UNDEFINED) {
-            setTileModeInternal(tileMode);
+            final Shader.TileMode mode = parseTileMode(tileMode);
+            setTileModeXY(mode, mode);
+        }
+
+        final int tileModeX = a.getInt(R.styleable.BitmapDrawable_tileModeX, TILE_MODE_UNDEFINED);
+        if (tileModeX != TILE_MODE_UNDEFINED) {
+            setTileModeX(parseTileMode(tileModeX));
+        }
+
+        final int tileModeY = a.getInt(R.styleable.BitmapDrawable_tileModeY, TILE_MODE_UNDEFINED);
+        if (tileModeY != TILE_MODE_UNDEFINED) {
+            setTileModeY(parseTileMode(tileModeY));
         }
 
         // Update local properties.
@@ -783,20 +794,16 @@
         }
     }
 
-    private void setTileModeInternal(final int tileMode) {
+    private static Shader.TileMode parseTileMode(int tileMode) {
         switch (tileMode) {
-            case TILE_MODE_DISABLED:
-                setTileModeXY(null, null);
-                break;
             case TILE_MODE_CLAMP:
-                setTileModeXY(Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
-                break;
+                return Shader.TileMode.CLAMP;
             case TILE_MODE_REPEAT:
-                setTileModeXY(Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
-                break;
+                return Shader.TileMode.REPEAT;
             case TILE_MODE_MIRROR:
-                setTileModeXY(Shader.TileMode.MIRROR, Shader.TileMode.MIRROR);
-                break;
+                return Shader.TileMode.MIRROR;
+            default:
+                return null;
         }
     }
 
@@ -919,7 +926,9 @@
     }
 
     /**
-     * Initializes local dynamic properties from state.
+     * Initializes local dynamic properties from state. This should be called
+     * after significant state changes, e.g. from the One True Constructor and
+     * after inflating or applying a theme.
      */
     private void initializeWithState(BitmapState state, Resources res) {
         if (res != null) {
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index 369bb59..86765dd 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -396,6 +396,9 @@
                         " for ShapeDrawable " + this);
             }
         }
+
+        // Update local properties.
+        initializeWithState(mShapeState, r);
     }
 
     @Override
@@ -410,6 +413,9 @@
         final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.ShapeDrawable);
         updateStateFromTypedArray(a);
         a.recycle();
+
+        // Update local properties.
+        initializeWithState(state, t.getResources());
     }
 
     private void updateStateFromTypedArray(TypedArray a) {
@@ -431,6 +437,16 @@
                 R.styleable.ShapeDrawable_width, state.mIntrinsicWidth));
         setIntrinsicHeight((int) a.getDimension(
                 R.styleable.ShapeDrawable_height, state.mIntrinsicHeight));
+
+        final int tintMode = a.getInt(R.styleable.ShapeDrawable_tintMode, -1);
+        if (tintMode != -1) {
+            state.mTintMode = Drawable.parseTintMode(tintMode, Mode.SRC_IN);
+        }
+
+        final ColorStateList tint = a.getColorStateList(R.styleable.ShapeDrawable_tint);
+        if (tint != null) {
+            state.mTint = tint;
+        }
     }
 
     private void updateShape() {
@@ -545,6 +561,10 @@
         }
     }
 
+    /**
+     * The one constructor to rule them all. This is called by all public
+     * constructors to set the state and initialize local properties.
+     */
     private ShapeDrawable(ShapeState state, Resources res, Theme theme) {
         if (theme != null && state.canApplyTheme()) {
             mShapeState = new ShapeState(state);
@@ -553,7 +573,16 @@
             mShapeState = state;
         }
 
-        mTintFilter = updateTintFilter(mTintFilter, mShapeState.mTint, mShapeState.mTintMode);
+        initializeWithState(state, res);
+    }
+
+    /**
+     * Initializes local dynamic properties from state. This should be called
+     * after significant state changes, e.g. from the One True Constructor and
+     * after inflating or applying a theme.
+     */
+    private void initializeWithState(ShapeState state, Resources res) {
+        mTintFilter = updateTintFilter(mTintFilter, state.mTint, state.mTintMode);
     }
 
     /**
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 3773a9b..c98f2a1 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -237,34 +237,6 @@
         return PixelFormat.TRANSLUCENT;
     }
 
-    /**
-     * Sets padding for this shape, defined by a Rect object. Define the padding
-     * in the Rect object as: left, top, right, bottom.
-     */
-    public void setPadding(Rect padding) {
-        setPadding(padding.left, padding.top, padding.right, padding.bottom);
-    }
-
-    /**
-     * Sets padding for the shape.
-     *
-     * @param left padding for the left side (in pixels)
-     * @param top padding for the top (in pixels)
-     * @param right padding for the right side (in pixels)
-     * @param bottom padding for the bottom (in pixels)
-     */
-    public void setPadding(int left, int top, int right, int bottom) {
-        if ((left | top | right | bottom) == 0) {
-            mVectorState.mPadding = null;
-        } else {
-            if (mVectorState.mPadding == null) {
-                mVectorState.mPadding = new Rect();
-            }
-            mVectorState.mPadding.set(left, top, right, bottom);
-        }
-        invalidateSelf();
-    }
-
     @Override
     public int getIntrinsicWidth() {
         return (int) mVectorState.mVPathRenderer.mBaseWidth;
@@ -276,16 +248,6 @@
     }
 
     @Override
-    public boolean getPadding(Rect padding) {
-        if (mVectorState.mPadding != null) {
-            padding.set(mVectorState.mPadding);
-            return true;
-        } else {
-            return super.getPadding(padding);
-        }
-    }
-
-    @Override
     public boolean canApplyTheme() {
         return super.canApplyTheme() || mVectorState != null && mVectorState.canApplyTheme();
     }
@@ -462,7 +424,6 @@
         int[] mThemeAttrs;
         int mChangingConfigurations;
         VPathRenderer mVPathRenderer;
-        Rect mPadding;
         ColorStateList mTint;
         Mode mTintMode;
 
@@ -472,7 +433,6 @@
                 mChangingConfigurations = copy.mChangingConfigurations;
                 // TODO: Make sure the constant state are handled correctly.
                 mVPathRenderer = new VPathRenderer(copy.mVPathRenderer);
-                mPadding = new Rect(copy.mPadding);
                 mTint = copy.mTint;
                 mTintMode = copy.mTintMode;
             }
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 02e85fe..a704e19 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -45,6 +45,7 @@
 		RenderBufferCache.cpp \
 		RenderNode.cpp \
 		RenderProperties.cpp \
+		RenderState.cpp \
 		ResourceCache.cpp \
 		ShadowTessellator.cpp \
 		SkiaShader.cpp \
@@ -61,6 +62,7 @@
 	LOCAL_SRC_FILES += \
 		renderthread/CanvasContext.cpp \
 		renderthread/DrawFrameTask.cpp \
+		renderthread/EglManager.cpp \
 		renderthread/RenderProxy.cpp \
 		renderthread/RenderTask.cpp \
 		renderthread/RenderThread.cpp \
@@ -69,8 +71,6 @@
 	intermediates := $(call intermediates-dir-for,STATIC_LIBRARIES,libRS,TARGET,)
 
 	LOCAL_C_INCLUDES += \
-		$(JNI_H_INCLUDE) \
-		$(LOCAL_PATH)/../../include/utils \
 		external/skia/src/core
 
 	LOCAL_CFLAGS += -DUSE_OPENGL_RENDERER -DEGL_EGLEXT_PROTOTYPES -DGL_GLEXT_PROTOTYPES
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index 937bf8d..a998594 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -500,7 +500,7 @@
 void DeferredDisplayList::addDrawOp(OpenGLRenderer& renderer, DrawOp* op) {
     /* 1: op calculates local bounds */
     DeferredDisplayState* const state = createState();
-    if (op->getLocalBounds(renderer.getDrawModifiers(), state->mBounds)) {
+    if (op->getLocalBounds(state->mBounds)) {
         if (state->mBounds.isEmpty()) {
             // valid empty bounds, don't bother deferring
             tryRecycleState(state);
diff --git a/libs/hwui/DeferredDisplayList.h b/libs/hwui/DeferredDisplayList.h
index 48489c2..8a015b2 100644
--- a/libs/hwui/DeferredDisplayList.h
+++ b/libs/hwui/DeferredDisplayList.h
@@ -38,7 +38,6 @@
 class StateOp;
 
 class DeferredDisplayState;
-class OpenGLRenderer;
 
 class Batch;
 class DrawBatch;
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index 5082271..c76bd5e 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -23,7 +23,6 @@
 #include <utils/StrongPointer.h>
 
 #include "Layer.h"
-#include "OpenGLRenderer.h"
 #include "Rect.h"
 #include "RenderNode.h"
 
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index f418c9b..e38b532 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -90,8 +90,8 @@
     layers.clear();
 }
 
-void DisplayListData::addChild(DrawDisplayListOp* op) {
-    LOG_ALWAYS_FATAL_IF(!op->renderNode(), "DrawDisplayListOp with no render node!");
+void DisplayListData::addChild(DrawRenderNodeOp* op) {
+    LOG_ALWAYS_FATAL_IF(!op->renderNode(), "DrawRenderNodeOp with no render node!");
 
     mChildren.push(op);
     mReferenceHolders.push(op->renderNode());
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index 7b7dc16..bfffbb4 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -61,7 +61,7 @@
 class SaveLayerOp;
 class SaveOp;
 class RestoreToCountOp;
-class DrawDisplayListOp;
+class DrawRenderNodeOp;
 
 /**
  * Holds data used in the playback a tree of DisplayLists.
@@ -133,8 +133,8 @@
         return !displayListOps.size();
     }
 
-    void addChild(DrawDisplayListOp* childOp);
-    const Vector<DrawDisplayListOp*>& children() { return mChildren; }
+    void addChild(DrawRenderNodeOp* childOp);
+    const Vector<DrawRenderNodeOp*>& children() { return mChildren; }
 
     void refProperty(CanvasPropertyPrimitive* prop) {
         mReferenceHolders.push(prop);
@@ -148,7 +148,7 @@
     Vector< sp<VirtualLightRefBase> > mReferenceHolders;
 
     // list of children display lists for quick, non-drawing traversal
-    Vector<DrawDisplayListOp*> mChildren;
+    Vector<DrawRenderNodeOp*> mChildren;
 
     void cleanupResources();
 };
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index f8d620d..5ed04a0 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -171,7 +171,7 @@
      *
      * returns true if bounds exist
      */
-    virtual bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) {
+    virtual bool getLocalBounds(Rect& localBounds) {
         return false;
     }
 
@@ -253,7 +253,7 @@
     // default empty constructor for bounds, to be overridden in child constructor body
     DrawBoundedOp(const SkPaint* paint): DrawOp(paint) { }
 
-    bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) {
+    bool getLocalBounds(Rect& localBounds) {
         localBounds.set(mLocalBounds);
         OpenGLRenderer::TextShadow textShadow;
         if (OpenGLRenderer::getTextShadow(mPaint, &textShadow)) {
@@ -1029,7 +1029,7 @@
     DrawStrokableOp(float left, float top, float right, float bottom, const SkPaint* paint)
             : DrawBoundedOp(left, top, right, bottom, paint) {};
 
-    bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) {
+    bool getLocalBounds(Rect& localBounds) {
         localBounds.set(mLocalBounds);
         if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) {
             localBounds.outset(strokeWidthOutset());
@@ -1399,7 +1399,7 @@
 
     virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
         Rect bounds;
-        getLocalBounds(renderer.getDrawModifiers(), bounds);
+        getLocalBounds(bounds);
         return renderer.drawText(mText, mBytesCount, mCount, mX, mY,
                 mPositions, getPaint(renderer), mTotalAdvance, bounds);
     }
@@ -1465,23 +1465,23 @@
     Functor* mFunctor;
 };
 
-class DrawDisplayListOp : public DrawBoundedOp {
-    friend class RenderNode; // grant DisplayList access to info of child
+class DrawRenderNodeOp : public DrawBoundedOp {
+    friend class RenderNode; // grant RenderNode access to info of child
 public:
-    DrawDisplayListOp(RenderNode* displayList, int flags, const mat4& transformFromParent)
-            : DrawBoundedOp(0, 0, displayList->getWidth(), displayList->getHeight(), 0),
-            mDisplayList(displayList), mFlags(flags), mTransformFromParent(transformFromParent) {}
+    DrawRenderNodeOp(RenderNode* renderNode, int flags, const mat4& transformFromParent)
+            : DrawBoundedOp(0, 0, renderNode->getWidth(), renderNode->getHeight(), 0),
+            mRenderNode(renderNode), mFlags(flags), mTransformFromParent(transformFromParent) {}
 
     virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
             bool useQuickReject) {
-        if (mDisplayList && mDisplayList->isRenderable() && !mSkipInOrderDraw) {
-            mDisplayList->defer(deferStruct, level + 1);
+        if (mRenderNode && mRenderNode->isRenderable() && !mSkipInOrderDraw) {
+            mRenderNode->defer(deferStruct, level + 1);
         }
     }
     virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
             bool useQuickReject) {
-        if (mDisplayList && mDisplayList->isRenderable() && !mSkipInOrderDraw) {
-            mDisplayList->replay(replayStruct, level + 1);
+        if (mRenderNode && mRenderNode->isRenderable() && !mSkipInOrderDraw) {
+            mRenderNode->replay(replayStruct, level + 1);
         }
     }
 
@@ -1491,22 +1491,22 @@
     }
 
     virtual void output(int level, uint32_t logFlags) const {
-        OP_LOG("Draw Display List %p, flags %#x", mDisplayList, mFlags);
-        if (mDisplayList && (logFlags & kOpLogFlag_Recurse)) {
-            mDisplayList->output(level + 1);
+        OP_LOG("Draw Display List %p, flags %#x", mRenderNode, mFlags);
+        if (mRenderNode && (logFlags & kOpLogFlag_Recurse)) {
+            mRenderNode->output(level + 1);
         }
     }
 
-    virtual const char* name() { return "DrawDisplayList"; }
+    virtual const char* name() { return "DrawRenderNode"; }
 
-    RenderNode* renderNode() { return mDisplayList; }
+    RenderNode* renderNode() { return mRenderNode; }
 
 private:
-    RenderNode* mDisplayList;
+    RenderNode* mRenderNode;
     const int mFlags;
 
     ///////////////////////////
-    // Properties below are used by DisplayList::computeOrderingImpl() and iterate()
+    // Properties below are used by RenderNode::computeOrderingImpl() and issueOperations()
     ///////////////////////////
     /**
      * Records transform vs parent, used for computing total transform without rerunning DL contents
@@ -1514,12 +1514,12 @@
     const mat4 mTransformFromParent;
 
     /**
-     * Holds the transformation between the projection surface ViewGroup and this DisplayList
+     * Holds the transformation between the projection surface ViewGroup and this RenderNode
      * drawing instance. Represents any translations / transformations done within the drawing of
      * the compositing ancestor ViewGroup's draw, before the draw of the View represented by this
      * DisplayList draw instance.
      *
-     * Note: doesn't include any transformation recorded within the DisplayList and its properties.
+     * Note: doesn't include transformation within the RenderNode, or its properties.
      */
     mat4 mTransformFromCompositingAncestor;
     bool mSkipInOrderDraw;
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index fc4d40b..7789358 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -169,18 +169,16 @@
     return StatefulBaseRenderer::clipRegion(region, op);
 }
 
-status_t DisplayListRenderer::drawDisplayList(RenderNode* displayList,
-        Rect& dirty, int32_t flags) {
+status_t DisplayListRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t flags) {
     // dirty is an out parameter and should not be recorded,
     // it matters only when replaying the display list
 
-    if (displayList->stagingProperties().isProjectionReceiver()) {
+    if (renderNode->stagingProperties().isProjectionReceiver()) {
         // use staging property, since recording on UI thread
         mDisplayListData->projectionReceiveIndex = mDisplayListData->displayListOps.size();
     }
 
-    DrawDisplayListOp* op = new (alloc()) DrawDisplayListOp(displayList,
-            flags, *currentTransform());
+    DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp(renderNode, flags, *currentTransform());
     addDrawOp(op);
     mDisplayListData->addChild(op);
     return DrawGlInfo::kStatusDone;
@@ -427,7 +425,7 @@
 
 void DisplayListRenderer::addDrawOp(DrawOp* op) {
     Rect localBounds;
-    if (op->getLocalBounds(mDrawModifiers, localBounds)) {
+    if (op->getLocalBounds(localBounds)) {
         bool rejected = quickRejectConservative(localBounds.left, localBounds.top,
                 localBounds.right, localBounds.bottom);
         op->setQuickRejected(rejected);
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 2eaa671..8ca9af1 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -23,7 +23,6 @@
 #include <cutils/compiler.h>
 
 #include "DisplayListLogBuffer.h"
-#include "OpenGLRenderer.h"
 #include "RenderNode.h"
 
 namespace android {
@@ -53,12 +52,12 @@
 /**
  * Records drawing commands in a display list for later playback into an OpenGLRenderer.
  */
-class DisplayListRenderer: public OpenGLRenderer {
+class ANDROID_API DisplayListRenderer: public StatefulBaseRenderer {
 public:
-    ANDROID_API DisplayListRenderer();
+    DisplayListRenderer();
     virtual ~DisplayListRenderer();
 
-    ANDROID_API DisplayListData* finishRecording();
+    DisplayListData* finishRecording();
 
     virtual bool isRecording() const { return true; }
 
@@ -81,7 +80,7 @@
             const SkPaint* paint, int flags);
 
     // Matrix
-    virtual void translate(float dx, float dy, float dz);
+    virtual void translate(float dx, float dy, float dz = 0.0f);
     virtual void rotate(float degrees);
     virtual void scale(float sx, float sy);
     virtual void skew(float sx, float sy);
@@ -98,6 +97,10 @@
     virtual void resetPaintFilter();
     virtual void setupPaintFilter(int clearBits, int setBits);
 
+    bool isCurrentTransformSimple() {
+        return currentTransform()->isSimple();
+    }
+
 // ----------------------------------------------------------------------------
 // Canvas draw operations
 // ----------------------------------------------------------------------------
@@ -148,16 +151,10 @@
 // Canvas draw operations - special
 // ----------------------------------------------------------------------------
     virtual status_t drawLayer(Layer* layer, float x, float y);
-    virtual status_t drawDisplayList(RenderNode* displayList, Rect& dirty,
-            int32_t replayFlags);
+    virtual status_t drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t replayFlags);
 
     // TODO: rename for consistency
     virtual status_t callDrawGLFunction(Functor* functor, Rect& dirty);
-protected:
-    // NOTE: must override these to avoid calling into super class, which calls GL. These may be
-    // removed once DisplayListRenderer no longer inherits from OpenGLRenderer
-    virtual void onViewportInitialized() {};
-    virtual void onSnapshotRestored() {};
 
 private:
     void insertRestoreToCount();
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 24dd1d3..73a4da5 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -20,6 +20,7 @@
 
 #include "Caches.h"
 #include "DeferredDisplayList.h"
+#include "RenderState.h"
 #include "Layer.h"
 #include "LayerRenderer.h"
 #include "OpenGLRenderer.h"
@@ -28,8 +29,10 @@
 namespace android {
 namespace uirenderer {
 
-Layer::Layer(const uint32_t layerWidth, const uint32_t layerHeight):
-        caches(Caches::getInstance()), texture(caches) {
+Layer::Layer(RenderState& renderState, const uint32_t layerWidth, const uint32_t layerHeight)
+        : caches(Caches::getInstance())
+        , renderState(renderState)
+        , texture(caches) {
     mesh = NULL;
     meshElementCount = 0;
     cacheable = true;
@@ -41,7 +44,7 @@
     colorFilter = NULL;
     deferredUpdateScheduled = false;
     renderer = NULL;
-    displayList = NULL;
+    renderNode = NULL;
     fbo = 0;
     stencil = NULL;
     debugDrawUpdate = false;
@@ -72,7 +75,7 @@
 
 void Layer::requireRenderer() {
     if (!renderer) {
-        renderer = new LayerRenderer(this);
+        renderer = new LayerRenderer(renderState, this);
         renderer->initProperties();
     }
 }
@@ -123,28 +126,26 @@
 
 void Layer::removeFbo(bool flush) {
     if (stencil) {
-        GLuint previousFbo;
-        glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
-        if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+        GLuint previousFbo = renderState.getFramebuffer();
+        renderState.bindFramebuffer(fbo);
         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
-        if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
+        renderState.bindFramebuffer(previousFbo);
 
         caches.renderBufferCache.put(stencil);
         stencil = NULL;
     }
 
     if (fbo) {
-        if (flush) LayerRenderer::flushLayer(this);
+        if (flush) LayerRenderer::flushLayer(renderState, this);
         // If put fails the cache will delete the FBO
         caches.fboCache.put(fbo);
         fbo = 0;
     }
 }
 
-void Layer::updateDeferred(RenderNode* displayList,
-        int left, int top, int right, int bottom) {
+void Layer::updateDeferred(RenderNode* renderNode, int left, int top, int right, int bottom) {
     requireRenderer();
-    this->displayList = displayList;
+    this->renderNode = renderNode;
     const Rect r(left, top, right, bottom);
     dirtyRect.unionWith(r);
     deferredUpdateScheduled = true;
@@ -219,14 +220,14 @@
     renderer->setupFrameState(dirtyRect.left, dirtyRect.top,
             dirtyRect.right, dirtyRect.bottom, !isBlend());
 
-    displayList->computeOrdering();
-    displayList->defer(deferredState, 0);
+    renderNode->computeOrdering();
+    renderNode->defer(deferredState, 0);
 
     deferredUpdateScheduled = false;
 }
 
 void Layer::cancelDefer() {
-    displayList = NULL;
+    renderNode = NULL;
     deferredUpdateScheduled = false;
     if (deferredList) {
         delete deferredList;
@@ -246,7 +247,7 @@
         renderer->finish();
 
         dirtyRect.setEmpty();
-        displayList = NULL;
+        renderNode = NULL;
     }
 }
 
@@ -255,14 +256,14 @@
     renderer->prepareDirty(dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom,
             !isBlend());
 
-    renderer->drawDisplayList(displayList.get(), dirtyRect, RenderNode::kReplayFlag_ClipChildren);
+    renderer->drawRenderNode(renderNode.get(), dirtyRect, RenderNode::kReplayFlag_ClipChildren);
 
     renderer->finish();
 
     dirtyRect.setEmpty();
 
     deferredUpdateScheduled = false;
-    displayList = NULL;
+    renderNode = NULL;
 }
 
 }; // namespace uirenderer
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 49610d5..0bf05d0 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -43,6 +43,7 @@
 
 // Forward declarations
 class Caches;
+class RenderState;
 class OpenGLRenderer;
 class RenderNode;
 class DeferredDisplayList;
@@ -53,7 +54,7 @@
  */
 class Layer {
 public:
-    Layer(const uint32_t layerWidth, const uint32_t layerHeight);
+    Layer(RenderState& renderState, const uint32_t layerWidth, const uint32_t layerHeight);
     ~Layer();
 
     static uint32_t computeIdealWidth(uint32_t layerWidth);
@@ -85,8 +86,7 @@
         regionRect.translate(layer.left, layer.top);
     }
 
-    void updateDeferred(RenderNode* displayList,
-            int left, int top, int right, int bottom);
+    void updateDeferred(RenderNode* renderNode, int left, int top, int right, int bottom);
 
     inline uint32_t getWidth() const {
         return texture.width;
@@ -297,7 +297,7 @@
      */
     bool deferredUpdateScheduled;
     OpenGLRenderer* renderer;
-    sp<RenderNode> displayList;
+    sp<RenderNode> renderNode;
     Rect dirtyRect;
     bool debugDrawUpdate;
     bool hasDrawnSinceUpdate;
@@ -307,6 +307,8 @@
 
     Caches& caches;
 
+    RenderState& renderState;
+
     /**
      * Name of the FBO used to render the layer. If the name is 0
      * this layer is not backed by an FBO, but a simple texture.
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index 6be0146..13869aa 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -91,7 +91,7 @@
     mCache.clear();
 }
 
-Layer* LayerCache::get(const uint32_t width, const uint32_t height) {
+Layer* LayerCache::get(RenderState& renderState, const uint32_t width, const uint32_t height) {
     Layer* layer = NULL;
 
     LayerEntry entry(width, height);
@@ -108,7 +108,7 @@
     } else {
         LAYER_LOGD("Creating new layer %dx%d", entry.mWidth, entry.mHeight);
 
-        layer = new Layer(entry.mWidth, entry.mHeight);
+        layer = new Layer(renderState, entry.mWidth, entry.mHeight);
         layer->setBlend(true);
         layer->setEmpty(true);
         layer->setFbo(0);
diff --git a/libs/hwui/LayerCache.h b/libs/hwui/LayerCache.h
index 221bfe0..1b0fc2c 100644
--- a/libs/hwui/LayerCache.h
+++ b/libs/hwui/LayerCache.h
@@ -24,6 +24,8 @@
 namespace android {
 namespace uirenderer {
 
+class RenderState;
+
 ///////////////////////////////////////////////////////////////////////////////
 // Defines
 ///////////////////////////////////////////////////////////////////////////////
@@ -55,7 +57,7 @@
      * @param width The desired width of the layer
      * @param height The desired height of the layer
      */
-    Layer* get(const uint32_t width, const uint32_t height);
+    Layer* get(RenderState& renderState, const uint32_t width, const uint32_t height);
 
     /**
      * Adds the layer to the cache. The layer will not be added if there is
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index a5fd375..873baf5 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -20,6 +20,7 @@
 
 #include <private/hwui/DrawGlInfo.h>
 
+#include "RenderState.h"
 #include "LayerCache.h"
 #include "LayerRenderer.h"
 #include "Matrix.h"
@@ -33,7 +34,9 @@
 // Rendering
 ///////////////////////////////////////////////////////////////////////////////
 
-LayerRenderer::LayerRenderer(Layer* layer): mLayer(layer) {
+LayerRenderer::LayerRenderer(RenderState& renderState, Layer* layer)
+        : OpenGLRenderer(renderState)
+        , mLayer(layer) {
 }
 
 LayerRenderer::~LayerRenderer() {
@@ -43,7 +46,7 @@
         bool opaque) {
     LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->getFbo());
 
-    glBindFramebuffer(GL_FRAMEBUFFER, mLayer->getFbo());
+    renderState().bindFramebuffer(mLayer->getFbo());
 
     const float width = mLayer->layer.getWidth();
     const float height = mLayer->layer.getHeight();
@@ -180,7 +183,7 @@
 // Layers management
 ///////////////////////////////////////////////////////////////////////////////
 
-Layer* LayerRenderer::createRenderLayer(uint32_t width, uint32_t height) {
+Layer* LayerRenderer::createRenderLayer(RenderState& renderState, uint32_t width, uint32_t height) {
     LAYER_RENDERER_LOGD("Requesting new render layer %dx%d", width, height);
 
     Caches& caches = Caches::getInstance();
@@ -191,7 +194,7 @@
     }
 
     caches.activeTexture(0);
-    Layer* layer = caches.layerCache.get(width, height);
+    Layer* layer = caches.layerCache.get(renderState, width, height);
     if (!layer) {
         ALOGW("Could not obtain a layer");
         return NULL;
@@ -221,10 +224,9 @@
     layer->setDirty(true);
     layer->region.clear();
 
-    GLuint previousFbo;
-    glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
+    GLuint previousFbo = renderState.getFramebuffer();
 
-    glBindFramebuffer(GL_FRAMEBUFFER, layer->getFbo());
+    renderState.bindFramebuffer(layer->getFbo());
     layer->bindTexture();
 
     // Initialize the texture if needed
@@ -235,7 +237,7 @@
         // This should only happen if we run out of memory
         if (glGetError() != GL_NO_ERROR) {
             ALOGE("Could not allocate texture for layer (fbo=%d %dx%d)", fbo, width, height);
-            glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
+            renderState.bindFramebuffer(previousFbo);
             caches.resourceCache.decrementRefcount(layer);
             return NULL;
         }
@@ -244,7 +246,7 @@
     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
             layer->getTexture(), 0);
 
-    glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
+    renderState.bindFramebuffer(previousFbo);
 
     return layer;
 }
@@ -265,10 +267,10 @@
     return true;
 }
 
-Layer* LayerRenderer::createTextureLayer() {
+Layer* LayerRenderer::createTextureLayer(RenderState& renderState) {
     LAYER_RENDERER_LOGD("Creating new texture layer");
 
-    Layer* layer = new Layer(0, 0);
+    Layer* layer = new Layer(renderState, 0, 0);
     layer->setCacheable(false);
     layer->setTextureLayer(true);
     layer->setEmpty(true);
@@ -332,7 +334,7 @@
     }
 }
 
-void LayerRenderer::flushLayer(Layer* layer) {
+void LayerRenderer::flushLayer(RenderState& renderState, Layer* layer) {
 #ifdef GL_EXT_discard_framebuffer
     if (!layer) return;
 
@@ -341,20 +343,23 @@
         // If possible, discard any enqueud operations on deferred
         // rendering architectures
         if (Extensions::getInstance().hasDiscardFramebuffer()) {
-            GLuint previousFbo;
-            glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
-            if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+            GLuint previousFbo = renderState.getFramebuffer();
+            if (fbo != previousFbo) {
+                renderState.bindFramebuffer(fbo);
+            }
 
             const GLenum attachments[] = { GL_COLOR_ATTACHMENT0 };
             glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, attachments);
 
-            if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
+            if (fbo != previousFbo) {
+                renderState.bindFramebuffer(previousFbo);
+            }
         }
     }
 #endif
 }
 
-bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) {
+bool LayerRenderer::copyLayer(RenderState& renderState, Layer* layer, SkBitmap* bitmap) {
     Caches& caches = Caches::getInstance();
     if (layer && bitmap->width() <= caches.maxTextureSize &&
             bitmap->height() <= caches.maxTextureSize) {
@@ -369,7 +374,8 @@
 
         GLuint texture;
         GLuint previousFbo;
-        GLuint previousViewport[4];
+        GLsizei previousViewportWidth;
+        GLsizei previousViewportHeight;
 
         GLenum format;
         GLenum type;
@@ -404,9 +410,9 @@
         layer->setAlpha(255, SkXfermode::kSrc_Mode);
         layer->setFbo(fbo);
 
-        glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
-        glGetIntegerv(GL_VIEWPORT, (GLint*) &previousViewport);
-        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+        previousFbo = renderState.getFramebuffer();
+        renderState.getViewport(&previousViewportWidth, &previousViewportHeight);
+        renderState.bindFramebuffer(fbo);
 
         glGenTextures(1, &texture);
         if ((error = glGetError()) != GL_NO_ERROR) goto error;
@@ -431,7 +437,7 @@
         if ((error = glGetError()) != GL_NO_ERROR) goto error;
 
         {
-            LayerRenderer renderer(layer);
+            LayerRenderer renderer(renderState, layer);
             renderer.setViewport(bitmap->width(), bitmap->height());
             renderer.OpenGLRenderer::prepareDirty(0.0f, 0.0f,
                     bitmap->width(), bitmap->height(), !layer->isBlend());
@@ -471,13 +477,12 @@
         }
 #endif
 
-        glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
+        renderState.bindFramebuffer(previousFbo);
         layer->setAlpha(alpha, mode);
         layer->setFbo(previousLayerFbo);
         caches.deleteTexture(texture);
         caches.fboCache.put(fbo);
-        glViewport(previousViewport[0], previousViewport[1],
-                previousViewport[2], previousViewport[3]);
+        renderState.setViewport(previousViewportWidth, previousViewportHeight);
 
         return status;
     }
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index e79e7b8..9202e49 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -27,6 +27,8 @@
 namespace android {
 namespace uirenderer {
 
+class RenderState;
+
 ///////////////////////////////////////////////////////////////////////////////
 // Defines
 ///////////////////////////////////////////////////////////////////////////////
@@ -44,7 +46,7 @@
 
 class LayerRenderer: public OpenGLRenderer {
 public:
-    ANDROID_API LayerRenderer(Layer* layer);
+    LayerRenderer(RenderState& renderState, Layer* layer);
     virtual ~LayerRenderer();
 
     virtual void onViewportInitialized(int width, int height) { /* do nothing */ }
@@ -52,16 +54,16 @@
     virtual status_t clear(float left, float top, float right, float bottom, bool opaque);
     virtual void finish();
 
-    ANDROID_API static Layer* createTextureLayer();
-    ANDROID_API static Layer* createRenderLayer(uint32_t width, uint32_t height);
-    ANDROID_API static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height);
-    ANDROID_API static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
+    static Layer* createTextureLayer(RenderState& renderState);
+    static Layer* createRenderLayer(RenderState& renderState, uint32_t width, uint32_t height);
+    static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height);
+    static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
             bool isOpaque, bool forceFilter, GLenum renderTarget, float* textureTransform);
-    ANDROID_API static void destroyLayer(Layer* layer);
+    static void destroyLayer(Layer* layer);
     ANDROID_API static void destroyLayerDeferred(Layer* layer);
-    ANDROID_API static bool copyLayer(Layer* layer, SkBitmap* bitmap);
+    static bool copyLayer(RenderState& renderState, Layer* layer, SkBitmap* bitmap);
 
-    static void flushLayer(Layer* layer);
+    static void flushLayer(RenderState& renderState, Layer* layer);
 
 protected:
     virtual void ensureStencilBuffer();
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index e1dfeae..ede89d7 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -35,6 +35,7 @@
 #include "DeferredDisplayList.h"
 #include "DisplayListRenderer.h"
 #include "Fence.h"
+#include "RenderState.h"
 #include "PathTessellator.h"
 #include "Properties.h"
 #include "ShadowTessellator.h"
@@ -129,8 +130,10 @@
 // Constructors/destructor
 ///////////////////////////////////////////////////////////////////////////////
 
-OpenGLRenderer::OpenGLRenderer():
-        mCaches(Caches::getInstance()), mExtensions(Extensions::getInstance()) {
+OpenGLRenderer::OpenGLRenderer(RenderState& renderState)
+        : mCaches(Caches::getInstance())
+        , mExtensions(Extensions::getInstance())
+        , mRenderState(renderState) {
     // *set* draw modifiers to be 0
     memset(&mDrawModifiers, 0, sizeof(mDrawModifiers));
     mDrawModifiers.mOverrideLayerAlpha = 1.0f;
@@ -187,7 +190,7 @@
 
     discardFramebuffer(mTilingClip.left, mTilingClip.top, mTilingClip.right, mTilingClip.bottom);
 
-    glViewport(0, 0, getWidth(), getHeight());
+    mRenderState.setViewport(getWidth(), getHeight());
 
     // Functors break the tiling extension in pretty spectacular ways
     // This ensures we don't use tiling when a functor is going to be
@@ -311,46 +314,9 @@
     mFrameStarted = false;
 }
 
-void OpenGLRenderer::interrupt() {
-    if (mCaches.currentProgram) {
-        if (mCaches.currentProgram->isInUse()) {
-            mCaches.currentProgram->remove();
-            mCaches.currentProgram = NULL;
-        }
-    }
-    mCaches.resetActiveTexture();
-    mCaches.unbindMeshBuffer();
-    mCaches.unbindIndicesBuffer();
-    mCaches.resetVertexPointers();
-    mCaches.disableTexCoordsVertexArray();
-    debugOverdraw(false, false);
-}
-
-void OpenGLRenderer::resume() {
-    const Snapshot* snapshot = currentSnapshot();
-    glViewport(0, 0, getViewportWidth(), getViewportHeight());
-    glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo);
-    debugOverdraw(true, false);
-
-    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-
-    mCaches.scissorEnabled = glIsEnabled(GL_SCISSOR_TEST);
-    mCaches.enableScissor();
-    mCaches.resetScissor();
-    dirtyClip();
-
-    mCaches.activeTexture(0);
-    mCaches.resetBoundTextures();
-
-    mCaches.blend = true;
-    glEnable(GL_BLEND);
-    glBlendFunc(mCaches.lastSrcMode, mCaches.lastDstMode);
-    glBlendEquation(GL_FUNC_ADD);
-}
-
 void OpenGLRenderer::resumeAfterLayer() {
-    glViewport(0, 0, getViewportWidth(), getViewportHeight());
-    glBindFramebuffer(GL_FRAMEBUFFER, currentSnapshot()->fbo);
+    mRenderState.setViewport(getViewportWidth(), getViewportHeight());
+    mRenderState.bindFramebuffer(currentSnapshot()->fbo);
     debugOverdraw(true, false);
 
     mCaches.resetScissor();
@@ -379,20 +345,19 @@
     info.height = getViewportHeight();
     currentTransform()->copyTo(&info.transform[0]);
 
-    bool dirtyClip = mDirtyClip;
+    bool prevDirtyClip = mDirtyClip;
     // setup GL state for functor
     if (mDirtyClip) {
         setStencilFromClip(); // can issue draws, so must precede enableScissor()/interrupt()
     }
-    if (mCaches.enableScissor() || dirtyClip) {
+    if (mCaches.enableScissor() || prevDirtyClip) {
         setScissorFromClip();
     }
-    interrupt();
 
-    // call functor immediately after GL state setup
-    (*functor)(DrawGlInfo::kModeDraw, &info);
+    mRenderState.invokeFunctor(functor, DrawGlInfo::kModeDraw, &info);
+    // Scissor may have been modified, reset dirty clip
+    dirtyClip();
 
-    resume();
     return DrawGlInfo::kStatusDrew;
 }
 
@@ -413,17 +378,7 @@
 }
 
 void OpenGLRenderer::debugOverdraw(bool enable, bool clear) {
-    if (mCaches.debugOverdraw && getTargetFbo() == 0) {
-        if (clear) {
-            mCaches.disableScissor();
-            mCaches.stencil.clear();
-        }
-        if (enable) {
-            mCaches.stencil.enableDebugWrite();
-        } else {
-            mCaches.stencil.disable();
-        }
-    }
+    mRenderState.debugOverdraw(enable, clear);
 }
 
 void OpenGLRenderer::renderOverdraw() {
@@ -474,8 +429,8 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 bool OpenGLRenderer::updateLayer(Layer* layer, bool inFrame) {
-    if (layer->deferredUpdateScheduled && layer->renderer &&
-            layer->displayList.get() && layer->displayList->isRenderable()) {
+    if (layer->deferredUpdateScheduled && layer->renderer
+            && layer->renderNode.get() && layer->renderNode->isRenderable()) {
         ATRACE_CALL();
 
         Rect& dirty = layer->dirtyRect;
@@ -528,7 +483,7 @@
 
         if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
             mLayerUpdates.clear();
-            glBindFramebuffer(GL_FRAMEBUFFER, getTargetFbo());
+            mRenderState.bindFramebuffer(getTargetFbo());
         }
         endMark();
     }
@@ -556,7 +511,7 @@
         }
 
         mLayerUpdates.clear();
-        glBindFramebuffer(GL_FRAMEBUFFER, getTargetFbo());
+        mRenderState.bindFramebuffer(getTargetFbo());
 
         endMark();
     }
@@ -620,7 +575,7 @@
     bool restoreLayer = removed.flags & Snapshot::kFlagIsLayer;
 
     if (restoreViewport) {
-        glViewport(0, 0, getViewportWidth(), getViewportHeight());
+        mRenderState.setViewport(getViewportWidth(), getViewportHeight());
     }
 
     if (restoreClip) {
@@ -791,7 +746,7 @@
     }
 
     mCaches.activeTexture(0);
-    Layer* layer = mCaches.layerCache.get(bounds.getWidth(), bounds.getHeight());
+    Layer* layer = mCaches.layerCache.get(mRenderState, bounds.getWidth(), bounds.getHeight());
     if (!layer) {
         return false;
     }
@@ -853,7 +808,7 @@
     endTiling();
     debugOverdraw(false, false);
     // Bind texture to FBO
-    glBindFramebuffer(GL_FRAMEBUFFER, layer->getFbo());
+    mRenderState.bindFramebuffer(layer->getFbo());
     layer->bindTexture();
 
     // Initialize the texture if needed
@@ -876,7 +831,7 @@
     dirtyClip();
 
     // Change the ortho projection
-    glViewport(0, 0, bounds.getWidth(), bounds.getHeight());
+    mRenderState.setViewport(bounds.getWidth(), bounds.getHeight());
     return true;
 }
 
@@ -907,7 +862,7 @@
         layer->removeFbo(false);
 
         // Unbind current FBO and restore previous one
-        glBindFramebuffer(GL_FRAMEBUFFER, restored.fbo);
+        mRenderState.bindFramebuffer(restored.fbo);
         debugOverdraw(true, false);
 
         startTilingCurrentClip();
@@ -1931,25 +1886,24 @@
 // Drawing
 ///////////////////////////////////////////////////////////////////////////////
 
-status_t OpenGLRenderer::drawDisplayList(RenderNode* displayList, Rect& dirty,
-        int32_t replayFlags) {
+status_t OpenGLRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t replayFlags) {
     status_t status;
     // All the usual checks and setup operations (quickReject, setupDraw, etc.)
     // will be performed by the display list itself
-    if (displayList && displayList->isRenderable()) {
+    if (renderNode && renderNode->isRenderable()) {
         // compute 3d ordering
-        displayList->computeOrdering();
+        renderNode->computeOrdering();
         if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
             status = startFrame();
             ReplayStateStruct replayStruct(*this, dirty, replayFlags);
-            displayList->replay(replayStruct, 0);
+            renderNode->replay(replayStruct, 0);
             return status | replayStruct.mDrawGlStatus;
         }
 
         bool avoidOverdraw = !mCaches.debugOverdraw && !mCountOverdraw; // shh, don't tell devs!
         DeferredDisplayList deferredList(*currentClipRect(), avoidOverdraw);
         DeferStateStruct deferStruct(deferredList, *this, replayFlags);
-        displayList->defer(deferStruct, 0);
+        renderNode->defer(deferStruct, 0);
 
         flushLayers();
         status = startFrame();
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 346a65c..4ff5780 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -57,6 +57,7 @@
 namespace uirenderer {
 
 class DeferredDisplayState;
+class RenderState;
 class RenderNode;
 class TextSetupFunctor;
 class VertexBuffer;
@@ -119,33 +120,31 @@
  */
 class OpenGLRenderer : public StatefulBaseRenderer {
 public:
-    ANDROID_API OpenGLRenderer();
+    OpenGLRenderer(RenderState& renderState);
     virtual ~OpenGLRenderer();
 
-    ANDROID_API void initProperties();
+    void initProperties();
 
     virtual void onViewportInitialized();
     virtual status_t prepareDirty(float left, float top, float right, float bottom, bool opaque);
     virtual void finish();
-    virtual void interrupt();
-    virtual void resume();
 
-    ANDROID_API void setCountOverdrawEnabled(bool enabled) {
+    void setCountOverdrawEnabled(bool enabled) {
         mCountOverdraw = enabled;
     }
 
-    ANDROID_API float getOverdraw() {
+    float getOverdraw() {
         return mCountOverdraw ? mOverdraw : 0.0f;
     }
 
     virtual status_t callDrawGLFunction(Functor* functor, Rect& dirty);
 
-    ANDROID_API void pushLayerUpdate(Layer* layer);
-    ANDROID_API void cancelLayerUpdate(Layer* layer);
-    ANDROID_API void clearLayerUpdates();
-    ANDROID_API void flushLayerUpdates();
+    void pushLayerUpdate(Layer* layer);
+    void cancelLayerUpdate(Layer* layer);
+    void clearLayerUpdates();
+    void flushLayerUpdates();
 
-    ANDROID_API virtual int saveLayer(float left, float top, float right, float bottom,
+    virtual int saveLayer(float left, float top, float right, float bottom,
             const SkPaint* paint, int flags) {
         return saveLayer(left, top, right, bottom, paint, flags, NULL);
     }
@@ -158,7 +157,7 @@
     int saveLayerDeferred(float left, float top, float right, float bottom,
             const SkPaint* paint, int flags);
 
-    virtual status_t drawDisplayList(RenderNode* displayList, Rect& dirty, int32_t replayFlags = 1);
+    virtual status_t drawRenderNode(RenderNode* displayList, Rect& dirty, int32_t replayFlags = 1);
     virtual status_t drawLayer(Layer* layer, float x, float y);
     virtual status_t drawBitmap(const SkBitmap* bitmap, float left, float top,
             const SkPaint* paint);
@@ -231,7 +230,7 @@
     const DrawModifiers& getDrawModifiers() { return mDrawModifiers; }
     void setDrawModifiers(const DrawModifiers& drawModifiers) { mDrawModifiers = drawModifiers; }
 
-    ANDROID_API bool isCurrentTransformSimple() {
+    bool isCurrentTransformSimple() {
         return currentTransform()->isSimple();
     }
 
@@ -474,6 +473,8 @@
         return false;
     }
 
+    inline RenderState& renderState() { return mRenderState; }
+
 private:
     /**
      * Discards the content of the framebuffer if supported by the driver.
@@ -977,6 +978,7 @@
     // Various caches
     Caches& mCaches;
     Extensions& mExtensions;
+    RenderState& mRenderState;
 
     // List of rectangles to clear after saveLayer() is invoked
     Vector<Rect*> mLayers;
@@ -1012,7 +1014,6 @@
 
     bool mSkipOutlineClip;
 
-    friend class DisplayListRenderer;
     friend class Layer;
     friend class TextSetupFunctor;
     friend class DrawBitmapOp;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 4cda178..131384a 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -155,7 +155,7 @@
     }
 
     if (!mLayer) {
-        mLayer = LayerRenderer::createRenderLayer(getWidth(), getHeight());
+        mLayer = LayerRenderer::createRenderLayer(info.renderState, getWidth(), getHeight());
         applyLayerPropertiesToLayer(info);
         damageSelf(info);
     } else if (mLayer->layer.getWidth() != getWidth() || mLayer->layer.getHeight() != getHeight()) {
@@ -267,7 +267,7 @@
         mNeedsDisplayListDataSync = false;
         // Do a push pass on the old tree to handle freeing DisplayListData
         // that are no longer used
-        TreeInfo oldTreeInfo(TreeInfo::MODE_MAYBE_DETACHING);
+        TreeInfo oldTreeInfo(TreeInfo::MODE_MAYBE_DETACHING, info.renderState);
         oldTreeInfo.damageAccumulator = info.damageAccumulator;
         prepareSubTree(oldTreeInfo, mDisplayListData);
         delete mDisplayListData;
@@ -323,8 +323,8 @@
             info.prepareTextures = cache.prefetchAndMarkInUse(subtree->bitmapResources[i]);
         }
         for (size_t i = 0; i < subtree->children().size(); i++) {
-            DrawDisplayListOp* op = subtree->children()[i];
-            RenderNode* childNode = op->mDisplayList;
+            DrawRenderNodeOp* op = subtree->children()[i];
+            RenderNode* childNode = op->mRenderNode;
             info.damageAccumulator->pushTransform(&op->mTransformFromParent);
             childNode->prepareTreeImpl(info);
             info.damageAccumulator->popTransform();
@@ -455,16 +455,16 @@
     // transform properties are applied correctly to top level children
     if (mDisplayListData == NULL) return;
     for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) {
-        DrawDisplayListOp* childOp = mDisplayListData->children()[i];
-        childOp->mDisplayList->computeOrderingImpl(childOp,
+        DrawRenderNodeOp* childOp = mDisplayListData->children()[i];
+        childOp->mRenderNode->computeOrderingImpl(childOp,
                 properties().getOutline().getPath(), &mProjectedNodes, &mat4::identity());
     }
 }
 
 void RenderNode::computeOrderingImpl(
-        DrawDisplayListOp* opState,
+        DrawRenderNodeOp* opState,
         const SkPath* outlineOfProjectionSurface,
-        Vector<DrawDisplayListOp*>* compositedChildrenOfProjectionSurface,
+        Vector<DrawRenderNodeOp*>* compositedChildrenOfProjectionSurface,
         const mat4* transformFromProjectionSurface) {
     mProjectedNodes.clear();
     if (mDisplayListData == NULL || mDisplayListData->isEmpty()) return;
@@ -488,11 +488,11 @@
         const bool isProjectionReceiver = mDisplayListData->projectionReceiveIndex >= 0;
         bool haveAppliedPropertiesToProjection = false;
         for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) {
-            DrawDisplayListOp* childOp = mDisplayListData->children()[i];
-            RenderNode* child = childOp->mDisplayList;
+            DrawRenderNodeOp* childOp = mDisplayListData->children()[i];
+            RenderNode* child = childOp->mRenderNode;
 
             const SkPath* projectionOutline = NULL;
-            Vector<DrawDisplayListOp*>* projectionChildren = NULL;
+            Vector<DrawRenderNodeOp*>* projectionChildren = NULL;
             const mat4* projectionTransform = NULL;
             if (isProjectionReceiver && !child->properties().getProjectBackwards()) {
                 // if receiving projections, collect projecting descendent
@@ -571,16 +571,16 @@
     issueOperations<ReplayOperationHandler>(replayStruct.mRenderer, handler);
 }
 
-void RenderNode::buildZSortedChildList(Vector<ZDrawDisplayListOpPair>& zTranslatedNodes) {
+void RenderNode::buildZSortedChildList(Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes) {
     if (mDisplayListData == NULL || mDisplayListData->children().size() == 0) return;
 
     for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) {
-        DrawDisplayListOp* childOp = mDisplayListData->children()[i];
-        RenderNode* child = childOp->mDisplayList;
+        DrawRenderNodeOp* childOp = mDisplayListData->children()[i];
+        RenderNode* child = childOp->mRenderNode;
         float childZ = child->properties().getZ();
 
         if (!MathUtils::isZero(childZ)) {
-            zTranslatedNodes.add(ZDrawDisplayListOpPair(childZ, childOp));
+            zTranslatedNodes.add(ZDrawRenderNodeOpPair(childZ, childOp));
             childOp->mSkipInOrderDraw = true;
         } else if (!child->properties().getProjectBackwards()) {
             // regular, in order drawing DisplayList
@@ -627,7 +627,7 @@
 
 template <class T>
 int RenderNode::issueOperationsOfNegZChildren(
-        const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
+        const Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes,
         OpenGLRenderer& renderer, T& handler) {
     if (zTranslatedNodes.isEmpty()) return -1;
 
@@ -643,7 +643,7 @@
 
 template <class T>
 void RenderNode::issueOperationsOfPosZChildren(int shadowRestoreTo,
-        const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
+        const Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes,
         OpenGLRenderer& renderer, T& handler) {
     if (zTranslatedNodes.isEmpty()) return;
 
@@ -658,7 +658,7 @@
 #define SHADOW_DELTA 0.1f
 
 template <class T>
-void RenderNode::issueOperationsOf3dChildren(const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
+void RenderNode::issueOperationsOf3dChildren(const Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes,
         ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler) {
     const int size = zTranslatedNodes.size();
     if (size == 0
@@ -693,8 +693,8 @@
     float lastCasterZ = 0.0f;
     while (shadowIndex < endIndex || drawIndex < endIndex) {
         if (shadowIndex < endIndex) {
-            DrawDisplayListOp* casterOp = zTranslatedNodes[shadowIndex].value;
-            RenderNode* caster = casterOp->mDisplayList;
+            DrawRenderNodeOp* casterOp = zTranslatedNodes[shadowIndex].value;
+            RenderNode* caster = casterOp->mRenderNode;
             const float casterZ = zTranslatedNodes[shadowIndex].key;
             // attempt to render the shadow if the caster about to be drawn is its caster,
             // OR if its caster's Z value is similar to the previous potential caster
@@ -711,8 +711,8 @@
         // since it modifies the renderer's matrix
         int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag);
 
-        DrawDisplayListOp* childOp = zTranslatedNodes[drawIndex].value;
-        RenderNode* child = childOp->mDisplayList;
+        DrawRenderNodeOp* childOp = zTranslatedNodes[drawIndex].value;
+        RenderNode* child = childOp->mRenderNode;
 
         renderer.concatMatrix(childOp->mTransformFromParent);
         childOp->mSkipInOrderDraw = false; // this is horrible, I'm so sorry everyone
@@ -761,7 +761,7 @@
 
     // draw projected nodes
     for (size_t i = 0; i < mProjectedNodes.size(); i++) {
-        DrawDisplayListOp* childOp = mProjectedNodes[i];
+        DrawRenderNodeOp* childOp = mProjectedNodes[i];
 
         // matrix save, concat, and restore can be done safely without allocating operations
         int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag);
@@ -833,7 +833,7 @@
             handler(new (alloc) DrawLayerOp(mLayer, 0, 0),
                     renderer.getSaveCount() - 1, properties().getClipToBounds());
         } else {
-            Vector<ZDrawDisplayListOpPair> zTranslatedNodes;
+            Vector<ZDrawRenderNodeOpPair> zTranslatedNodes;
             buildZSortedChildList(zTranslatedNodes);
 
             // for 3d root, draw children with negative z values
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index c510ac6..3980dad 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -55,7 +55,6 @@
 namespace android {
 namespace uirenderer {
 
-class DeferredDisplayList;
 class DisplayListOp;
 class DisplayListRenderer;
 class OpenGLRenderer;
@@ -67,7 +66,7 @@
 class SaveLayerOp;
 class SaveOp;
 class RestoreToCountOp;
-class DrawDisplayListOp;
+class DrawRenderNodeOp;
 
 /**
  * Primary class for storing recorded canvas commands, as well as per-View/ViewGroup display properties.
@@ -195,9 +194,9 @@
     virtual void damageSelf(TreeInfo& info);
 
 private:
-    typedef key_value_pair_t<float, DrawDisplayListOp*> ZDrawDisplayListOpPair;
+    typedef key_value_pair_t<float, DrawRenderNodeOp*> ZDrawRenderNodeOpPair;
 
-    static size_t findNonNegativeIndex(const Vector<ZDrawDisplayListOpPair>& nodes) {
+    static size_t findNonNegativeIndex(const Vector<ZDrawRenderNodeOpPair>& nodes) {
         for (size_t i = 0; i < nodes.size(); i++) {
             if (nodes[i].key >= 0.0f) return i;
         }
@@ -211,29 +210,29 @@
 
     void applyViewPropertyTransforms(mat4& matrix, bool true3dTransform = false);
 
-    void computeOrderingImpl(DrawDisplayListOp* opState,
+    void computeOrderingImpl(DrawRenderNodeOp* opState,
             const SkPath* outlineOfProjectionSurface,
-            Vector<DrawDisplayListOp*>* compositedChildrenOfProjectionSurface,
+            Vector<DrawRenderNodeOp*>* compositedChildrenOfProjectionSurface,
             const mat4* transformFromProjectionSurface);
 
     template <class T>
     inline void setViewProperties(OpenGLRenderer& renderer, T& handler);
 
-    void buildZSortedChildList(Vector<ZDrawDisplayListOpPair>& zTranslatedNodes);
+    void buildZSortedChildList(Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes);
 
     template<class T>
     inline void issueDrawShadowOperation(const Matrix4& transformFromParent, T& handler);
 
     template <class T>
     inline int issueOperationsOfNegZChildren(
-            const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
+            const Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes,
             OpenGLRenderer& renderer, T& handler);
     template <class T>
     inline void issueOperationsOfPosZChildren(int shadowRestoreTo,
-            const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
+            const Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes,
             OpenGLRenderer& renderer, T& handler);
     template <class T>
-    inline void issueOperationsOf3dChildren(const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
+    inline void issueOperationsOf3dChildren(const Vector<ZDrawRenderNodeOpPair>& zTranslatedNodes,
             ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler);
 
     template <class T>
@@ -241,7 +240,7 @@
 
     /**
      * Issue the RenderNode's operations into a handler, recursing for subtrees through
-     * DrawDisplayListOp's defer() or replay() methods
+     * DrawRenderNodeOp's defer() or replay() methods
      */
     template <class T>
     inline void issueOperations(OpenGLRenderer& renderer, T& handler);
@@ -292,7 +291,7 @@
      */
 
     // for projection surfaces, contains a list of all children items
-    Vector<DrawDisplayListOp*> mProjectedNodes;
+    Vector<DrawRenderNodeOp*> mProjectedNodes;
 }; // class RenderNode
 
 } /* namespace uirenderer */
diff --git a/libs/hwui/RenderState.cpp b/libs/hwui/RenderState.cpp
new file mode 100644
index 0000000..97f379d
--- /dev/null
+++ b/libs/hwui/RenderState.cpp
@@ -0,0 +1,112 @@
+/*
+ * 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 "RenderState.h"
+
+namespace android {
+namespace uirenderer {
+
+RenderState::RenderState()
+        : mCaches(NULL)
+        , mViewportWidth(0)
+        , mViewportHeight(0)
+        , mFramebuffer(0) {
+}
+
+RenderState::~RenderState() {
+}
+
+void RenderState::onGLContextCreated() {
+    // This is delayed because the first access of Caches makes GL calls
+    mCaches = &Caches::getInstance();
+    mCaches->init();
+}
+
+void RenderState::setViewport(GLsizei width, GLsizei height) {
+    mViewportWidth = width;
+    mViewportHeight = height;
+    glViewport(0, 0, mViewportWidth, mViewportHeight);
+}
+
+
+void RenderState::getViewport(GLsizei* outWidth, GLsizei* outHeight) {
+    *outWidth = mViewportWidth;
+    *outHeight = mViewportHeight;
+}
+
+void RenderState::bindFramebuffer(GLuint fbo) {
+    if (mFramebuffer != fbo) {
+        mFramebuffer = fbo;
+        glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+    }
+}
+
+void RenderState::invokeFunctor(Functor* functor, DrawGlInfo::Mode mode, DrawGlInfo* info) {
+    interruptForFunctorInvoke();
+    (*functor)(mode, info);
+    resumeFromFunctorInvoke();
+}
+
+void RenderState::interruptForFunctorInvoke() {
+    if (mCaches->currentProgram) {
+        if (mCaches->currentProgram->isInUse()) {
+            mCaches->currentProgram->remove();
+            mCaches->currentProgram = NULL;
+        }
+    }
+    mCaches->resetActiveTexture();
+    mCaches->unbindMeshBuffer();
+    mCaches->unbindIndicesBuffer();
+    mCaches->resetVertexPointers();
+    mCaches->disableTexCoordsVertexArray();
+    debugOverdraw(false, false);
+}
+
+void RenderState::resumeFromFunctorInvoke() {
+    glViewport(0, 0, mViewportWidth, mViewportHeight);
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
+    debugOverdraw(false, false);
+
+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+
+    mCaches->scissorEnabled = glIsEnabled(GL_SCISSOR_TEST);
+    mCaches->enableScissor();
+    mCaches->resetScissor();
+
+    mCaches->activeTexture(0);
+    mCaches->resetBoundTextures();
+
+    mCaches->blend = true;
+    glEnable(GL_BLEND);
+    glBlendFunc(mCaches->lastSrcMode, mCaches->lastDstMode);
+    glBlendEquation(GL_FUNC_ADD);
+}
+
+void RenderState::debugOverdraw(bool enable, bool clear) {
+    if (mCaches->debugOverdraw && mFramebuffer == 0) {
+        if (clear) {
+            mCaches->disableScissor();
+            mCaches->stencil.clear();
+        }
+        if (enable) {
+            mCaches->stencil.enableDebugWrite();
+        } else {
+            mCaches->stencil.disable();
+        }
+    }
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/RenderState.h b/libs/hwui/RenderState.h
new file mode 100644
index 0000000..f7116e2
--- /dev/null
+++ b/libs/hwui/RenderState.h
@@ -0,0 +1,70 @@
+/*
+ * 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 RENDERSTATE_H
+#define RENDERSTATE_H
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <private/hwui/DrawGlInfo.h>
+
+#include "Caches.h"
+#include "utils/Macros.h"
+
+namespace android {
+namespace uirenderer {
+
+namespace renderthread {
+class RenderThread;
+}
+
+// TODO: Replace Cache's GL state tracking with this. For now it's more a thin
+// wrapper of Caches for users to migrate to.
+class RenderState {
+    PREVENT_COPY_AND_ASSIGN(RenderState);
+public:
+    void onGLContextCreated();
+
+    void setViewport(GLsizei width, GLsizei height);
+    void getViewport(GLsizei* outWidth, GLsizei* outHeight);
+
+    void bindFramebuffer(GLuint fbo);
+    GLint getFramebuffer() { return mFramebuffer; }
+
+    void invokeFunctor(Functor* functor, DrawGlInfo::Mode mode, DrawGlInfo* info);
+
+    void debugOverdraw(bool enable, bool clear);
+
+private:
+    friend class renderthread::RenderThread;
+
+    void interruptForFunctorInvoke();
+    void resumeFromFunctorInvoke();
+
+    RenderState();
+    ~RenderState();
+
+    Caches* mCaches;
+
+    GLsizei mViewportWidth;
+    GLsizei mViewportHeight;
+    GLuint mFramebuffer;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* RENDERSTATE_H */
diff --git a/libs/hwui/Renderer.h b/libs/hwui/Renderer.h
index 320895c..2ec99c9 100644
--- a/libs/hwui/Renderer.h
+++ b/libs/hwui/Renderer.h
@@ -129,21 +129,6 @@
      */
     virtual void finish() = 0;
 
-    /**
-     * This method must be invoked before handing control over to a draw functor.
-     * See callDrawGLFunction() for instance.
-     *
-     * This command must not be recorded inside display lists.
-     */
-    virtual void interrupt() = 0;
-
-    /**
-     * This method must be invoked after getting control back from a draw functor.
-     *
-     * This command must not be recorded inside display lists.
-     */
-    virtual void resume() = 0;
-
 // ----------------------------------------------------------------------------
 // Canvas state operations
 // ----------------------------------------------------------------------------
@@ -233,7 +218,7 @@
 // Canvas draw operations - special
 // ----------------------------------------------------------------------------
     virtual status_t drawLayer(Layer* layer, float x, float y) = 0;
-    virtual status_t drawDisplayList(RenderNode* displayList, Rect& dirty,
+    virtual status_t drawRenderNode(RenderNode* renderNode, Rect& dirty,
             int32_t replayFlags) = 0;
 
     // TODO: rename for consistency
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index f67e434..249e525 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -29,6 +29,7 @@
 class BaseRenderNodeAnimator;
 class AnimationListener;
 class OpenGLRenderer;
+class RenderState;
 
 class AnimationHook {
 public:
@@ -67,14 +68,15 @@
         // TODO: TRIM_MEMORY?
     };
 
-    explicit TreeInfo(TraversalMode mode)
+    explicit TreeInfo(TraversalMode mode, RenderState& renderState)
         : mode(mode)
         , frameTimeMs(0)
         , animationHook(NULL)
         , prepareTextures(mode == MODE_FULL)
         , damageAccumulator(NullDamageAccumulator::instance())
-        , renderer(0)
-        , errorHandler(0)
+        , renderState(renderState)
+        , renderer(NULL)
+        , errorHandler(NULL)
     {}
 
     const TraversalMode mode;
@@ -85,6 +87,7 @@
     bool prepareTextures;
     // Must not be null
     IDamageAccumulator* damageAccumulator;
+    RenderState& renderState;
     // The renderer that will be drawing the next frame. Use this to push any
     // layer updates or similar. May be NULL.
     OpenGLRenderer* renderer;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index dc1951b..281a8e1 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -18,332 +18,31 @@
 
 #include "CanvasContext.h"
 
-#include <cutils/properties.h>
 #include <private/hwui/DrawGlInfo.h>
 #include <strings.h>
 
+#include "EglManager.h"
 #include "RenderThread.h"
 #include "../Caches.h"
 #include "../DeferredLayerUpdater.h"
+#include "../RenderState.h"
 #include "../LayerRenderer.h"
 #include "../OpenGLRenderer.h"
 #include "../Stencil.h"
 
-#define PROPERTY_RENDER_DIRTY_REGIONS "debug.hwui.render_dirty_regions"
-#define GLES_VERSION 2
-
-// Android-specific addition that is used to show when frames began in systrace
-EGLAPI void EGLAPIENTRY eglBeginFrame(EGLDisplay dpy, EGLSurface surface);
-
 namespace android {
 namespace uirenderer {
 namespace renderthread {
 
-#define ERROR_CASE(x) case x: return #x;
-static const char* egl_error_str(EGLint error) {
-    switch (error) {
-        ERROR_CASE(EGL_SUCCESS)
-        ERROR_CASE(EGL_NOT_INITIALIZED)
-        ERROR_CASE(EGL_BAD_ACCESS)
-        ERROR_CASE(EGL_BAD_ALLOC)
-        ERROR_CASE(EGL_BAD_ATTRIBUTE)
-        ERROR_CASE(EGL_BAD_CONFIG)
-        ERROR_CASE(EGL_BAD_CONTEXT)
-        ERROR_CASE(EGL_BAD_CURRENT_SURFACE)
-        ERROR_CASE(EGL_BAD_DISPLAY)
-        ERROR_CASE(EGL_BAD_MATCH)
-        ERROR_CASE(EGL_BAD_NATIVE_PIXMAP)
-        ERROR_CASE(EGL_BAD_NATIVE_WINDOW)
-        ERROR_CASE(EGL_BAD_PARAMETER)
-        ERROR_CASE(EGL_BAD_SURFACE)
-        ERROR_CASE(EGL_CONTEXT_LOST)
-    default:
-        return "Unknown error";
-    }
-}
-static const char* egl_error_str() {
-    return egl_error_str(eglGetError());
-}
-
-static bool load_dirty_regions_property() {
-    char buf[PROPERTY_VALUE_MAX];
-    int len = property_get(PROPERTY_RENDER_DIRTY_REGIONS, buf, "true");
-    return !strncasecmp("true", buf, len);
-}
-
-// This class contains the shared global EGL objects, such as EGLDisplay
-// and EGLConfig, which are re-used by CanvasContext
-class GlobalContext {
-public:
-    static GlobalContext* get();
-
-    // Returns true on success, false on failure
-    void initialize();
-
-    bool hasContext();
-
-    void usePBufferSurface();
-    EGLSurface createSurface(EGLNativeWindowType window);
-    void destroySurface(EGLSurface surface);
-
-    void destroy();
-
-    bool isCurrent(EGLSurface surface) { return mCurrentSurface == surface; }
-    // Returns true if the current surface changed, false if it was already current
-    bool makeCurrent(EGLSurface surface);
-    void beginFrame(EGLSurface surface, EGLint* width, EGLint* height);
-    void swapBuffers(EGLSurface surface);
-
-    bool enableDirtyRegions(EGLSurface surface);
-
-    void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize);
-
-private:
-    GlobalContext();
-    // GlobalContext is never destroyed, method is purposely not implemented
-    ~GlobalContext();
-
-    void loadConfig();
-    void createContext();
-    void initAtlas();
-
-    static GlobalContext* sContext;
-
-    EGLDisplay mEglDisplay;
-    EGLConfig mEglConfig;
-    EGLContext mEglContext;
-    EGLSurface mPBufferSurface;
-
-    const bool mRequestDirtyRegions;
-    bool mCanSetDirtyRegions;
-
-    EGLSurface mCurrentSurface;
-
-    sp<GraphicBuffer> mAtlasBuffer;
-    int64_t* mAtlasMap;
-    size_t mAtlasMapSize;
-};
-
-GlobalContext* GlobalContext::sContext = 0;
-
-GlobalContext* GlobalContext::get() {
-    if (!sContext) {
-        sContext = new GlobalContext();
-    }
-    return sContext;
-}
-
-GlobalContext::GlobalContext()
-        : mEglDisplay(EGL_NO_DISPLAY)
-        , mEglConfig(0)
-        , mEglContext(EGL_NO_CONTEXT)
-        , mPBufferSurface(EGL_NO_SURFACE)
-        , mRequestDirtyRegions(load_dirty_regions_property())
-        , mCurrentSurface(EGL_NO_SURFACE)
-        , mAtlasMap(NULL)
-        , mAtlasMapSize(0) {
-    mCanSetDirtyRegions = mRequestDirtyRegions;
-    ALOGD("Render dirty regions requested: %s", mRequestDirtyRegions ? "true" : "false");
-}
-
-void GlobalContext::initialize() {
-    if (hasContext()) return;
-
-    mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-    LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
-            "Failed to get EGL_DEFAULT_DISPLAY! err=%s", egl_error_str());
-
-    EGLint major, minor;
-    LOG_ALWAYS_FATAL_IF(eglInitialize(mEglDisplay, &major, &minor) == EGL_FALSE,
-            "Failed to initialize display %p! err=%s", mEglDisplay, egl_error_str());
-
-    ALOGI("Initialized EGL, version %d.%d", (int)major, (int)minor);
-
-    loadConfig();
-    createContext();
-    usePBufferSurface();
-    Caches::getInstance().init();
-    initAtlas();
-}
-
-bool GlobalContext::hasContext() {
-    return mEglDisplay != EGL_NO_DISPLAY;
-}
-
-void GlobalContext::loadConfig() {
-    EGLint swapBehavior = mCanSetDirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
-    EGLint attribs[] = {
-            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-            EGL_RED_SIZE, 8,
-            EGL_GREEN_SIZE, 8,
-            EGL_BLUE_SIZE, 8,
-            EGL_ALPHA_SIZE, 8,
-            EGL_DEPTH_SIZE, 0,
-            EGL_CONFIG_CAVEAT, EGL_NONE,
-            EGL_STENCIL_SIZE, Stencil::getStencilSize(),
-            EGL_SURFACE_TYPE, EGL_WINDOW_BIT | swapBehavior,
-            EGL_NONE
-    };
-
-    EGLint num_configs = 1;
-    if (!eglChooseConfig(mEglDisplay, attribs, &mEglConfig, num_configs, &num_configs)
-            || num_configs != 1) {
-        // Failed to get a valid config
-        if (mCanSetDirtyRegions) {
-            ALOGW("Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...");
-            // Try again without dirty regions enabled
-            mCanSetDirtyRegions = false;
-            loadConfig();
-        } else {
-            LOG_ALWAYS_FATAL("Failed to choose config, error = %s", egl_error_str());
-        }
-    }
-}
-
-void GlobalContext::createContext() {
-    EGLint attribs[] = { EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION, EGL_NONE };
-    mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attribs);
-    LOG_ALWAYS_FATAL_IF(mEglContext == EGL_NO_CONTEXT,
-        "Failed to create context, error = %s", egl_error_str());
-}
-
-void GlobalContext::setTextureAtlas(const sp<GraphicBuffer>& buffer,
-        int64_t* map, size_t mapSize) {
-
-    // Already initialized
-    if (mAtlasBuffer.get()) {
-        ALOGW("Multiple calls to setTextureAtlas!");
-        delete map;
-        return;
-    }
-
-    mAtlasBuffer = buffer;
-    mAtlasMap = map;
-    mAtlasMapSize = mapSize;
-
-    if (hasContext()) {
-        usePBufferSurface();
-        initAtlas();
-    }
-}
-
-void GlobalContext::initAtlas() {
-    if (mAtlasBuffer.get()) {
-        Caches::getInstance().assetAtlas.init(mAtlasBuffer, mAtlasMap, mAtlasMapSize);
-    }
-}
-
-void GlobalContext::usePBufferSurface() {
-    LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
-            "usePBufferSurface() called on uninitialized GlobalContext!");
-
-    if (mPBufferSurface == EGL_NO_SURFACE) {
-        EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
-        mPBufferSurface = eglCreatePbufferSurface(mEglDisplay, mEglConfig, attribs);
-    }
-    makeCurrent(mPBufferSurface);
-}
-
-EGLSurface GlobalContext::createSurface(EGLNativeWindowType window) {
-    initialize();
-    return eglCreateWindowSurface(mEglDisplay, mEglConfig, window, NULL);
-}
-
-void GlobalContext::destroySurface(EGLSurface surface) {
-    if (isCurrent(surface)) {
-        makeCurrent(EGL_NO_SURFACE);
-    }
-    if (!eglDestroySurface(mEglDisplay, surface)) {
-        ALOGW("Failed to destroy surface %p, error=%s", (void*)surface, egl_error_str());
-    }
-}
-
-void GlobalContext::destroy() {
-    if (mEglDisplay == EGL_NO_DISPLAY) return;
-
-    usePBufferSurface();
-    if (Caches::hasInstance()) {
-        Caches::getInstance().terminate();
-    }
-
-    eglDestroyContext(mEglDisplay, mEglContext);
-    eglDestroySurface(mEglDisplay, mPBufferSurface);
-    eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-    eglTerminate(mEglDisplay);
-    eglReleaseThread();
-
-    mEglDisplay = EGL_NO_DISPLAY;
-    mEglContext = EGL_NO_CONTEXT;
-    mPBufferSurface = EGL_NO_SURFACE;
-    mCurrentSurface = EGL_NO_SURFACE;
-}
-
-bool GlobalContext::makeCurrent(EGLSurface surface) {
-    if (isCurrent(surface)) return false;
-
-    if (surface == EGL_NO_SURFACE) {
-        // If we are setting EGL_NO_SURFACE we don't care about any of the potential
-        // return errors, which would only happen if mEglDisplay had already been
-        // destroyed in which case the current context is already NO_CONTEXT
-        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-    } else if (!eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)) {
-        LOG_ALWAYS_FATAL("Failed to make current on surface %p, error=%s",
-                (void*)surface, egl_error_str());
-    }
-    mCurrentSurface = surface;
-    return true;
-}
-
-void GlobalContext::beginFrame(EGLSurface surface, EGLint* width, EGLint* height) {
-    LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE,
-            "Tried to beginFrame on EGL_NO_SURFACE!");
-    makeCurrent(surface);
-    if (width) {
-        eglQuerySurface(mEglDisplay, surface, EGL_WIDTH, width);
-    }
-    if (height) {
-        eglQuerySurface(mEglDisplay, surface, EGL_HEIGHT, height);
-    }
-    eglBeginFrame(mEglDisplay, surface);
-}
-
-void GlobalContext::swapBuffers(EGLSurface surface) {
-    eglSwapBuffers(mEglDisplay, surface);
-    EGLint err = eglGetError();
-    LOG_ALWAYS_FATAL_IF(err != EGL_SUCCESS,
-            "Encountered EGL error %d %s during rendering", err, egl_error_str(err));
-}
-
-bool GlobalContext::enableDirtyRegions(EGLSurface surface) {
-    if (!mRequestDirtyRegions) return false;
-
-    if (mCanSetDirtyRegions) {
-        if (!eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED)) {
-            ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s",
-                    (void*) surface, egl_error_str());
-            return false;
-        }
-        return true;
-    }
-    // Perhaps it is already enabled?
-    EGLint value;
-    if (!eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &value)) {
-        ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p",
-                (void*) surface, egl_error_str());
-        return false;
-    }
-    return value == EGL_BUFFER_PRESERVED;
-}
-
-CanvasContext::CanvasContext(bool translucent, RenderNode* rootRenderNode)
-        : mRenderThread(RenderThread::getInstance())
+CanvasContext::CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode)
+        : mRenderThread(thread)
+        , mEglManager(thread.eglManager())
         , mEglSurface(EGL_NO_SURFACE)
         , mDirtyRegionsEnabled(false)
         , mOpaque(!translucent)
-        , mCanvas(0)
+        , mCanvas(NULL)
         , mHaveNewSurface(false)
         , mRootRenderNode(rootRenderNode) {
-    mGlobalContext = GlobalContext::get();
 }
 
 CanvasContext::~CanvasContext() {
@@ -363,19 +62,16 @@
     mNativeWindow = window;
 
     if (mEglSurface != EGL_NO_SURFACE) {
-        mGlobalContext->destroySurface(mEglSurface);
+        mEglManager.destroySurface(mEglSurface);
         mEglSurface = EGL_NO_SURFACE;
     }
 
     if (window) {
-        mEglSurface = mGlobalContext->createSurface(window);
-        LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE,
-                "Failed to create EGLSurface for window %p, eglErr = %s",
-                (void*) window, egl_error_str());
+        mEglSurface = mEglManager.createSurface(window);
     }
 
     if (mEglSurface != EGL_NO_SURFACE) {
-        mDirtyRegionsEnabled = mGlobalContext->enableDirtyRegions(mEglSurface);
+        mDirtyRegionsEnabled = mEglManager.enableDirtyRegions(mEglSurface);
         mHaveNewSurface = true;
         makeCurrent();
     } else {
@@ -384,7 +80,7 @@
 }
 
 void CanvasContext::swapBuffers() {
-    mGlobalContext->swapBuffers(mEglSurface);
+    mEglManager.swapBuffers(mEglSurface);
     mHaveNewSurface = false;
 }
 
@@ -397,7 +93,7 @@
 bool CanvasContext::initialize(ANativeWindow* window) {
     if (mCanvas) return false;
     setSurface(window);
-    mCanvas = new OpenGLRenderer();
+    mCanvas = new OpenGLRenderer(mRenderThread.renderState());
     mCanvas->initProperties();
     return true;
 }
@@ -424,7 +120,7 @@
 void CanvasContext::makeCurrent() {
     // TODO: Figure out why this workaround is needed, see b/13913604
     // In the meantime this matches the behavior of GLRenderer, so it is not a regression
-    mHaveNewSurface |= mGlobalContext->makeCurrent(mEglSurface);
+    mHaveNewSurface |= mEglManager.makeCurrent(mEglSurface);
 }
 
 void CanvasContext::processLayerUpdate(DeferredLayerUpdater* layerUpdater, TreeInfo& info) {
@@ -452,9 +148,7 @@
     info.out.canDrawThisFrame = !runningBehind;
 
     if (info.out.hasAnimations || !info.out.canDrawThisFrame) {
-        if (info.out.hasFunctors) {
-            info.out.requiresUiRedraw = true;
-        } else if (!info.out.requiresUiRedraw) {
+        if (!info.out.requiresUiRedraw) {
             // If animationsNeedsRedraw is set don't bother posting for an RT anim
             // as we will just end up fighting the UI thread.
             mRenderThread.postFrameCallback(this);
@@ -469,7 +163,7 @@
 
 void CanvasContext::draw() {
     LOG_ALWAYS_FATAL_IF(!mCanvas || mEglSurface == EGL_NO_SURFACE,
-            "drawDisplayList called on a context with no canvas or surface!");
+            "drawRenderNode called on a context with no canvas or surface!");
 
     profiler().markPlaybackStart();
 
@@ -477,7 +171,7 @@
     mDamageAccumulator.finish(&dirty);
 
     EGLint width, height;
-    mGlobalContext->beginFrame(mEglSurface, &width, &height);
+    mEglManager.beginFrame(mEglSurface, &width, &height);
     if (width != mCanvas->getViewportWidth() || height != mCanvas->getViewportHeight()) {
         mCanvas->setViewport(width, height);
         dirty.setEmpty();
@@ -496,7 +190,7 @@
     }
 
     Rect outBounds;
-    status |= mCanvas->drawDisplayList(mRootRenderNode.get(), outBounds);
+    status |= mCanvas->drawRenderNode(mRootRenderNode.get(), outBounds);
 
     profiler().draw(mCanvas);
 
@@ -521,7 +215,7 @@
 
     profiler().startFrame();
 
-    TreeInfo info(TreeInfo::MODE_RT_ONLY);
+    TreeInfo info(TreeInfo::MODE_RT_ONLY, mRenderThread.renderState());
     info.prepareTextures = false;
 
     prepareTree(info);
@@ -530,32 +224,26 @@
     }
 }
 
-void CanvasContext::invokeFunctor(Functor* functor) {
+void CanvasContext::invokeFunctor(RenderThread& thread, Functor* functor) {
     ATRACE_CALL();
     DrawGlInfo::Mode mode = DrawGlInfo::kModeProcessNoContext;
-    if (mGlobalContext->hasContext()) {
-        requireGlContext();
+    if (thread.eglManager().hasEglContext()) {
+        thread.eglManager().requireGlContext();
         mode = DrawGlInfo::kModeProcess;
     }
 
-    if (mCanvas) {
-        mCanvas->interrupt();
-    }
-    (*functor)(mode, NULL);
-    if (mCanvas) {
-        mCanvas->resume();
-    }
+    thread.renderState().invokeFunctor(functor, mode, NULL);
 }
 
 bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
     requireGlContext();
-    TreeInfo info(TreeInfo::MODE_FULL);
+    TreeInfo info(TreeInfo::MODE_FULL, mRenderThread.renderState());
     layer->apply(info);
-    return LayerRenderer::copyLayer(layer->backingLayer(), bitmap);
+    return LayerRenderer::copyLayer(mRenderThread.renderState(), layer->backingLayer(), bitmap);
 }
 
 void CanvasContext::flushCaches(Caches::FlushMode flushMode) {
-    if (mGlobalContext->hasContext()) {
+    if (mEglManager.hasEglContext()) {
         requireGlContext();
         Caches::getInstance().flush(flushMode);
     }
@@ -568,25 +256,25 @@
 
 Layer* CanvasContext::createRenderLayer(int width, int height) {
     requireSurface();
-    return LayerRenderer::createRenderLayer(width, height);
+    return LayerRenderer::createRenderLayer(mRenderThread.renderState(), width, height);
 }
 
 Layer* CanvasContext::createTextureLayer() {
     requireSurface();
-    return LayerRenderer::createTextureLayer();
+    return LayerRenderer::createTextureLayer(mRenderThread.renderState());
 }
 
 void CanvasContext::requireGlContext() {
     if (mEglSurface != EGL_NO_SURFACE) {
         makeCurrent();
     } else {
-        mGlobalContext->usePBufferSurface();
+        mEglManager.usePBufferSurface();
     }
 }
 
-void CanvasContext::setTextureAtlas(const sp<GraphicBuffer>& buffer,
-        int64_t* map, size_t mapSize) {
-    GlobalContext::get()->setTextureAtlas(buffer, map, mapSize);
+void CanvasContext::setTextureAtlas(RenderThread& thread,
+        const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize) {
+    thread.eglManager().setTextureAtlas(buffer, map, mapSize);
 }
 
 } /* namespace renderthread */
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index d926b38..d2ce1a6 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -41,13 +41,13 @@
 
 namespace renderthread {
 
-class GlobalContext;
+class EglManager;
 
 // This per-renderer class manages the bridge between the global EGL context
 // and the render surface.
 class CanvasContext : public IFrameCallback {
 public:
-    CanvasContext(bool translucent, RenderNode* rootRenderNode);
+    CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode);
     virtual ~CanvasContext();
 
     bool initialize(ANativeWindow* window);
@@ -68,15 +68,15 @@
 
     void flushCaches(Caches::FlushMode flushMode);
 
-    void invokeFunctor(Functor* functor);
+    static void invokeFunctor(RenderThread& thread, Functor* functor);
 
     void runWithGlContext(RenderTask* task);
 
     Layer* createRenderLayer(int width, int height);
     Layer* createTextureLayer();
 
-    ANDROID_API static void setTextureAtlas(const sp<GraphicBuffer>& buffer,
-            int64_t* map, size_t mapSize);
+    ANDROID_API static void setTextureAtlas(RenderThread& thread,
+            const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize);
 
     void notifyFramePending();
 
@@ -91,8 +91,8 @@
 
     void requireGlContext();
 
-    GlobalContext* mGlobalContext;
     RenderThread& mRenderThread;
+    EglManager& mEglManager;
     sp<ANativeWindow> mNativeWindow;
     EGLSurface mEglSurface;
     bool mDirtyRegionsEnabled;
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 797566f..fddffd5 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -98,7 +98,7 @@
     bool canUnblockUiThread;
     bool canDrawThisFrame;
     {
-        TreeInfo info(TreeInfo::MODE_FULL);
+        TreeInfo info(TreeInfo::MODE_FULL, mRenderThread->renderState());
         canUnblockUiThread = syncFrameState(info);
         canDrawThisFrame = info.out.canDrawThisFrame;
     }
@@ -138,7 +138,7 @@
         }
     }
     // If prepareTextures is false, we ran out of texture cache space
-    return !info.out.hasFunctors && info.prepareTextures;
+    return info.prepareTextures;
 }
 
 void DrawFrameTask::unblockUiThread() {
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index 96f0add..243cc5d 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -41,7 +41,7 @@
 
 enum SyncResult {
     kSync_OK = 0,
-    kSync_UIRedrawRequired = 1 << 1,
+    kSync_UIRedrawRequired = 1 << 0,
 };
 
 /*
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
new file mode 100644
index 0000000..05ca34d
--- /dev/null
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -0,0 +1,288 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "EglContext"
+
+#include "EglManager.h"
+
+#include <cutils/log.h>
+#include <cutils/properties.h>
+
+#include "../RenderState.h"
+#include "RenderThread.h"
+
+#define PROPERTY_RENDER_DIRTY_REGIONS "debug.hwui.render_dirty_regions"
+#define GLES_VERSION 2
+
+// Android-specific addition that is used to show when frames began in systrace
+EGLAPI void EGLAPIENTRY eglBeginFrame(EGLDisplay dpy, EGLSurface surface);
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+#define ERROR_CASE(x) case x: return #x;
+static const char* egl_error_str(EGLint error) {
+    switch (error) {
+        ERROR_CASE(EGL_SUCCESS)
+        ERROR_CASE(EGL_NOT_INITIALIZED)
+        ERROR_CASE(EGL_BAD_ACCESS)
+        ERROR_CASE(EGL_BAD_ALLOC)
+        ERROR_CASE(EGL_BAD_ATTRIBUTE)
+        ERROR_CASE(EGL_BAD_CONFIG)
+        ERROR_CASE(EGL_BAD_CONTEXT)
+        ERROR_CASE(EGL_BAD_CURRENT_SURFACE)
+        ERROR_CASE(EGL_BAD_DISPLAY)
+        ERROR_CASE(EGL_BAD_MATCH)
+        ERROR_CASE(EGL_BAD_NATIVE_PIXMAP)
+        ERROR_CASE(EGL_BAD_NATIVE_WINDOW)
+        ERROR_CASE(EGL_BAD_PARAMETER)
+        ERROR_CASE(EGL_BAD_SURFACE)
+        ERROR_CASE(EGL_CONTEXT_LOST)
+    default:
+        return "Unknown error";
+    }
+}
+static const char* egl_error_str() {
+    return egl_error_str(eglGetError());
+}
+
+static bool load_dirty_regions_property() {
+    char buf[PROPERTY_VALUE_MAX];
+    int len = property_get(PROPERTY_RENDER_DIRTY_REGIONS, buf, "true");
+    return !strncasecmp("true", buf, len);
+}
+
+EglManager::EglManager(RenderThread& thread)
+        : mRenderThread(thread)
+        , mEglDisplay(EGL_NO_DISPLAY)
+        , mEglConfig(0)
+        , mEglContext(EGL_NO_CONTEXT)
+        , mPBufferSurface(EGL_NO_SURFACE)
+        , mRequestDirtyRegions(load_dirty_regions_property())
+        , mCurrentSurface(EGL_NO_SURFACE)
+        , mAtlasMap(NULL)
+        , mAtlasMapSize(0) {
+    mCanSetDirtyRegions = mRequestDirtyRegions;
+    ALOGD("Render dirty regions requested: %s", mRequestDirtyRegions ? "true" : "false");
+}
+
+void EglManager::initialize() {
+    if (hasEglContext()) return;
+
+    mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+    LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
+            "Failed to get EGL_DEFAULT_DISPLAY! err=%s", egl_error_str());
+
+    EGLint major, minor;
+    LOG_ALWAYS_FATAL_IF(eglInitialize(mEglDisplay, &major, &minor) == EGL_FALSE,
+            "Failed to initialize display %p! err=%s", mEglDisplay, egl_error_str());
+
+    ALOGI("Initialized EGL, version %d.%d", (int)major, (int)minor);
+
+    loadConfig();
+    createContext();
+    usePBufferSurface();
+    mRenderThread.renderState().onGLContextCreated();
+    initAtlas();
+}
+
+bool EglManager::hasEglContext() {
+    return mEglDisplay != EGL_NO_DISPLAY;
+}
+
+void EglManager::requireGlContext() {
+    LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY, "No EGL context");
+
+    // We don't care *WHAT* surface is active, just that one is active to give
+    // us access to the GL context
+    if (mCurrentSurface == EGL_NO_SURFACE) {
+        usePBufferSurface();
+    }
+}
+
+void EglManager::loadConfig() {
+    EGLint swapBehavior = mCanSetDirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
+    EGLint attribs[] = {
+            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+            EGL_RED_SIZE, 8,
+            EGL_GREEN_SIZE, 8,
+            EGL_BLUE_SIZE, 8,
+            EGL_ALPHA_SIZE, 8,
+            EGL_DEPTH_SIZE, 0,
+            EGL_CONFIG_CAVEAT, EGL_NONE,
+            EGL_STENCIL_SIZE, Stencil::getStencilSize(),
+            EGL_SURFACE_TYPE, EGL_WINDOW_BIT | swapBehavior,
+            EGL_NONE
+    };
+
+    EGLint num_configs = 1;
+    if (!eglChooseConfig(mEglDisplay, attribs, &mEglConfig, num_configs, &num_configs)
+            || num_configs != 1) {
+        // Failed to get a valid config
+        if (mCanSetDirtyRegions) {
+            ALOGW("Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...");
+            // Try again without dirty regions enabled
+            mCanSetDirtyRegions = false;
+            loadConfig();
+        } else {
+            LOG_ALWAYS_FATAL("Failed to choose config, error = %s", egl_error_str());
+        }
+    }
+}
+
+void EglManager::createContext() {
+    EGLint attribs[] = { EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION, EGL_NONE };
+    mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attribs);
+    LOG_ALWAYS_FATAL_IF(mEglContext == EGL_NO_CONTEXT,
+        "Failed to create context, error = %s", egl_error_str());
+}
+
+void EglManager::setTextureAtlas(const sp<GraphicBuffer>& buffer,
+        int64_t* map, size_t mapSize) {
+
+    // Already initialized
+    if (mAtlasBuffer.get()) {
+        ALOGW("Multiple calls to setTextureAtlas!");
+        delete map;
+        return;
+    }
+
+    mAtlasBuffer = buffer;
+    mAtlasMap = map;
+    mAtlasMapSize = mapSize;
+
+    if (hasEglContext()) {
+        usePBufferSurface();
+        initAtlas();
+    }
+}
+
+void EglManager::initAtlas() {
+    if (mAtlasBuffer.get()) {
+        Caches::getInstance().assetAtlas.init(mAtlasBuffer, mAtlasMap, mAtlasMapSize);
+    }
+}
+
+void EglManager::usePBufferSurface() {
+    LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY,
+            "usePBufferSurface() called on uninitialized GlobalContext!");
+
+    if (mPBufferSurface == EGL_NO_SURFACE) {
+        EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
+        mPBufferSurface = eglCreatePbufferSurface(mEglDisplay, mEglConfig, attribs);
+    }
+    makeCurrent(mPBufferSurface);
+}
+
+EGLSurface EglManager::createSurface(EGLNativeWindowType window) {
+    initialize();
+    EGLSurface surface = eglCreateWindowSurface(mEglDisplay, mEglConfig, window, NULL);
+    LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE,
+            "Failed to create EGLSurface for window %p, eglErr = %s",
+            (void*) window, egl_error_str());
+    return surface;
+}
+
+void EglManager::destroySurface(EGLSurface surface) {
+    if (isCurrent(surface)) {
+        makeCurrent(EGL_NO_SURFACE);
+    }
+    if (!eglDestroySurface(mEglDisplay, surface)) {
+        ALOGW("Failed to destroy surface %p, error=%s", (void*)surface, egl_error_str());
+    }
+}
+
+void EglManager::destroy() {
+    if (mEglDisplay == EGL_NO_DISPLAY) return;
+
+    usePBufferSurface();
+    if (Caches::hasInstance()) {
+        Caches::getInstance().terminate();
+    }
+
+    eglDestroyContext(mEglDisplay, mEglContext);
+    eglDestroySurface(mEglDisplay, mPBufferSurface);
+    eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    eglTerminate(mEglDisplay);
+    eglReleaseThread();
+
+    mEglDisplay = EGL_NO_DISPLAY;
+    mEglContext = EGL_NO_CONTEXT;
+    mPBufferSurface = EGL_NO_SURFACE;
+    mCurrentSurface = EGL_NO_SURFACE;
+}
+
+bool EglManager::makeCurrent(EGLSurface surface) {
+    if (isCurrent(surface)) return false;
+
+    if (surface == EGL_NO_SURFACE) {
+        // If we are setting EGL_NO_SURFACE we don't care about any of the potential
+        // return errors, which would only happen if mEglDisplay had already been
+        // destroyed in which case the current context is already NO_CONTEXT
+        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+    } else if (!eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)) {
+        LOG_ALWAYS_FATAL("Failed to make current on surface %p, error=%s",
+                (void*)surface, egl_error_str());
+    }
+    mCurrentSurface = surface;
+    return true;
+}
+
+void EglManager::beginFrame(EGLSurface surface, EGLint* width, EGLint* height) {
+    LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE,
+            "Tried to beginFrame on EGL_NO_SURFACE!");
+    makeCurrent(surface);
+    if (width) {
+        eglQuerySurface(mEglDisplay, surface, EGL_WIDTH, width);
+    }
+    if (height) {
+        eglQuerySurface(mEglDisplay, surface, EGL_HEIGHT, height);
+    }
+    eglBeginFrame(mEglDisplay, surface);
+}
+
+void EglManager::swapBuffers(EGLSurface surface) {
+    eglSwapBuffers(mEglDisplay, surface);
+    EGLint err = eglGetError();
+    LOG_ALWAYS_FATAL_IF(err != EGL_SUCCESS,
+            "Encountered EGL error %d %s during rendering", err, egl_error_str(err));
+}
+
+bool EglManager::enableDirtyRegions(EGLSurface surface) {
+    if (!mRequestDirtyRegions) return false;
+
+    if (mCanSetDirtyRegions) {
+        if (!eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED)) {
+            ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s",
+                    (void*) surface, egl_error_str());
+            return false;
+        }
+        return true;
+    }
+    // Perhaps it is already enabled?
+    EGLint value;
+    if (!eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &value)) {
+        ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p",
+                (void*) surface, egl_error_str());
+        return false;
+    }
+    return value == EGL_BUFFER_PRESERVED;
+}
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
new file mode 100644
index 0000000..a844cfc
--- /dev/null
+++ b/libs/hwui/renderthread/EglManager.h
@@ -0,0 +1,88 @@
+/*
+ * 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 EGLMANAGER_H
+#define EGLMANAGER_H
+
+#include <cutils/compiler.h>
+#include <EGL/egl.h>
+#include <ui/GraphicBuffer.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+namespace uirenderer {
+namespace renderthread {
+
+class RenderThread;
+
+// This class contains the shared global EGL objects, such as EGLDisplay
+// and EGLConfig, which are re-used by CanvasContext
+class EglManager {
+public:
+    // Returns true on success, false on failure
+    void initialize();
+
+    bool hasEglContext();
+    void requireGlContext();
+
+    void usePBufferSurface();
+    EGLSurface createSurface(EGLNativeWindowType window);
+    void destroySurface(EGLSurface surface);
+
+    void destroy();
+
+    bool isCurrent(EGLSurface surface) { return mCurrentSurface == surface; }
+    // Returns true if the current surface changed, false if it was already current
+    bool makeCurrent(EGLSurface surface);
+    void beginFrame(EGLSurface surface, EGLint* width, EGLint* height);
+    void swapBuffers(EGLSurface surface);
+
+    bool enableDirtyRegions(EGLSurface surface);
+
+    void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize);
+
+private:
+    friend class RenderThread;
+
+    EglManager(RenderThread& thread);
+    // EglContext is never destroyed, method is purposely not implemented
+    ~EglManager();
+
+    void loadConfig();
+    void createContext();
+    void initAtlas();
+
+    RenderThread& mRenderThread;
+
+    EGLDisplay mEglDisplay;
+    EGLConfig mEglConfig;
+    EGLContext mEglContext;
+    EGLSurface mPBufferSurface;
+
+    const bool mRequestDirtyRegions;
+    bool mCanSetDirtyRegions;
+
+    EGLSurface mCurrentSurface;
+
+    sp<GraphicBuffer> mAtlasBuffer;
+    int64_t* mAtlasMap;
+    size_t mAtlasMapSize;
+};
+
+} /* namespace renderthread */
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* EGLMANAGER_H */
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 4988f19..f90a26a 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -52,8 +52,8 @@
     MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \
     ARGS(method) *args = (ARGS(method) *) task->payload()
 
-CREATE_BRIDGE2(createContext, bool translucent, RenderNode* rootRenderNode) {
-    return new CanvasContext(args->translucent, args->rootRenderNode);
+CREATE_BRIDGE3(createContext, RenderThread* thread, bool translucent, RenderNode* rootRenderNode) {
+    return new CanvasContext(*args->thread, args->translucent, args->rootRenderNode);
 }
 
 RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode)
@@ -62,6 +62,7 @@
     SETUP_TASK(createContext);
     args->translucent = translucent;
     args->rootRenderNode = rootRenderNode;
+    args->thread = &mRenderThread;
     mContext = (CanvasContext*) postAndWait(task);
     mDrawFrameTask.setContext(&mRenderThread, mContext);
 }
@@ -199,20 +200,29 @@
     postAndWait(task);
 }
 
-CREATE_BRIDGE2(invokeFunctor, CanvasContext* context, Functor* functor) {
-    args->context->invokeFunctor(args->functor);
+CREATE_BRIDGE2(invokeFunctor, RenderThread* thread, Functor* functor) {
+    CanvasContext::invokeFunctor(*args->thread, args->functor);
     return NULL;
 }
 
 void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) {
     ATRACE_CALL();
+    RenderThread& thread = RenderThread::getInstance();
     SETUP_TASK(invokeFunctor);
-    args->context = mContext;
+    args->thread = &thread;
     args->functor = functor;
     if (waitForCompletion) {
-        postAndWait(task);
+        // waitForCompletion = true is expected to be fairly rare and only
+        // happen in destruction. Thus it should be fine to temporarily
+        // create a Mutex
+        Mutex mutex;
+        Condition condition;
+        SignalingRenderTask syncTask(task, &mutex, &condition);
+        AutoMutex _lock(mutex);
+        thread.queue(&syncTask);
+        condition.wait(mutex);
     } else {
-        post(task);
+        thread.queue(task);
     }
 }
 
@@ -233,7 +243,7 @@
     return NULL;
 }
 
-static void enqueueDestroyLayer(Layer* layer) {
+void RenderProxy::enqueueDestroyLayer(Layer* layer) {
     SETUP_TASK(destroyLayer);
     args->layer = layer;
     RenderThread::getInstance().queue(task);
@@ -242,7 +252,7 @@
 CREATE_BRIDGE3(createDisplayListLayer, CanvasContext* context, int width, int height) {
     Layer* layer = args->context->createRenderLayer(args->width, args->height);
     if (!layer) return 0;
-    return new DeferredLayerUpdater(layer, enqueueDestroyLayer);
+    return new DeferredLayerUpdater(layer, RenderProxy::enqueueDestroyLayer);
 }
 
 DeferredLayerUpdater* RenderProxy::createDisplayListLayer(int width, int height) {
@@ -258,7 +268,7 @@
 CREATE_BRIDGE1(createTextureLayer, CanvasContext* context) {
     Layer* layer = args->context->createTextureLayer();
     if (!layer) return 0;
-    return new DeferredLayerUpdater(layer, enqueueDestroyLayer);
+    return new DeferredLayerUpdater(layer, RenderProxy::enqueueDestroyLayer);
 }
 
 DeferredLayerUpdater* RenderProxy::createTextureLayer() {
@@ -336,6 +346,22 @@
     postAndWait(task);
 }
 
+CREATE_BRIDGE4(setTextureAtlas, RenderThread* thread, GraphicBuffer* buffer, int64_t* map, size_t size) {
+    CanvasContext::setTextureAtlas(*args->thread, args->buffer, args->map, args->size);
+    args->buffer->decStrong(0);
+    return NULL;
+}
+
+void RenderProxy::setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size) {
+    SETUP_TASK(setTextureAtlas);
+    args->thread = &mRenderThread;
+    args->buffer = buffer.get();
+    args->buffer->incStrong(0);
+    args->map = map;
+    args->size = size;
+    post(task);
+}
+
 void RenderProxy::post(RenderTask* task) {
     mRenderThread.queue(task);
 }
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index a95f8f0..df0aff0 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -73,10 +73,11 @@
             float density);
     ANDROID_API void destroyCanvasAndSurface();
 
-    ANDROID_API void invokeFunctor(Functor* functor, bool waitForCompletion);
+    ANDROID_API static void invokeFunctor(Functor* functor, bool waitForCompletion);
 
     ANDROID_API void runWithGlContext(RenderTask* task);
 
+    static void enqueueDestroyLayer(Layer* layer);
     ANDROID_API DeferredLayerUpdater* createDisplayListLayer(int width, int height);
     ANDROID_API DeferredLayerUpdater* createTextureLayer();
     ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
@@ -90,6 +91,8 @@
 
     ANDROID_API void dumpProfileInfo(int fd);
 
+    ANDROID_API void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size);
+
 private:
     RenderThread& mRenderThread;
     CanvasContext* mContext;
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 4a4e254..03e98d5 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -21,7 +21,9 @@
 #include <gui/DisplayEventReceiver.h>
 #include <utils/Log.h>
 
+#include "../RenderState.h"
 #include "CanvasContext.h"
+#include "EglManager.h"
 #include "RenderProxy.h"
 
 namespace android {
@@ -138,13 +140,16 @@
         , mDisplayEventReceiver(0)
         , mVsyncRequested(false)
         , mFrameCallbackTaskPending(false)
-        , mFrameCallbackTask(0) {
+        , mFrameCallbackTask(0)
+        , mRenderState(NULL)
+        , mEglManager(NULL) {
     mFrameCallbackTask = new DispatchFrameCallbacks(this);
     mLooper = new Looper(false);
     run("RenderThread");
 }
 
 RenderThread::~RenderThread() {
+    LOG_ALWAYS_FATAL("Can't destroy the render thread");
 }
 
 void RenderThread::initializeDisplayEventReceiver() {
@@ -159,6 +164,12 @@
             Looper::EVENT_INPUT, RenderThread::displayEventReceiverCallback, this);
 }
 
+void RenderThread::initThreadLocals() {
+    initializeDisplayEventReceiver();
+    mEglManager = new EglManager(*this);
+    mRenderState = new RenderState();
+}
+
 int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) {
     if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
         ALOGE("Display event receiver pipe was closed or an error occurred.  "
@@ -233,7 +244,7 @@
 }
 
 bool RenderThread::threadLoop() {
-    initializeDisplayEventReceiver();
+    initThreadLocals();
 
     int timeoutMillis = -1;
     for (;;) {
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 4412584..0b91e9d 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -31,12 +31,18 @@
 #include "TimeLord.h"
 
 namespace android {
+
 class DisplayEventReceiver;
 
 namespace uirenderer {
+
+class RenderState;
+
 namespace renderthread {
 
 class DispatchFrameCallbacks;
+class EglManager;
+class RenderProxy;
 
 class TaskQueue {
 public:
@@ -62,7 +68,7 @@
     ~IFrameCallback() {}
 };
 
-class ANDROID_API RenderThread : public Thread, public Singleton<RenderThread> {
+class ANDROID_API RenderThread : public Thread, protected Singleton<RenderThread> {
 public:
     // RenderThread takes complete ownership of tasks that are queued
     // and will delete them after they are run
@@ -79,6 +85,8 @@
     void pushBackFrameCallback(IFrameCallback* callback);
 
     TimeLord& timeLord() { return mTimeLord; }
+    RenderState& renderState() { return *mRenderState; }
+    EglManager& eglManager() { return *mEglManager; }
 
 protected:
     virtual bool threadLoop();
@@ -86,10 +94,12 @@
 private:
     friend class Singleton<RenderThread>;
     friend class DispatchFrameCallbacks;
+    friend class RenderProxy;
 
     RenderThread();
     virtual ~RenderThread();
 
+    void initThreadLocals();
     void initializeDisplayEventReceiver();
     static int displayEventReceiverCallback(int fd, int events, void* data);
     void drainDisplayEventQueue(bool skipCallbacks = false);
@@ -119,6 +129,8 @@
     DispatchFrameCallbacks* mFrameCallbackTask;
 
     TimeLord mTimeLord;
+    RenderState* mRenderState;
+    EglManager* mEglManager;
 };
 
 } /* namespace renderthread */
diff --git a/media/java/android/media/MediaMetadata.java b/media/java/android/media/MediaMetadata.java
index 5dc8e1b..5d2f3bd 100644
--- a/media/java/android/media/MediaMetadata.java
+++ b/media/java/android/media/MediaMetadata.java
@@ -260,7 +260,7 @@
             rating = mBundle.getParcelable(key);
         } catch (Exception e) {
             // ignore, value was not a bitmap
-            Log.d(TAG, "Failed to retrieve a key as Rating.", e);
+            Log.w(TAG, "Failed to retrieve a key as Rating.", e);
         }
         return rating;
     }
@@ -278,7 +278,7 @@
             bmp = mBundle.getParcelable(key);
         } catch (Exception e) {
             // ignore, value was not a bitmap
-            Log.d(TAG, "Failed to retrieve a key as Bitmap.", e);
+            Log.w(TAG, "Failed to retrieve a key as Bitmap.", e);
         }
         return bmp;
     }
@@ -323,8 +323,8 @@
         return EDITOR_KEY_MAPPING.get(editorKey, null);
     }
 
-    public static final Parcelable.Creator<MediaMetadata> CREATOR
-            = new Parcelable.Creator<MediaMetadata>() {
+    public static final Parcelable.Creator<MediaMetadata> CREATOR =
+            new Parcelable.Creator<MediaMetadata>() {
                 @Override
                 public MediaMetadata createFromParcel(Parcel in) {
                     return new MediaMetadata(in);
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 66175d0..d1909bc 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -2335,7 +2335,9 @@
                 case MEDIA_INFO_EXTERNAL_METADATA_UPDATE:
                     msg.arg1 = MEDIA_INFO_METADATA_UPDATE;
                     // update default track selection
-                    mSubtitleController.selectDefaultTrack();
+                    if (mSubtitleController != null) {
+                        mSubtitleController.selectDefaultTrack();
+                    }
                     break;
                 }
 
diff --git a/media/java/android/media/MiniThumbFile.java b/media/java/android/media/MiniThumbFile.java
index 23c3652..664308c 100644
--- a/media/java/android/media/MiniThumbFile.java
+++ b/media/java/android/media/MiniThumbFile.java
@@ -248,7 +248,8 @@
                 long magic = mBuffer.getLong();
                 int length = mBuffer.getInt();
 
-                if (size >= 1 + 8 + 4 + length && data.length >= length) {
+                if (size >= 1 + 8 + 4 + length && length != 0 && magic != 0 && flag == 1 &&
+                        data.length >= length) {
                     mBuffer.get(data, 0, length);
                     return data;
                 }
diff --git a/media/java/android/media/Rating.java b/media/java/android/media/Rating.java
index f4fbe2c..a518bb4 100644
--- a/media/java/android/media/Rating.java
+++ b/media/java/android/media/Rating.java
@@ -30,6 +30,7 @@
  */
 public final class Rating implements Parcelable {
     private final static String TAG = "Rating";
+
     /**
      * Indicates a rating style is not supported. A Rating will never have this
      * type, but can be used by other classes to indicate they do not support
@@ -79,12 +80,8 @@
         mRatingValue = rating;
     }
 
-
-    /**
-     * @hide
-     */
     @Override
-    public String toString () {
+    public String toString() {
         return "Rating:style=" + mRatingStyle + " rating="
                 + (mRatingValue < 0.0f ? "unrated" : String.valueOf(mRatingValue));
     }
@@ -107,9 +104,12 @@
          * @param p    Parcel object to read the Rating from
          * @return a new Rating created from the data in the parcel
          */
+        @Override
         public Rating createFromParcel(Parcel p) {
             return new Rating(p.readInt(), p.readFloat());
         }
+
+        @Override
         public Rating[] newArray(int size) {
             return new Rating[size];
         }
diff --git a/media/java/android/media/RemoteController.java b/media/java/android/media/RemoteController.java
index be96398..1f5b216 100644
--- a/media/java/android/media/RemoteController.java
+++ b/media/java/android/media/RemoteController.java
@@ -35,6 +35,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.SystemClock;
+import android.os.UserHandle;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.KeyEvent;
@@ -793,12 +794,12 @@
         final ComponentName listenerComponent = new ComponentName(mContext,
                 mOnClientUpdateListener.getClass());
         mSessionManager.addActiveSessionsListener(mSessionListener, listenerComponent,
-                ActivityManager.getCurrentUser());
+                UserHandle.myUserId());
         mSessionListener.onActiveSessionsChanged(mSessionManager
                 .getActiveSessions(listenerComponent));
         if (DEBUG) {
             Log.d(TAG, "Registered session listener with component " + listenerComponent
-                    + " for user " + ActivityManager.getCurrentUser());
+                    + " for user " + UserHandle.myUserId());
         }
     }
 
@@ -809,7 +810,7 @@
         mSessionManager.removeActiveSessionsListener(mSessionListener);
         if (DEBUG) {
             Log.d(TAG, "Unregistered session listener for user "
-                    + ActivityManager.getCurrentUser());
+                    + UserHandle.myUserId());
         }
     }
 
diff --git a/media/java/android/media/VolumeProvider.java b/media/java/android/media/VolumeProvider.java
index 7d93b40..d151e66 100644
--- a/media/java/android/media/VolumeProvider.java
+++ b/media/java/android/media/VolumeProvider.java
@@ -16,8 +16,6 @@
 package android.media;
 
 import android.media.session.MediaSession;
-import android.os.RemoteException;
-import android.util.Log;
 
 /**
  * Handles requests to adjust or set the volume on a session. This is also used
@@ -26,8 +24,6 @@
  * {@link MediaSession#setPlaybackToRemote}.
  */
 public abstract class VolumeProvider {
-    private static final String TAG = "VolumeProvider";
-
     /**
      * The volume is fixed and can not be modified. Requests to change volume
      * should be ignored.
@@ -50,8 +46,7 @@
 
     private final int mControlType;
     private final int mMaxVolume;
-
-    private MediaSession mSession;
+    private Callback mCallback;
 
     /**
      * Create a new volume provider for handling volume events. You must specify
@@ -92,10 +87,12 @@
     }
 
     /**
-     * Notify the system that the remote playback's volume has been changed.
+     * Notify the system that the volume has been changed.
      */
     public final void notifyVolumeChanged() {
-        mSession.notifyRemoteVolumeChanged(this);
+        if (mCallback != null) {
+            mCallback.onVolumeChanged(this);
+        }
     }
 
     /**
@@ -116,9 +113,18 @@
     }
 
     /**
+     * Sets a callback to receive volume changes.
      * @hide
      */
-    public void setSession(MediaSession session) {
-        mSession = session;
+    public void setCallback(Callback callback) {
+        mCallback = callback;
+    }
+
+    /**
+     * Listens for changes to the volume.
+     * @hide
+     */
+    public static abstract class Callback {
+        public abstract void onVolumeChanged(VolumeProvider volumeProvider);
     }
 }
\ No newline at end of file
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 84dad25..cc3db26 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -16,6 +16,8 @@
 
 package android.media.session;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.media.MediaMetadata;
 import android.media.Rating;
 import android.media.VolumeProvider;
@@ -44,7 +46,7 @@
  * MediaController objects are thread-safe.
  */
 public final class MediaController {
-    private static final String TAG = "SessionController";
+    private static final String TAG = "MediaController";
 
     private static final int MSG_EVENT = 1;
     private static final int MSG_UPDATE_PLAYBACK_STATE = 2;
@@ -75,14 +77,14 @@
     }
 
     /**
-     * Get a new MediaController for a MediaSessionToken. If successful the
-     * controller returned will be connected to the session that generated the
-     * token.
+     * Get a new media controller from a session token which may have
+     * been obtained from another process.  If successful the controller returned
+     * will be connected to the session that generated the token.
      *
-     * @param token The session token to use
-     * @return A controller for the session or null
+     * @param token The session token to control.
+     * @return A controller for the session or null if inaccessible.
      */
-    public static MediaController fromToken(MediaSessionToken token) {
+    public static MediaController fromToken(@NonNull MediaSessionToken token) {
         return fromBinder(token.getBinder());
     }
 
@@ -91,7 +93,7 @@
      *
      * @return A controls instance
      */
-    public TransportControls getTransportControls() {
+    public @NonNull TransportControls getTransportControls() {
         return mTransportController;
     }
 
@@ -102,7 +104,7 @@
      * @param keyEvent The media button event to dispatch.
      * @return true if the event was sent to the session, false otherwise.
      */
-    public boolean dispatchMediaButtonEvent(KeyEvent keyEvent) {
+    public boolean dispatchMediaButtonEvent(@NonNull KeyEvent keyEvent) {
         if (keyEvent == null) {
             throw new IllegalArgumentException("KeyEvent may not be null");
         }
@@ -122,7 +124,7 @@
      *
      * @return The current PlaybackState or null
      */
-    public PlaybackState getPlaybackState() {
+    public @Nullable PlaybackState getPlaybackState() {
         try {
             return mSessionBinder.getPlaybackState();
         } catch (RemoteException e) {
@@ -136,7 +138,7 @@
      *
      * @return The current MediaMetadata or null.
      */
-    public MediaMetadata getMetadata() {
+    public @Nullable MediaMetadata getMetadata() {
         try {
             return mSessionBinder.getMetadata();
         } catch (RemoteException e) {
@@ -188,7 +190,7 @@
      *
      * @return The current volume info or null.
      */
-    public VolumeInfo getVolumeInfo() {
+    public @Nullable VolumeInfo getVolumeInfo() {
         try {
             ParcelableVolumeInfo result = mSessionBinder.getVolumeAttributes();
             return new VolumeInfo(result.volumeType, result.audioStream, result.controlType,
@@ -204,26 +206,29 @@
      * Adds a callback to receive updates from the Session. Updates will be
      * posted on the caller's thread.
      *
-     * @param cb The callback object, must not be null
+     * @param callback The callback object, must not be null.
      */
-    public void addCallback(Callback cb) {
-        addCallback(cb, null);
+    public void addCallback(@NonNull Callback callback) {
+        addCallback(callback, null);
     }
 
     /**
      * Adds a callback to receive updates from the session. Updates will be
      * posted on the specified handler's thread.
      *
-     * @param cb Cannot be null.
+     * @param callback The callback object, must not be null.
      * @param handler The handler to post updates on. If null the callers thread
-     *            will be used
+     *            will be used.
      */
-    public void addCallback(Callback cb, Handler handler) {
+    public void addCallback(@NonNull Callback callback, @Nullable Handler handler) {
+        if (callback == null) {
+            throw new IllegalArgumentException("callback must not be null");
+        }
         if (handler == null) {
             handler = new Handler();
         }
         synchronized (mLock) {
-            addCallbackLocked(cb, handler);
+            addCallbackLocked(callback, handler);
         }
     }
 
@@ -231,11 +236,14 @@
      * Stop receiving updates on the specified callback. If an update has
      * already been posted you may still receive it after calling this method.
      *
-     * @param cb The callback to remove
+     * @param callback The callback to remove.
      */
-    public void removeCallback(Callback cb) {
+    public void removeCallback(@NonNull Callback callback) {
+        if (callback == null) {
+            throw new IllegalArgumentException("callback must not be null");
+        }
         synchronized (mLock) {
-            removeCallbackLocked(cb);
+            removeCallbackLocked(callback);
         }
     }
 
@@ -248,7 +256,8 @@
      * @param params Any parameters to include with the command
      * @param cb The callback to receive the result on
      */
-    public void sendControlCommand(String command, Bundle params, ResultReceiver cb) {
+    public void sendControlCommand(@NonNull String command, @Nullable Bundle params,
+            @Nullable ResultReceiver cb) {
         if (TextUtils.isEmpty(command)) {
             throw new IllegalArgumentException("command cannot be null or empty");
         }
@@ -298,12 +307,6 @@
     }
 
     private void addCallbackLocked(Callback cb, Handler handler) {
-        if (cb == null) {
-            throw new IllegalArgumentException("Callback cannot be null");
-        }
-        if (handler == null) {
-            throw new IllegalArgumentException("Handler cannot be null");
-        }
         if (getHandlerForCallbackLocked(cb) != null) {
             Log.w(TAG, "Callback is already added, ignoring");
             return;
@@ -322,9 +325,6 @@
     }
 
     private boolean removeCallbackLocked(Callback cb) {
-        if (cb == null) {
-            throw new IllegalArgumentException("Callback cannot be null");
-        }
         boolean success = false;
         for (int i = mCallbacks.size() - 1; i >= 0; i--) {
             MessageHandler handler = mCallbacks.get(i);
@@ -375,9 +375,10 @@
          * specified interface. Controllers should only handle these for
          * sessions they own.
          *
-         * @param event
+         * @param event The event from the session.
+         * @param extras Optional parameters for the event, may be null.
          */
-        public void onSessionEvent(String event, Bundle extras) {
+        public void onSessionEvent(@NonNull String event, @Nullable Bundle extras) {
         }
 
         /**
@@ -394,16 +395,16 @@
          *
          * @param state The new playback state of the session
          */
-        public void onPlaybackStateChanged(PlaybackState state) {
+        public void onPlaybackStateChanged(@NonNull PlaybackState state) {
         }
 
         /**
          * Override to handle changes to the current metadata.
          *
+         * @param metadata The current metadata for the session or null if none.
          * @see MediaMetadata
-         * @param metadata The current metadata for the session or null
          */
-        public void onMetadataChanged(MediaMetadata metadata) {
+        public void onMetadataChanged(@Nullable MediaMetadata metadata) {
         }
     }
 
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index 406b1c3..8909d55 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -51,10 +51,9 @@
  * for all playback, though multiple sessions can be created to provide finer
  * grain controls of media.
  * <p>
- * A MediaSession is created by calling
- * {@link MediaSessionManager#createSession(String)}. Once a session is created
- * the owner of the session may use {@link #getSessionToken()} to allow apps to
- * create a {@link MediaController} to interact with this session.
+ * Once a session is created the owner of the session may pass its
+ * {@link #getSessionToken() session token} to other processes to allow them to
+ * create a {@link MediaController} to interact with the session.
  * <p>
  * To receive commands, media keys, and other events a {@link Callback} must be
  * set with {@link #addCallback(Callback)}. To receive transport control
@@ -64,10 +63,10 @@
  * When an app is finished performing playback it must call {@link #release()}
  * to clean up the session and notify any controllers.
  * <p>
- * MediaSession objects are thread safe
+ * MediaSession objects are thread safe.
  */
 public final class MediaSession {
-    private static final String TAG = "Session";
+    private static final String TAG = "MediaSession";
 
     /**
      * Set this flag on the session to indicate that it can handle media button
@@ -77,9 +76,8 @@
 
     /**
      * Set this flag on the session to indicate that it handles transport
-     * control commands through a {@link TransportControlsCallback}. The
-     * callback can be retrieved by calling
-     * {@link #addTransportControlsCallback}.
+     * control commands through a {@link TransportControlsCallback}.
+     * The callback can be retrieved by calling {@link #addTransportControlsCallback}.
      */
     public static final int FLAG_HANDLES_TRANSPORT_CONTROLS = 1 << 1;
 
@@ -153,7 +151,7 @@
     private Route mRoute;
     private VolumeProvider mVolumeProvider;
 
-    private boolean mActive = false;;
+    private boolean mActive = false;
 
     /**
      * @hide
@@ -177,7 +175,7 @@
      *
      * @param callback The callback object
      */
-    public void addCallback(Callback callback) {
+    public void addCallback(@NonNull Callback callback) {
         addCallback(callback, null);
     }
 
@@ -188,7 +186,7 @@
      * @param callback The callback to receive updates on.
      * @param handler The handler that events should be posted on.
      */
-    public void addCallback(Callback callback, Handler handler) {
+    public void addCallback(@NonNull Callback callback, @Nullable Handler handler) {
         if (callback == null) {
             throw new IllegalArgumentException("Callback cannot be null");
         }
@@ -211,7 +209,7 @@
      *
      * @param callback The callback to remove.
      */
-    public void removeCallback(Callback callback) {
+    public void removeCallback(@NonNull Callback callback) {
         synchronized (mLock) {
             removeCallbackLocked(callback);
         }
@@ -223,7 +221,7 @@
      *
      * @param pi The intent to launch to show UI for this Session.
      */
-    public void setLaunchPendingIntent(PendingIntent pi) {
+    public void setLaunchPendingIntent(@Nullable PendingIntent pi) {
         // TODO
     }
 
@@ -234,7 +232,7 @@
      * @param mbr The receiver component to send the media button event to.
      * @hide
      */
-    public void setMediaButtonReceiver(ComponentName mbr) {
+    public void setMediaButtonReceiver(@Nullable ComponentName mbr) {
         try {
             mBinder.setMediaButtonReceiver(mbr);
         } catch (RemoteException e) {
@@ -283,12 +281,17 @@
      * @param volumeProvider The provider that will handle volume changes. May
      *            not be null.
      */
-    public void setPlaybackToRemote(VolumeProvider volumeProvider) {
+    public void setPlaybackToRemote(@NonNull VolumeProvider volumeProvider) {
         if (volumeProvider == null) {
             throw new IllegalArgumentException("volumeProvider may not be null!");
         }
         mVolumeProvider = volumeProvider;
-        volumeProvider.setSession(this);
+        volumeProvider.setCallback(new VolumeProvider.Callback() {
+            @Override
+            public void onVolumeChanged(VolumeProvider volumeProvider) {
+                notifyRemoteVolumeChanged(volumeProvider);
+            }
+        });
 
         try {
             mBinder.configureVolumeHandling(VOLUME_TYPE_REMOTE, volumeProvider.getVolumeControl(),
@@ -335,7 +338,7 @@
      * @param event The name of the event to send
      * @param extras Any extras included with the event
      */
-    public void sendSessionEvent(String event, Bundle extras) {
+    public void sendSessionEvent(@NonNull String event, @Nullable Bundle extras) {
         if (TextUtils.isEmpty(event)) {
             throw new IllegalArgumentException("event cannot be null or empty");
         }
@@ -367,7 +370,7 @@
      * @return A token that can be used to create a MediaController for this
      *         session
      */
-    public MediaSessionToken getSessionToken() {
+    public @NonNull MediaSessionToken getSessionToken() {
         return mSessionToken;
     }
 
@@ -512,7 +515,7 @@
      *
      * @param state The current state of playback
      */
-    public void setPlaybackState(PlaybackState state) {
+    public void setPlaybackState(@Nullable PlaybackState state) {
         try {
             mBinder.setPlaybackState(state);
         } catch (RemoteException e) {
@@ -526,7 +529,7 @@
      *
      * @param metadata The new metadata
      */
-    public void setMetadata(MediaMetadata metadata) {
+    public void setMetadata(@Nullable MediaMetadata metadata) {
         try {
             mBinder.setMetadata(metadata);
         } catch (RemoteException e) {
@@ -714,7 +717,7 @@
          * @param mediaButtonIntent an intent containing the KeyEvent as an
          *            extra
          */
-        public void onMediaButtonEvent(Intent mediaButtonIntent) {
+        public void onMediaButtonEvent(@NonNull Intent mediaButtonIntent) {
         }
 
         /**
@@ -722,10 +725,12 @@
          * The owner of the session may handle custom commands but is not
          * required to.
          *
-         * @param command
-         * @param extras optional
+         * @param command The command name.
+         * @param extras Optional parameters for the command, may be null.
+         * @param cb A result receiver to which a result may be sent by the command, may be null.
          */
-        public void onControlCommand(String command, Bundle extras, ResultReceiver cb) {
+        public void onControlCommand(@NonNull String command, @Nullable Bundle extras,
+                @Nullable ResultReceiver cb) {
         }
 
         /**
@@ -831,7 +836,7 @@
          *
          * @param rating
          */
-        public void onSetRating(Rating rating) {
+        public void onSetRating(@NonNull Rating rating) {
         }
 
         /**
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 2e6b86e..882453f 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -16,6 +16,8 @@
 
 package android.media.session;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Context;
 import android.media.session.ISessionManager;
@@ -24,6 +26,7 @@
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.service.notification.NotificationListenerService;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.KeyEvent;
 
@@ -63,10 +66,10 @@
     /**
      * Creates a new session.
      *
-     * @param tag A short name for debugging purposes
-     * @return a {@link MediaSession} for the new session
+     * @param tag A short name for debugging purposes.
+     * @return A {@link MediaSession} for the new session.
      */
-    public MediaSession createSession(String tag) {
+    public @NonNull MediaSession createSession(@NonNull String tag) {
         return createSessionAsUser(tag, UserHandle.myUserId());
     }
 
@@ -76,12 +79,16 @@
      * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}
      * permission.
      *
-     * @param tag A short name for debugging purposes
+     * @param tag A short name for debugging purposes.
      * @param userId The user id to create the session as.
-     * @return a {@link MediaSession} for the new session
+     * @return A {@link MediaSession} for the new session.
      * @hide
      */
-    public MediaSession createSessionAsUser(String tag, int userId) {
+    public @NonNull MediaSession createSessionAsUser(@NonNull String tag, int userId) {
+        if (TextUtils.isEmpty(tag)) {
+            throw new IllegalArgumentException("tag must not be null or empty");
+        }
+
         try {
             MediaSession.CallbackStub cbStub = new MediaSession.CallbackStub();
             MediaSession session = new MediaSession(mService
@@ -108,10 +115,10 @@
      *
      * @param notificationListener The enabled notification listener component.
      *            May be null.
-     * @return A list of controllers for ongoing sessions
-     * @hide
+     * @return A list of controllers for ongoing sessions.
      */
-    public List<MediaController> getActiveSessions(ComponentName notificationListener) {
+    public @NonNull List<MediaController> getActiveSessions(
+            @Nullable ComponentName notificationListener) {
         return getActiveSessionsForUser(notificationListener, UserHandle.myUserId());
     }
 
@@ -128,8 +135,8 @@
      * @return A list of controllers for ongoing sessions.
      * @hide
      */
-    public List<MediaController> getActiveSessionsForUser(ComponentName notificationListener,
-            int userId) {
+    public @NonNull List<MediaController> getActiveSessionsForUser(
+            @Nullable ComponentName notificationListener, int userId) {
         ArrayList<MediaController> controllers = new ArrayList<MediaController>();
         try {
             List<IBinder> binders = mService.getSessions(notificationListener, userId);
@@ -157,11 +164,29 @@
      * @param sessionListener The listener to add.
      * @param notificationListener The enabled notification listener component.
      *            May be null.
+     */
+    public void addActiveSessionsListener(SessionListener sessionListener,
+            ComponentName notificationListener) {
+        addActiveSessionsListener(sessionListener, notificationListener, UserHandle.myUserId());
+    }
+
+    /**
+     * Add a listener to be notified when the list of active sessions
+     * changes.This requires the
+     * android.Manifest.permission.MEDIA_CONTENT_CONTROL permission be held by
+     * the calling app. You may also retrieve this list if your app is an
+     * enabled notification listener using the
+     * {@link NotificationListenerService} APIs, in which case you must pass the
+     * {@link ComponentName} of your enabled listener.
+     *
+     * @param sessionListener The listener to add.
+     * @param notificationListener The enabled notification listener component.
+     *            May be null.
      * @param userId The userId to listen for changes on.
      * @hide
      */
-    public void addActiveSessionsListener(SessionListener sessionListener,
-            ComponentName notificationListener, int userId) {
+    public void addActiveSessionsListener(@NonNull SessionListener sessionListener,
+            @Nullable ComponentName notificationListener, int userId) {
         if (sessionListener == null) {
             throw new IllegalArgumentException("listener may not be null");
         }
@@ -178,7 +203,7 @@
      * @param listener The listener to remove.
      * @hide
      */
-    public void removeActiveSessionsListener(SessionListener listener) {
+    public void removeActiveSessionsListener(@NonNull SessionListener listener) {
         if (listener == null) {
             throw new IllegalArgumentException("listener may not be null");
         }
@@ -195,19 +220,18 @@
      * @param keyEvent The KeyEvent to send.
      * @hide
      */
-    public void dispatchMediaKeyEvent(KeyEvent keyEvent) {
+    public void dispatchMediaKeyEvent(@NonNull KeyEvent keyEvent) {
         dispatchMediaKeyEvent(keyEvent, false);
     }
 
     /**
      * Send a media key event. The receiver will be selected automatically.
      *
-     * @param keyEvent The KeyEvent to send
-     * @param needWakeLock true if a wake lock should be held while sending the
-     *            key
+     * @param keyEvent The KeyEvent to send.
+     * @param needWakeLock True if a wake lock should be held while sending the key.
      * @hide
      */
-    public void dispatchMediaKeyEvent(KeyEvent keyEvent, boolean needWakeLock) {
+    public void dispatchMediaKeyEvent(@NonNull KeyEvent keyEvent, boolean needWakeLock) {
         try {
             mService.dispatchMediaKeyEvent(keyEvent, needWakeLock);
         } catch (RemoteException e) {
@@ -236,8 +260,6 @@
     /**
      * Listens for changes to the list of active sessions. This can be added
      * using {@link #addActiveSessionsListener}.
-     *
-     * @hide
      */
     public static abstract class SessionListener {
         /**
@@ -249,7 +271,8 @@
          * @param controllers The updated list of controllers for the user that
          *            changed.
          */
-        public abstract void onActiveSessionsChanged(List<MediaController> controllers);
+        public abstract void onActiveSessionsChanged(
+                @Nullable List<MediaController> controllers);
 
         private final IActiveSessionsListener.Stub mStub = new IActiveSessionsListener.Stub() {
             @Override
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index 3b3f249..6125cb4 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -561,8 +561,8 @@
         return 0;
     }
 
-    public static final Parcelable.Creator<PlaybackState> CREATOR
-            = new Parcelable.Creator<PlaybackState>() {
+    public static final Parcelable.Creator<PlaybackState> CREATOR =
+            new Parcelable.Creator<PlaybackState>() {
         @Override
         public PlaybackState createFromParcel(Parcel in) {
             return new PlaybackState(in);
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 41ed9e1..ad7ee7a 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -33,6 +33,9 @@
 #include <jni.h>
 #include <JNIHelp.h>
 
+#include <stdint.h>
+#include <inttypes.h>
+
 #define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
 
 #define ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID       "mNativeContext"
@@ -300,6 +303,14 @@
 
     // failed to find size, default to whole buffer
     if (size == 0) {
+        /*
+         * This is a problem because not including the JPEG header
+         * means that in certain rare situations a regular JPEG blob
+         * will be misidentified as having a header, in which case
+         * we will get a garbage size value.
+         */
+        ALOGW("%s: No JPEG header detected, defaulting to size=width=%d",
+                __FUNCTION__, width);
         size = width;
     }
 
@@ -848,6 +859,14 @@
 
     // Create byteBuffer from native buffer
     Image_getLockedBufferInfo(env, buffer, idx, &base, &size);
+
+    if (size > static_cast<uint32_t>(INT32_MAX)) {
+        // Byte buffer have 'int capacity', so check the range
+        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+                "Size too large for bytebuffer capacity " PRIu32, size);
+        return NULL;
+    }
+
     byteBuffer = env->NewDirectByteBuffer(base, size);
     // TODO: throw dvm exOutOfMemoryError?
     if ((byteBuffer == NULL) && (env->ExceptionCheck() == false)) {
diff --git a/packages/DocumentsUI/res/values-km-rKH/strings.xml b/packages/DocumentsUI/res/values-km-rKH/strings.xml
index e8944ec..8c9030d 100644
--- a/packages/DocumentsUI/res/values-km-rKH/strings.xml
+++ b/packages/DocumentsUI/res/values-km-rKH/strings.xml
@@ -20,14 +20,14 @@
     <string name="title_open" msgid="4353228937663917801">"បើក​ពី"</string>
     <string name="title_save" msgid="2433679664882857999">"រក្សា​ទុក​ទៅ"</string>
     <string name="menu_create_dir" msgid="5947289605844398389">"បង្កើត​ថត"</string>
-    <string name="menu_grid" msgid="6878021334497835259">"ទិដ្ឋភាព​ក្រឡា"</string>
+    <string name="menu_grid" msgid="6878021334497835259">"ទិដ្ឋភាព​ក្រឡា​"</string>
     <string name="menu_list" msgid="7279285939892417279">"ទិដ្ឋភាព​បញ្ជី"</string>
     <string name="menu_sort" msgid="7677740407158414452">"តម្រៀប​តាម"</string>
     <string name="menu_search" msgid="3816712084502856974">"ស្វែងរក"</string>
     <string name="menu_settings" msgid="6008033148948428823">"ការ​កំណត់"</string>
     <string name="menu_open" msgid="432922957274920903">"បើក"</string>
     <string name="menu_save" msgid="2394743337684426338">"រក្សាទុក"</string>
-    <string name="menu_share" msgid="3075149983979628146">"ចែករំលែក"</string>
+    <string name="menu_share" msgid="3075149983979628146">"ចែករំលែក​"</string>
     <string name="menu_delete" msgid="8138799623850614177">"លុប"</string>
     <string name="menu_select" msgid="8711270657353563424">"ជ្រើស \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"បាន​ជ្រើស <xliff:g id="COUNT">%1$d</xliff:g>"</string>
@@ -48,7 +48,7 @@
     <string name="pref_advanced_devices" msgid="903257239609301276">"បង្ហាញ​ឧបករណ៍​កម្រិត​ខ្ពស់"</string>
     <string name="pref_file_size" msgid="2826879315743961459">"បង្ហាញ​ទំហំ​ឯកសារ"</string>
     <string name="pref_device_size" msgid="3542106883278997222">"បង្ហាញ​ទំហំ​ឧបករណ៍"</string>
-    <string name="empty" msgid="7858882803708117596">"គ្មានធាតុ"</string>
+    <string name="empty" msgid="7858882803708117596">"គ្មានធាតុ​"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"មិន​អាច​បើក​ឯកសារ"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"មិន​អាច​លុប​ឯកសារ​មួយ​ចំនួន"</string>
     <string name="share_via" msgid="8966594246261344259">"ចែករំលែក​តាម"</string>
diff --git a/packages/Keyguard/res/values-da/strings.xml b/packages/Keyguard/res/values-da/strings.xml
index 85ebf4b..1acfa6b 100644
--- a/packages/Keyguard/res/values-da/strings.xml
+++ b/packages/Keyguard/res/values-da/strings.xml
@@ -85,7 +85,7 @@
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
     <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"Annuller"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"Slet"</string>
-    <string name="keyboardview_keycode_done" msgid="1992571118466679775">"Udført"</string>
+    <string name="keyboardview_keycode_done" msgid="1992571118466679775">"Udfør"</string>
     <string name="keyboardview_keycode_mode_change" msgid="4547387741906537519">"Ændring af tilstand"</string>
     <string name="keyboardview_keycode_shift" msgid="2270748814315147690">"Shift"</string>
     <string name="keyboardview_keycode_enter" msgid="2985864015076059467">"Angiv"</string>
diff --git a/packages/Keyguard/res/values-km-rKH/strings.xml b/packages/Keyguard/res/values-km-rKH/strings.xml
index ecdad8c..c26b1b4 100644
--- a/packages/Keyguard/res/values-km-rKH/strings.xml
+++ b/packages/Keyguard/res/values-km-rKH/strings.xml
@@ -83,7 +83,7 @@
     <string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
     <string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
     <string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
-    <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"បោះ​បង់"</string>
+    <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"បោះ​បង់​"</string>
     <string name="keyboardview_keycode_delete" msgid="3337914833206635744">"លុប"</string>
     <string name="keyboardview_keycode_done" msgid="1992571118466679775">"រួចរាល់"</string>
     <string name="keyboardview_keycode_mode_change" msgid="4547387741906537519">"ប្ដូរ​របៀប"</string>
@@ -120,7 +120,7 @@
     <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"ព្យាយាម​លំនាំ​ច្រើន​ពេក"</string>
     <string name="kg_login_instructions" msgid="1100551261265506448">"ដើម្បី​ដោះ​សោ ចូល​ក្នុង​គណនី Google ។"</string>
     <string name="kg_login_username_hint" msgid="5718534272070920364">"ឈ្មោះ​អ្នក​ប្រើ (អ៊ី​ម៉ែ​ល​)"</string>
-    <string name="kg_login_password_hint" msgid="9057289103827298549">"ពាក្យសម្ងាត់"</string>
+    <string name="kg_login_password_hint" msgid="9057289103827298549">"ពាក្យសម្ងាត់​"</string>
     <string name="kg_login_submit_button" msgid="5355904582674054702">"ចូល"</string>
     <string name="kg_login_invalid_input" msgid="5754664119319872197">"ឈ្មោះ​អ្នកប្រើ ឬ​ពាក្យ​សម្ងាត់​មិន​ត្រឹមត្រូវ។"</string>
     <string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"ភ្លេច​ឈ្មោះ​អ្នកប្រើ ឬ​ពាក្យ​សម្ងាត់​របស់​អ្នក?\nមើល "<b>"google.com/accounts/recovery"</b>" ។"</string>
diff --git a/packages/PrintSpooler/res/values-km-rKH/strings.xml b/packages/PrintSpooler/res/values-km-rKH/strings.xml
index 0146ab7..cdcb21f 100644
--- a/packages/PrintSpooler/res/values-km-rKH/strings.xml
+++ b/packages/PrintSpooler/res/values-km-rKH/strings.xml
@@ -60,7 +60,7 @@
   </plurals>
     <string name="cancel" msgid="4373674107267141885">"បោះបង់"</string>
     <string name="restart" msgid="2472034227037808749">"ចាប់ផ្ដើម​ឡើងវិញ"</string>
-    <string name="no_connection_to_printer" msgid="2159246915977282728">"គ្មាន​​​ការ​ភ្ជាប់​ទៅ​ម៉ាស៊ីន​បោះពុម្ព"</string>
+    <string name="no_connection_to_printer" msgid="2159246915977282728">"គ្មាន​​​ការ​ភ្ជាប់​ទៅ​ម៉ាស៊ីន​បោះពុម្ព​"</string>
     <string name="reason_unknown" msgid="5507940196503246139">"មិន​ស្គាល់"</string>
     <string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – មិន​អាច​ប្រើ​បាន"</string>
   <string-array name="color_mode_labels">
diff --git a/packages/SystemUI/res/layout/recents.xml b/packages/SystemUI/res/layout/recents.xml
new file mode 100644
index 0000000..47740ee
--- /dev/null
+++ b/packages/SystemUI/res/layout/recents.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent" 
+    android:layout_height="match_parent">
+    <!-- Status Bar Scrim View -->
+    <ImageView
+        android:id="@+id/status_bar_scrim"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal|top"
+        android:scaleType="fitXY"
+        android:src="@drawable/recents_status_gradient" />
+
+    <!-- Recents View -->
+    <com.android.systemui.recents.views.RecentsView
+        android:id="@+id/recents_view"
+        android:layout_width="match_parent" 
+        android:layout_height="match_parent"
+        android:focusable="true" />
+
+    <!-- Empty View -->
+    <ViewStub android:id="@+id/empty_view_stub"
+           android:layout="@layout/recents_empty"
+           android:layout_width="match_parent"
+           android:layout_height="match_parent" />
+
+    <!-- Fullscreen Transition View -->
+    <ViewStub android:id="@+id/fullscreen_overlay_stub"
+           android:layout="@layout/recents_fullscreen_overlay"
+           android:layout_width="match_parent"
+           android:layout_height="match_parent" />
+
+    <!-- Nav Bar Scrim View -->
+    <ImageView
+        android:id="@+id/nav_bar_scrim"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal|bottom"
+        android:scaleType="fitXY"
+        android:src="@drawable/recents_lower_gradient" />
+</FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_empty.xml b/packages/SystemUI/res/layout/recents_empty.xml
index c0ddde1..21d1711 100644
--- a/packages/SystemUI/res/layout/recents_empty.xml
+++ b/packages/SystemUI/res/layout/recents_empty.xml
@@ -16,11 +16,13 @@
 
 <TextView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:layout_gravity="center"
     android:gravity="center"
     android:textSize="20sp"
     android:textColor="#ffffffff"
     android:text="@string/recents_empty_message"
     android:fontFamily="sans-serif-light"
+    android:background="#80000000"
     android:visibility="gone" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_status_bar_scrim.xml b/packages/SystemUI/res/layout/recents_fullscreen_overlay.xml
similarity index 66%
rename from packages/SystemUI/res/layout/recents_status_bar_scrim.xml
rename to packages/SystemUI/res/layout/recents_fullscreen_overlay.xml
index 24928d0..1d021f9 100644
--- a/packages/SystemUI/res/layout/recents_status_bar_scrim.xml
+++ b/packages/SystemUI/res/layout/recents_fullscreen_overlay.xml
@@ -14,10 +14,14 @@
      limitations under the License.
 -->
 
-<ImageView
+<com.android.systemui.recents.views.FullscreenTransitionOverlayView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layout_gravity="center_horizontal|top"
-    android:scaleType="fitXY"
-    android:src="@drawable/recents_status_gradient" />
\ No newline at end of file
+    android:layout_height="match_parent"
+    android:visibility="gone">
+    <ImageView
+        android:id="@+id/image"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:scaleType="fitXY" />
+</com.android.systemui.recents.views.FullscreenTransitionOverlayView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_nav_bar_scrim.xml b/packages/SystemUI/res/layout/recents_nav_bar_scrim.xml
deleted file mode 100644
index 4245d49..0000000
--- a/packages/SystemUI/res/layout/recents_nav_bar_scrim.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<ImageView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:layout_gravity="center_horizontal|bottom"
-    android:scaleType="fitXY"
-    android:src="@drawable/recents_lower_gradient" />
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index ddea0bf..2abbad5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -33,6 +33,8 @@
             public static final boolean EnableTaskFiltering = true;
             // Enables clipping of tasks against each other
             public static final boolean EnableTaskStackClipping = true;
+            // Enables tapping on the TaskBar to launch the task
+            public static final boolean EnableTaskBarTouchEvents = true;
             // Enables the use of theme colors as the task bar background
             public static final boolean EnableTaskBarThemeColors = true;
             // Enables app-info pane on long-pressing the icon
diff --git a/packages/SystemUI/src/com/android/systemui/recents/DozeTrigger.java b/packages/SystemUI/src/com/android/systemui/recents/DozeTrigger.java
index 247aa6f..f0b2cb6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/DozeTrigger.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/DozeTrigger.java
@@ -49,12 +49,25 @@
 
     /** Starts dozing. This also resets the trigger flag. */
     public void startDozing() {
-        poke();
+        forcePoke();
         mHasTriggered = false;
     }
 
-    /** Poke this dozer to wake it up for a little bit. */
+    /** Stops dozing. */
+    public void stopDozing() {
+        mHandler.removeCallbacks(mDozeRunnable);
+        mIsDozing = false;
+    }
+
+    /** Poke this dozer to wake it up for a little bit, if it is dozing. */
     public void poke() {
+        if (mIsDozing) {
+            forcePoke();
+        }
+    }
+
+    /** Poke this dozer to wake it up for a little bit. */
+    void forcePoke() {
         mHandler.removeCallbacks(mDozeRunnable);
         mHandler.postDelayed(mDozeRunnable, mDozeDurationSeconds * 1000);
         mIsDozing = true;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 2d90e1a..52a17df 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -17,7 +17,7 @@
 package com.android.systemui.recents;
 
 import android.app.Activity;
-import android.appwidget.AppWidgetHost;
+import android.app.ActivityOptions;
 import android.appwidget.AppWidgetHostView;
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
@@ -26,75 +26,85 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.os.Bundle;
+import android.os.UserHandle;
 import android.util.Pair;
-import android.view.Gravity;
 import android.view.KeyEvent;
-import android.view.LayoutInflater;
 import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
+import android.view.ViewStub;
 import com.android.systemui.R;
 import com.android.systemui.recents.model.SpaceNode;
 import com.android.systemui.recents.model.TaskStack;
-import com.android.systemui.recents.views.FullScreenTransitionView;
+import com.android.systemui.recents.views.FullscreenTransitionOverlayView;
 import com.android.systemui.recents.views.RecentsView;
+import com.android.systemui.recents.views.SystemBarScrimViews;
 import com.android.systemui.recents.views.ViewAnimation;
 
 import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.util.ArrayList;
 
-/** Our special app widget host */
-class RecentsAppWidgetHost extends AppWidgetHost {
-    /* Callbacks to notify when an app package changes */
-    interface RecentsAppWidgetHostCallbacks {
-        public void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidgetInfo);
-    }
-
-    RecentsAppWidgetHostCallbacks mCb;
-
-    public RecentsAppWidgetHost(Context context, int hostId, RecentsAppWidgetHostCallbacks cb) {
-        super(context, hostId);
-        mCb = cb;
-    }
-
-    @Override
-    protected void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidget) {
-        mCb.onProviderChanged(appWidgetId, appWidget);
-    }
-}
-
 /* Activity */
 public class RecentsActivity extends Activity implements RecentsView.RecentsViewCallbacks,
         RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks,
-        FullScreenTransitionView.FullScreenTransitionViewCallbacks {
+        FullscreenTransitionOverlayView.FullScreenTransitionViewCallbacks {
 
-    FrameLayout mContainerView;
     RecentsView mRecentsView;
+    SystemBarScrimViews mScrimViews;
+    ViewStub mEmptyViewStub;
     View mEmptyView;
-    View mStatusBarScrimView;
-    View mNavBarScrimView;
-    FullScreenTransitionView mFullScreenshotView;
+    ViewStub mFullscreenOverlayStub;
+    FullscreenTransitionOverlayView mFullScreenOverlayView;
 
     RecentsConfiguration mConfig;
 
-    AppWidgetHost mAppWidgetHost;
+    RecentsAppWidgetHost mAppWidgetHost;
     AppWidgetProviderInfo mSearchAppWidgetInfo;
     AppWidgetHostView mSearchAppWidgetHostView;
 
     boolean mVisible;
     boolean mTaskLaunched;
 
-    private static Method sPropertyMethod;
-    static {
-        try {
-            Class<?> c = Class.forName("android.view.GLES20Canvas");
-            sPropertyMethod = c.getDeclaredMethod("setProperty", String.class, String.class);
-            if (!sPropertyMethod.isAccessible()) sPropertyMethod.setAccessible(true);
-        } catch (ClassNotFoundException e) {
-            e.printStackTrace();
-        } catch (NoSuchMethodException e) {
-            e.printStackTrace();
+    // Runnables to finish the Recents activity
+    FinishRecentsRunnable mFinishRunnable = new FinishRecentsRunnable(true);
+    FinishRecentsRunnable mFinishWithoutAnimationRunnable = new FinishRecentsRunnable(false);
+    FinishRecentsRunnable mFinishLaunchHomeRunnable;
+
+    /**
+     * A Runnable to finish Recents either with/without a transition, and either by calling finish()
+     * or just launching the specified intent.
+     */
+    class FinishRecentsRunnable implements Runnable {
+        boolean mUseCustomFinishTransition;
+        Intent mLaunchIntent;
+        ActivityOptions mLaunchOpts;
+
+        public FinishRecentsRunnable(boolean withTransition) {
+            mUseCustomFinishTransition = withTransition;
+        }
+
+        public FinishRecentsRunnable(Intent launchIntent, ActivityOptions opts) {
+            mLaunchIntent = launchIntent;
+            mLaunchOpts = opts;
+        }
+
+        @Override
+        public void run() {
+            // Mark Recents as no longer visible
+            AlternateRecentsComponent.notifyVisibilityChanged(false);
+            // Finish Recents
+            if (mLaunchIntent != null) {
+                if (mLaunchOpts != null) {
+                    startActivityAsUser(mLaunchIntent, new UserHandle(UserHandle.USER_CURRENT));
+                } else {
+                    startActivityAsUser(mLaunchIntent, mLaunchOpts.toBundle(),
+                            new UserHandle(UserHandle.USER_CURRENT));
+                }
+            } else {
+                finish();
+                if (mUseCustomFinishTransition) {
+                    overridePendingTransition(R.anim.recents_to_launcher_enter,
+                            R.anim.recents_to_launcher_exit);
+                }
+            }
         }
     }
 
@@ -113,11 +123,11 @@
                     dismissRecentsIfVisible();
                 } else {
                     // If we are mid-animation into Recents, then reverse it and finish
-                    if (mFullScreenshotView == null ||
-                            !mFullScreenshotView.cancelAnimateOnEnterRecents(mFinishRunnable)) {
-                        // Otherwise, just finish the activity without launching any other activities
+                    if (mFullScreenOverlayView == null ||
+                            !mFullScreenOverlayView.cancelAnimateOnEnterRecents(mFinishRunnable)) {
+                        // Otherwise, either finish Recents, or launch Home directly
                         ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(context,
-                                null, mFinishRunnable, null);
+                                null, mFinishLaunchHomeRunnable, null);
                         mRecentsView.startExitToHomeAnimation(
                                 new ViewAnimation.TaskViewExitContext(exitTrigger));
                     }
@@ -130,7 +140,7 @@
                 }
             } else if (action.equals(RecentsService.ACTION_START_ENTER_ANIMATION)) {
                 // Try and start the enter animation (or restart it on configuration changed)
-                mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(mFullScreenshotView));
+                mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(mFullScreenOverlayView));
                 // Call our callback
                 onEnterAnimationTriggered();
             }
@@ -141,23 +151,7 @@
     BroadcastReceiver mScreenOffReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            // Mark recents as no longer visible
-            AlternateRecentsComponent.notifyVisibilityChanged(false);
-            // Finish without an animations
-            finish();
-        }
-    };
-
-    // A runnable to finish the Recents activity
-    Runnable mFinishRunnable = new Runnable() {
-        @Override
-        public void run() {
-            // Mark recents as no longer visible
-            AlternateRecentsComponent.notifyVisibilityChanged(false);
-            // Finish with an animations
-            finish();
-            overridePendingTransition(R.anim.recents_to_launcher_enter,
-                    R.anim.recents_to_launcher_exit);
+            mFinishWithoutAnimationRunnable.run();
         }
     };
 
@@ -182,15 +176,14 @@
         mConfig.launchedWithNoRecentTasks = !root.hasTasks();
 
         // Show the scrim if we animate into Recents without window transitions
-        mNavBarScrimView.setVisibility(mConfig.hasNavBarScrim() &&
-                !mConfig.shouldAnimateNavBarScrim() ? View.VISIBLE : View.INVISIBLE);
-        mStatusBarScrimView.setVisibility(mConfig.hasStatusBarScrim() &&
-                !mConfig.shouldAnimateStatusBarScrim() ? View.VISIBLE : View.INVISIBLE);
+        mScrimViews.prepareEnterRecentsAnimation();
 
         // Add the default no-recents layout
+        if (mEmptyView == null) {
+            mEmptyView = mEmptyViewStub.inflate();
+        }
         if (mConfig.launchedWithNoRecentTasks) {
             mEmptyView.setVisibility(View.VISIBLE);
-            mEmptyView.setBackgroundColor(0x80000000);
         } else {
             mEmptyView.setVisibility(View.GONE);
         }
@@ -273,24 +266,21 @@
     boolean dismissRecentsIfVisible() {
         if (mVisible) {
             // If we are mid-animation into Recents, then reverse it and finish
-            if (mFullScreenshotView == null ||
-                    !mFullScreenshotView.cancelAnimateOnEnterRecents(mFinishRunnable)) {
+            if (mFullScreenOverlayView == null ||
+                    !mFullScreenOverlayView.cancelAnimateOnEnterRecents(mFinishRunnable)) {
                 // If we have a focused task, then launch that task
                 if (!mRecentsView.launchFocusedTask()) {
                     if (mConfig.launchedFromHome) {
                         // Just start the animation out of recents
                         ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(this,
-                                null, mFinishRunnable, null);
+                                null, mFinishLaunchHomeRunnable, null);
                         mRecentsView.startExitToHomeAnimation(
                                 new ViewAnimation.TaskViewExitContext(exitTrigger));
                     } else {
                         // Otherwise, try and launch the first task
                         if (!mRecentsView.launchFirstTask()) {
                             // If there are no tasks, then just finish recents
-                            ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(this,
-                                    null, mFinishRunnable, null);
-                            mRecentsView.startExitToHomeAnimation(
-                                    new ViewAnimation.TaskViewExitContext(exitTrigger));
+                            mFinishLaunchHomeRunnable.run();
                         }
                     }
                 }
@@ -316,52 +306,37 @@
         RecentsTaskLoader.initialize(this);
         mConfig = RecentsConfiguration.reinitialize(this);
 
-        // Initialize the widget host (the host id is static and does not change)
-        mAppWidgetHost = new RecentsAppWidgetHost(this, Constants.Values.App.AppWidgetHostId, this);
+        // Create the home intent runnable
+        Intent homeIntent = new Intent(Intent.ACTION_MAIN, null);
+        homeIntent.addCategory(Intent.CATEGORY_HOME);
+        homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
+                            Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+        mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent,
+                ActivityOptions.makeCustomAnimation(this, R.anim.recents_to_launcher_enter,
+                        R.anim.recents_to_launcher_exit));
 
-        // Create the view hierarchy
-        mRecentsView = new RecentsView(this);
+        // Initialize the widget host (the host id is static and does not change)
+        mAppWidgetHost = new RecentsAppWidgetHost(this, Constants.Values.App.AppWidgetHostId);
+
+        // Set the Recents layout
+        setContentView(R.layout.recents);
+        mRecentsView = (RecentsView) findViewById(R.id.recents_view);
         mRecentsView.setCallbacks(this);
-        mRecentsView.setLayoutParams(new FrameLayout.LayoutParams(
-                FrameLayout.LayoutParams.MATCH_PARENT,
-                FrameLayout.LayoutParams.MATCH_PARENT));
         mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
                 View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
                 View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
-
-        // Create the empty view
-        LayoutInflater inflater = LayoutInflater.from(this);
-        mEmptyView = inflater.inflate(R.layout.recents_empty, mContainerView, false);
-        mStatusBarScrimView = inflater.inflate(R.layout.recents_status_bar_scrim, mContainerView, false);
-        mStatusBarScrimView.setLayoutParams(new FrameLayout.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT,
-                ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.TOP));
-        mNavBarScrimView = inflater.inflate(R.layout.recents_nav_bar_scrim, mContainerView, false);
-        mNavBarScrimView.setLayoutParams(new FrameLayout.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT,
-                ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.BOTTOM));
-        if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
-            mFullScreenshotView = new FullScreenTransitionView(this, this);
-            mFullScreenshotView.setLayoutParams(new FrameLayout.LayoutParams(
-                    ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
-        }
-
-        mContainerView = new FrameLayout(this);
-        mContainerView.addView(mStatusBarScrimView);
-        mContainerView.addView(mRecentsView);
-        mContainerView.addView(mEmptyView);
-        if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
-            mContainerView.addView(mFullScreenshotView);
-        }
-        mContainerView.addView(mNavBarScrimView);
-        setContentView(mContainerView);
+        mEmptyViewStub = (ViewStub) findViewById(R.id.empty_view_stub);
+        mFullscreenOverlayStub = (ViewStub) findViewById(R.id.fullscreen_overlay_stub);
+        mScrimViews = new SystemBarScrimViews(this, mConfig);
 
         // Update the recent tasks
         updateRecentsTasks(getIntent());
 
         // Prepare the screenshot transition if necessary
         if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
-            mFullScreenshotView.prepareAnimateOnEnterRecents(AlternateRecentsComponent.getLastScreenshot());
+            mFullScreenOverlayView = (FullscreenTransitionOverlayView) mFullscreenOverlayStub.inflate();
+            mFullScreenOverlayView.setCallbacks(this);
+            mFullScreenOverlayView.prepareAnimateOnEnterRecents(AlternateRecentsComponent.getLastScreenshot());
         }
 
         // Bind the search app widget when we first start up
@@ -374,10 +349,10 @@
             onConfigurationChange();
         }
 
-        // XXX: Update the shadows
+        // Private API calls to make the shadows look better
         try {
-            sPropertyMethod.invoke(null, "ambientShadowStrength", String.valueOf(35f));
-            sPropertyMethod.invoke(null, "ambientRatio", String.valueOf(0.5f));
+            Utilities.setShadowProperty("ambientShadowStrength", String.valueOf(35f));
+            Utilities.setShadowProperty("ambientRatio", String.valueOf(0.5f));
         } catch (IllegalAccessException e) {
             e.printStackTrace();
         } catch (InvocationTargetException e) {
@@ -387,7 +362,7 @@
 
     void onConfigurationChange() {
         // Try and start the enter animation (or restart it on configuration changed)
-        mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(mFullScreenshotView));
+        mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(mFullScreenOverlayView));
         // Call our callback
         onEnterAnimationTriggered();
     }
@@ -415,7 +390,7 @@
 
         // Prepare the screenshot transition if necessary
         if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
-            mFullScreenshotView.prepareAnimateOnEnterRecents(AlternateRecentsComponent.getLastScreenshot());
+            mFullScreenOverlayView.prepareAnimateOnEnterRecents(AlternateRecentsComponent.getLastScreenshot());
         }
 
         // Don't attempt to rebind the search bar widget, but just add the search bar layout
@@ -430,11 +405,6 @@
         }
         super.onStart();
 
-        // Start listening for widget package changes if there is one bound
-        if (mConfig.searchBarAppWidgetId >= 0) {
-            mAppWidgetHost.startListening();
-        }
-
         mVisible = true;
     }
 
@@ -470,6 +440,11 @@
 
         // Register any broadcast receivers for the task loader
         RecentsTaskLoader.getInstance().registerReceivers(this, mRecentsView);
+
+        // Start listening for widget package changes if there is one bound
+        if (mConfig.searchBarAppWidgetId >= 0) {
+            mAppWidgetHost.startListening(this);
+        }
     }
 
     @Override
@@ -485,6 +460,11 @@
         unregisterReceiver(mServiceBroadcastReceiver);
         unregisterReceiver(mScreenOffReceiver);
         RecentsTaskLoader.getInstance().unregisterReceivers();
+
+        // Stop listening for widget package changes if there was one bound
+        if (mConfig.searchBarAppWidgetId >= 0) {
+            mAppWidgetHost.stopListening();
+        }
     }
 
     @Override
@@ -504,11 +484,6 @@
         }
         super.onStop();
 
-        // Stop listening for widget package changes if there was one bound
-        if (mConfig.searchBarAppWidgetId >= 0) {
-            mAppWidgetHost.stopListening();
-        }
-
         mVisible = false;
         mTaskLaunched = false;
     }
@@ -550,24 +525,21 @@
     @Override
     public void onBackPressed() {
         // If we are mid-animation into Recents, then reverse it and finish
-        if (mFullScreenshotView == null ||
-                !mFullScreenshotView.cancelAnimateOnEnterRecents(mFinishRunnable)) {
+        if (mFullScreenOverlayView == null ||
+                !mFullScreenOverlayView.cancelAnimateOnEnterRecents(mFinishRunnable)) {
             // If we are currently filtering in any stacks, unfilter them first
             if (!mRecentsView.unfilterFilteredStacks()) {
                 if (mConfig.launchedFromHome) {
                     // Just start the animation out of recents
                     ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(this,
-                            null, mFinishRunnable, null);
+                            null, mFinishLaunchHomeRunnable, null);
                     mRecentsView.startExitToHomeAnimation(
                             new ViewAnimation.TaskViewExitContext(exitTrigger));
                 } else {
                     // Otherwise, try and launch the first task
                     if (!mRecentsView.launchFirstTask()) {
                         // If there are no tasks, then just finish recents
-                        ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(this,
-                                null, mFinishRunnable, null);
-                        mRecentsView.startExitToHomeAnimation(
-                                new ViewAnimation.TaskViewExitContext(exitTrigger));
+                        mFinishLaunchHomeRunnable.run();
                     }
                 }
             }
@@ -575,58 +547,18 @@
     }
 
     public void onEnterAnimationTriggered() {
-        // Fade in the scrims
-        if (mConfig.hasStatusBarScrim() && mConfig.shouldAnimateStatusBarScrim()) {
-            mStatusBarScrimView.setTranslationY(-mStatusBarScrimView.getMeasuredHeight());
-            mStatusBarScrimView.animate()
-                    .translationY(0)
-                    .setStartDelay(mConfig.taskBarEnterAnimDelay)
-                    .setDuration(mConfig.navBarScrimEnterDuration)
-                    .setInterpolator(mConfig.quintOutInterpolator)
-                    .withStartAction(new Runnable() {
-                        @Override
-                        public void run() {
-                            mStatusBarScrimView.setVisibility(View.VISIBLE);
-                        }
-                    })
-                    .start();
-        }
-        if (mConfig.hasNavBarScrim() && mConfig.shouldAnimateNavBarScrim()) {
-            mNavBarScrimView.setTranslationY(mNavBarScrimView.getMeasuredHeight());
-            mNavBarScrimView.animate()
-                    .translationY(0)
-                    .setStartDelay(mConfig.taskBarEnterAnimDelay)
-                    .setDuration(mConfig.navBarScrimEnterDuration)
-                    .setInterpolator(mConfig.quintOutInterpolator)
-                    .withStartAction(new Runnable() {
-                        @Override
-                        public void run() {
-                            mNavBarScrimView.setVisibility(View.VISIBLE);
-                        }
-                    })
-                    .start();
-        }
+        // Animate the scrims in
+        mScrimViews.startEnterRecentsAnimation();
     }
 
-    @Override
-    public void onExitAnimationTriggered() {
-        // Fade out the scrim
-        if (mConfig.hasNavBarScrim() && mConfig.shouldAnimateNavBarScrim()) {
-            mNavBarScrimView.animate()
-                    .translationY(mNavBarScrimView.getMeasuredHeight())
-                    .setStartDelay(0)
-                    .setDuration(mConfig.taskBarExitAnimDuration)
-                    .setInterpolator(mConfig.fastOutSlowInInterpolator)
-                    .start();
-        }
-    }
+    /**** FullscreenTransitionOverlayView.FullScreenTransitionViewCallbacks Implementation ****/
 
     @Override
     public void onEnterAnimationComplete(boolean canceled) {
         if (!canceled) {
             // Reset the full screenshot transition view
             if (Constants.DebugFlags.App.EnableScreenshotAppTransition) {
-                mFullScreenshotView.reset();
+                mFullScreenOverlayView.reset();
             }
 
             // XXX: We should clean up the screenshot in this case as well, but it needs to happen
@@ -636,6 +568,14 @@
         AlternateRecentsComponent.consumeLastScreenshot();
     }
 
+    /**** RecentsView.RecentsViewCallbacks Implementation ****/
+
+    @Override
+    public void onExitToHomeAnimationTriggered() {
+        // Animate the scrims out
+        mScrimViews.startExitRecentsAnimation();
+    }
+
     @Override
     public void onTaskLaunching() {
         mTaskLaunched = true;
@@ -644,16 +584,12 @@
         AlternateRecentsComponent.notifyVisibilityChanged(false);
     }
 
+    /**** RecentsAppWidgetHost.RecentsAppWidgetHostCallbacks Implementation ****/
+
     @Override
-    public void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidgetInfo) {
-        SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
-        if (appWidgetId > -1 && appWidgetId == mConfig.searchBarAppWidgetId) {
-            // The search provider may have changed, so just delete the old widget and bind it again
-            ssp.unbindSearchAppWidget(mAppWidgetHost, appWidgetId);
-            mConfig.updateSearchBarAppWidgetId(this, -1);
-            // Load the widget again
-            bindSearchBarAppWidget();
-            addSearchBarAppWidgetView();
-        }
+    public void refreshSearchWidget() {
+        // Load the Search widget again
+        bindSearchBarAppWidget();
+        addSearchBarAppWidgetView();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
new file mode 100644
index 0000000..d55eba7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+package com.android.systemui.recents;
+
+import android.appwidget.AppWidgetHost;
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.Context;
+
+/** Our special app widget host for the Search widget */
+public class RecentsAppWidgetHost extends AppWidgetHost {
+
+    /* Callbacks to notify when an app package changes */
+    interface RecentsAppWidgetHostCallbacks {
+        public void refreshSearchWidget();
+    }
+
+    Context mContext;
+    RecentsAppWidgetHostCallbacks mCb;
+    RecentsConfiguration mConfig;
+
+    public RecentsAppWidgetHost(Context context, int hostId) {
+        super(context, hostId);
+        mContext = context;
+        mConfig = RecentsConfiguration.getInstance();
+    }
+
+    public void startListening(RecentsAppWidgetHostCallbacks cb) {
+        mCb = cb;
+        super.startListening();
+    }
+
+    @Override
+    public void stopListening() {
+        super.stopListening();
+        // Ensure that we release any references to the callbacks
+        mCb = null;
+        mContext = null;
+    }
+
+    @Override
+    protected void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidgetInfo) {
+        if (mCb == null) return;
+
+        SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
+        if (appWidgetId > -1 && appWidgetId == mConfig.searchBarAppWidgetId) {
+            // The search provider may have changed, so just delete the old widget and bind it again
+            ssp.unbindSearchAppWidget(this, appWidgetId);
+            // Update the search widget
+            mConfig.updateSearchBarAppWidgetId(mContext, -1);
+            mCb.refreshSearchWidget();
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java
index 8bcc7f5..04d1f1f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java
@@ -37,29 +37,29 @@
 
     PackageCallbacks mCb;
     List<ActivityManager.RecentTaskInfo> mTasks;
-    SystemServicesProxy mSsp;
-    boolean mRegistered;
-
-    public RecentsPackageMonitor(Context context) {
-        mSsp = new SystemServicesProxy(context);
-    }
+    SystemServicesProxy mSystemServicesProxy;
 
     /** Registers the broadcast receivers with the specified callbacks. */
     public void register(Context context, PackageCallbacks cb) {
+        mSystemServicesProxy = new SystemServicesProxy(context);
         mCb = cb;
-        if (!mRegistered) {
+        try {
             register(context, Looper.getMainLooper(), false);
-            mRegistered = true;
+        } catch (IllegalStateException e) {
+            e.printStackTrace();
         }
     }
 
     /** Unregisters the broadcast receivers. */
     @Override
     public void unregister() {
-        if (mRegistered) {
+        try {
             super.unregister();
-            mRegistered = false;
+        } catch (IllegalStateException e) {
+            e.printStackTrace();
         }
+        mSystemServicesProxy = null;
+        mCb = null;
         mTasks.clear();
     }
 
@@ -106,7 +106,7 @@
                     // If we know that the component still exists in the package, then skip
                     continue;
                 }
-                if (mSsp.getActivityInfo(cn) != null) {
+                if (mSystemServicesProxy.getActivityInfo(cn) != null) {
                     componentsKnownToExist.add(cn);
                 } else {
                     componentsToRemove.add(cn);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index 7762111..07a6a56 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -357,7 +357,7 @@
 
         // Initialize the proxy, cache and loaders
         mSystemServicesProxy = new SystemServicesProxy(context);
-        mPackageMonitor = new RecentsPackageMonitor(context);
+        mPackageMonitor = new RecentsPackageMonitor();
         mLoadQueue = new TaskResourceLoadQueue();
         mApplicationIconCache = new DrawableLruCache(iconCacheSize);
         mThumbnailCache = new BitmapLruCache(thumbnailCacheSize);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
index 46e6ee9..25875bc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Utilities.java
@@ -20,8 +20,26 @@
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
 /* Common code */
 public class Utilities {
+
+    // Reflection methods for altering shadows
+    private static Method sPropertyMethod;
+    static {
+        try {
+            Class<?> c = Class.forName("android.view.GLES20Canvas");
+            sPropertyMethod = c.getDeclaredMethod("setProperty", String.class, String.class);
+            if (!sPropertyMethod.isAccessible()) sPropertyMethod.setAccessible(true);
+        } catch (ClassNotFoundException e) {
+            e.printStackTrace();
+        } catch (NoSuchMethodException e) {
+            e.printStackTrace();
+        }
+    }
+
     /**
      * Calculates a consistent animation duration (ms) for all animations depending on the movement
      * of the object being animated.
@@ -66,4 +84,10 @@
         int greyscale = colorToGreyscale(color);
         return (greyscale < 128) ? lightRes : darkRes;
     }
+
+    /** Sets some private shadow properties. */
+    public static void setShadowProperty(String property, String value)
+            throws IllegalAccessException, InvocationTargetException {
+        sPropertyMethod.invoke(null, property, value);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FullScreenTransitionView.java b/packages/SystemUI/src/com/android/systemui/recents/views/FullscreenTransitionOverlayView.java
similarity index 89%
rename from packages/SystemUI/src/com/android/systemui/recents/views/FullScreenTransitionView.java
rename to packages/SystemUI/src/com/android/systemui/recents/views/FullscreenTransitionOverlayView.java
index cadfc56..2c632cf 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FullScreenTransitionView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/FullscreenTransitionOverlayView.java
@@ -25,10 +25,11 @@
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Rect;
+import android.util.AttributeSet;
 import android.view.View;
-import android.view.ViewGroup;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
+import com.android.systemui.R;
 import com.android.systemui.recents.Console;
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.RecentsConfiguration;
@@ -38,9 +39,9 @@
  * The full screen transition view that gets animated down from the full screen into a task
  * thumbnail view.
  */
-public class FullScreenTransitionView extends FrameLayout {
+public class FullscreenTransitionOverlayView extends FrameLayout {
 
-    /** The FullScreenTransitionView callbacks */
+    /** The FullscreenTransitionOverlayView callbacks */
     public interface FullScreenTransitionViewCallbacks {
         void onEnterAnimationComplete(boolean canceled);
     }
@@ -56,20 +57,37 @@
     boolean mIsAnimating;
     AnimatorSet mEnterAnimation;
 
-    public FullScreenTransitionView(Context context, FullScreenTransitionViewCallbacks cb) {
+    public FullscreenTransitionOverlayView(Context context) {
         super(context);
+    }
+
+    public FullscreenTransitionOverlayView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public FullscreenTransitionOverlayView(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public FullscreenTransitionOverlayView(Context context, AttributeSet attrs, int defStyleAttr,
+                                           int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
         mConfig = RecentsConfiguration.getInstance();
-        mCb = cb;
-        mScreenshotView = new ImageView(context);
-        mScreenshotView.setScaleType(ImageView.ScaleType.FIT_XY);
-        mScreenshotView.setLayoutParams(new FrameLayout.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
-        addView(mScreenshotView);
         setClipTop(getClipTop());
         setClipBottom(getClipBottom());
         setWillNotDraw(false);
     }
 
+    @Override
+    protected void onFinishInflate() {
+        mScreenshotView = (ImageView) findViewById(R.id.image);
+    }
+
+    /** Sets the callbacks */
+    public void setCallbacks(FullScreenTransitionViewCallbacks cb) {
+        mCb = cb;
+    }
+
     /** Sets the top clip */
     public void setClipTop(int clip) {
         mClipRect.top = clip;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 7248758..8afc5b9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -28,6 +28,7 @@
 import android.net.Uri;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.WindowInsets;
@@ -44,7 +45,6 @@
 import java.util.ArrayList;
 import java.util.Set;
 
-
 /**
  * This view is the the top level layout that contains TaskStacks (which are laid out according
  * to their SpaceNode bounds.
@@ -55,7 +55,7 @@
     /** The RecentsView callbacks */
     public interface RecentsViewCallbacks {
         public void onTaskLaunching();
-        public void onExitAnimationTriggered();
+        public void onExitToHomeAnimationTriggered();
     }
 
     RecentsConfiguration mConfig;
@@ -72,6 +72,18 @@
 
     public RecentsView(Context context) {
         super(context);
+    }
+
+    public RecentsView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public RecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public RecentsView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
         mConfig = RecentsConfiguration.getInstance();
         mInflater = LayoutInflater.from(context);
     }
@@ -194,7 +206,7 @@
         ctx.postAnimationTrigger.decrement();
 
         // Notify of the exit animation
-        mCb.onExitAnimationTriggered();
+        mCb.onExitToHomeAnimationTriggered();
     }
 
     /** Adds the search bar */
@@ -509,6 +521,34 @@
                 isDocument);
     }
 
+    @Override
+    public void onTaskStackFilterTriggered() {
+        // Hide the search bar
+        if (mSearchBar != null) {
+            mSearchBar.animate()
+                    .alpha(0f)
+                    .setStartDelay(0)
+                    .setInterpolator(mConfig.fastOutSlowInInterpolator)
+                    .setDuration(mConfig.filteringCurrentViewsAnimDuration)
+                    .withLayer()
+                    .start();
+        }
+    }
+
+    @Override
+    public void onTaskStackUnfilterTriggered() {
+        // Show the search bar
+        if (mSearchBar != null) {
+            mSearchBar.animate()
+                    .alpha(1f)
+                    .setStartDelay(0)
+                    .setInterpolator(mConfig.fastOutSlowInInterpolator)
+                    .setDuration(mConfig.filteringNewViewsAnimDuration)
+                    .withLayer()
+                    .start();
+        }
+    }
+
     /**** RecentsPackageMonitor.PackageCallbacks Implementation ****/
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
new file mode 100644
index 0000000..5b17b41
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
@@ -0,0 +1,109 @@
+/*
+ * 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.
+ */
+
+package com.android.systemui.recents.views;
+
+import android.app.Activity;
+import android.view.View;
+import com.android.systemui.R;
+import com.android.systemui.recents.RecentsConfiguration;
+
+/** Manages the scrims for the various system bars. */
+public class SystemBarScrimViews {
+
+    RecentsConfiguration mConfig;
+
+    View mStatusBarScrimView;
+    View mNavBarScrimView;
+
+    boolean mHasNavBarScrim;
+    boolean mShouldAnimateStatusBarScrim;
+    boolean mHasStatusBarScrim;
+    boolean mShouldAnimateNavBarScrim;
+
+    public SystemBarScrimViews(Activity activity, RecentsConfiguration config) {
+        mConfig = config;
+        mStatusBarScrimView = activity.findViewById(R.id.status_bar_scrim);
+        mNavBarScrimView = activity.findViewById(R.id.nav_bar_scrim);
+    }
+
+    /**
+     * Prepares the scrim views for animating when entering Recents. This will be called before
+     * the first draw.
+     */
+    public void prepareEnterRecentsAnimation() {
+        mHasNavBarScrim = mConfig.hasNavBarScrim();
+        mShouldAnimateNavBarScrim = mConfig.shouldAnimateNavBarScrim();
+        mHasStatusBarScrim = mConfig.hasStatusBarScrim();
+        mShouldAnimateStatusBarScrim = mConfig.shouldAnimateStatusBarScrim();
+
+        mNavBarScrimView.setVisibility(mHasNavBarScrim && !mShouldAnimateNavBarScrim ?
+                View.VISIBLE : View.INVISIBLE);
+        mStatusBarScrimView.setVisibility(mHasStatusBarScrim && !mShouldAnimateStatusBarScrim ?
+                View.VISIBLE : View.INVISIBLE);
+    }
+
+    /**
+     * Starts animating the scrim views when entering Recents.
+     */
+    public void startEnterRecentsAnimation() {
+        if (mHasStatusBarScrim && mShouldAnimateStatusBarScrim) {
+            mStatusBarScrimView.setTranslationY(-mStatusBarScrimView.getMeasuredHeight());
+            mStatusBarScrimView.animate()
+                    .translationY(0)
+                    .setStartDelay(mConfig.taskBarEnterAnimDelay)
+                    .setDuration(mConfig.navBarScrimEnterDuration)
+                    .setInterpolator(mConfig.quintOutInterpolator)
+                    .withStartAction(new Runnable() {
+                        @Override
+                        public void run() {
+                            mStatusBarScrimView.setVisibility(View.VISIBLE);
+                        }
+                    })
+                    .start();
+        }
+        if (mHasNavBarScrim && mShouldAnimateNavBarScrim) {
+            mNavBarScrimView.setTranslationY(mNavBarScrimView.getMeasuredHeight());
+            mNavBarScrimView.animate()
+                    .translationY(0)
+                    .setStartDelay(mConfig.taskBarEnterAnimDelay)
+                    .setDuration(mConfig.navBarScrimEnterDuration)
+                    .setInterpolator(mConfig.quintOutInterpolator)
+                    .withStartAction(new Runnable() {
+                        @Override
+                        public void run() {
+                            mNavBarScrimView.setVisibility(View.VISIBLE);
+                        }
+                    })
+                    .start();
+        }
+    }
+
+    /**
+     * Starts animating the scrim views when leaving Recents (either via launching a task, or
+     * going home).
+     */
+    public void startExitRecentsAnimation() {
+        if (mHasNavBarScrim && mShouldAnimateNavBarScrim) {
+            mNavBarScrimView.animate()
+                    .translationY(mNavBarScrimView.getMeasuredHeight())
+                    .setStartDelay(0)
+                    .setDuration(mConfig.taskBarExitAnimDuration)
+                    .setInterpolator(mConfig.fastOutSlowInInterpolator)
+                    .start();
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
index 1ef58ad..80f804d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
@@ -25,6 +25,7 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.RippleDrawable;
 import android.util.AttributeSet;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewPropertyAnimator;
 import android.widget.FrameLayout;
@@ -88,6 +89,15 @@
     }
 
     @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (Constants.DebugFlags.App.EnableTaskBarTouchEvents) {
+            return super.onTouchEvent(event);
+        }
+        // We ignore taps on the task bar except on the filter and dismiss buttons
+        return true;
+    }
+
+    @Override
     protected void onFinishInflate() {
         // Initialize the icon and description views
         mApplicationIcon = (ImageView) findViewById(R.id.application_icon);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 8f61e72..1cf28b9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -26,13 +26,9 @@
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.graphics.Region;
-import android.util.Pair;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
-import android.view.VelocityTracker;
 import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewParent;
 import android.widget.FrameLayout;
 import android.widget.OverScroller;
 import com.android.systemui.R;
@@ -62,6 +58,8 @@
         public void onTaskLaunched(TaskStackView stackView, TaskView tv, TaskStack stack, Task t);
         public void onTaskAppInfoLaunched(Task t);
         public void onTaskRemoved(Task t);
+        public void onTaskStackFilterTriggered();
+        public void onTaskStackUnfilterTriggered();
     }
 
     RecentsConfiguration mConfig;
@@ -71,7 +69,7 @@
     TaskStackViewCallbacks mCb;
     ViewPool<TaskView, Task> mViewPool;
     ArrayList<TaskViewTransform> mTaskTransforms = new ArrayList<TaskViewTransform>();
-    DozeTrigger mDozeTrigger;
+    DozeTrigger mUIDozeTrigger;
 
     // The various rects that define the stack view
     Rect mRect = new Rect();
@@ -119,7 +117,7 @@
         mTouchHandler = new TaskStackViewTouchHandler(context, this);
         mViewPool = new ViewPool<TaskView, Task>(context, this);
         mInflater = LayoutInflater.from(context);
-        mDozeTrigger = new DozeTrigger(mConfig.taskBarDismissDozeDelaySeconds, new Runnable() {
+        mUIDozeTrigger = new DozeTrigger(mConfig.taskBarDismissDozeDelaySeconds, new Runnable() {
             @Override
             public void run() {
                 // Show the task bar dismiss buttons
@@ -390,11 +388,13 @@
     /** Sets the current stack scroll */
     public void setStackScroll(int value) {
         mStackScroll = value;
+        mUIDozeTrigger.poke();
         requestSynchronizeStackViewsWithModel();
     }
     /** Sets the current stack scroll without synchronizing the stack view with the model */
     public void setStackScrollRaw(int value) {
         mStackScroll = value;
+        mUIDozeTrigger.poke();
     }
     /** Sets the current stack scroll to the initial state when you first enter recents */
     public void setStackScrollToInitialState() {
@@ -854,7 +854,7 @@
             mAwaitingFirstLayout = false;
 
             // Start dozing
-            mDozeTrigger.startDozing();
+            mUIDozeTrigger.startDozing();
 
             // Prepare the first view for its enter animation
             int offsetTopAlign = -mTaskRect.top;
@@ -931,11 +931,8 @@
 
     /** Pokes the dozer on user interaction. */
     void onUserInteraction() {
-        // If the dozer is not running, then either we have not yet laid out, or it has already
-        // fallen asleep, so just let it rest.
-        if (mDozeTrigger.isDozing()) {
-            mDozeTrigger.poke();
-        }
+        // Poke the doze trigger if it is dozing
+        mUIDozeTrigger.poke();
     }
 
     /**** TaskStackCallbacks Implementation ****/
@@ -1136,6 +1133,9 @@
 
         // Animate
         doFilteringAnimation(curTasks, curTaskTransforms, tasks, taskTransforms);
+
+        // Notify any callbacks
+        mCb.onTaskStackFilterTriggered();
     }
 
     @Override
@@ -1159,6 +1159,9 @@
 
         // Clear the saved vars
         mStashedScroll = 0;
+
+        // Notify any callbacks
+        mCb.onTaskStackUnfilterTriggered();
     }
 
     /**** ViewPoolConsumer Implementation ****/
@@ -1221,7 +1224,7 @@
         tv.setClipViewInStack(true);
 
         // If the doze trigger has already fired, then update the state for this task view
-        if (mDozeTrigger.hasTriggered()) {
+        if (mUIDozeTrigger.hasTriggered()) {
             tv.setNoUserInteractionState();
         }
 
@@ -1299,6 +1302,9 @@
                     task + " cb: " + mCb);
         }
 
+        // Cancel any doze triggers
+        mUIDozeTrigger.stopDozing();
+
         if (mCb != null) {
             mCb.onTaskLaunched(this, tv, mStack, task);
         }
@@ -1329,393 +1335,4 @@
             }
         }
     }
-}
-
-/* Handles touch events */
-class TaskStackViewTouchHandler implements SwipeHelper.Callback {
-    static int INACTIVE_POINTER_ID = -1;
-
-    TaskStackView mSv;
-    VelocityTracker mVelocityTracker;
-
-    boolean mIsScrolling;
-
-    int mInitialMotionX, mInitialMotionY;
-    int mLastMotionX, mLastMotionY;
-    int mActivePointerId = INACTIVE_POINTER_ID;
-    TaskView mActiveTaskView = null;
-
-    int mTotalScrollMotion;
-    int mMinimumVelocity;
-    int mMaximumVelocity;
-    // The scroll touch slop is used to calculate when we start scrolling
-    int mScrollTouchSlop;
-    // The page touch slop is used to calculate when we start swiping
-    float mPagingTouchSlop;
-
-    SwipeHelper mSwipeHelper;
-    boolean mInterceptedBySwipeHelper;
-
-    public TaskStackViewTouchHandler(Context context, TaskStackView sv) {
-        ViewConfiguration configuration = ViewConfiguration.get(context);
-        mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
-        mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
-        mScrollTouchSlop = configuration.getScaledTouchSlop();
-        mPagingTouchSlop = configuration.getScaledPagingTouchSlop();
-        mSv = sv;
-
-
-        float densityScale = context.getResources().getDisplayMetrics().density;
-        mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, mPagingTouchSlop);
-        mSwipeHelper.setMinAlpha(1f);
-    }
-
-    /** Velocity tracker helpers */
-    void initOrResetVelocityTracker() {
-        if (mVelocityTracker == null) {
-            mVelocityTracker = VelocityTracker.obtain();
-        } else {
-            mVelocityTracker.clear();
-        }
-    }
-    void initVelocityTrackerIfNotExists() {
-        if (mVelocityTracker == null) {
-            mVelocityTracker = VelocityTracker.obtain();
-        }
-    }
-    void recycleVelocityTracker() {
-        if (mVelocityTracker != null) {
-            mVelocityTracker.recycle();
-            mVelocityTracker = null;
-        }
-    }
-
-    /** Returns the view at the specified coordinates */
-    TaskView findViewAtPoint(int x, int y) {
-        int childCount = mSv.getChildCount();
-        for (int i = childCount - 1; i >= 0; i--) {
-            TaskView tv = (TaskView) mSv.getChildAt(i);
-            if (tv.getVisibility() == View.VISIBLE) {
-                if (mSv.isTransformedTouchPointInView(x, y, tv)) {
-                    return tv;
-                }
-            }
-        }
-        return null;
-    }
-
-    /** Touch preprocessing for handling below */
-    public boolean onInterceptTouchEvent(MotionEvent ev) {
-        if (Console.Enabled) {
-            Console.log(Constants.Log.UI.TouchEvents,
-                    "[TaskStackViewTouchHandler|interceptTouchEvent]",
-                    Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
-        }
-
-        // Return early if we have no children
-        boolean hasChildren = (mSv.getChildCount() > 0);
-        if (!hasChildren) {
-            return false;
-        }
-
-        // Pass through to swipe helper if we are swiping
-        mInterceptedBySwipeHelper = mSwipeHelper.onInterceptTouchEvent(ev);
-        if (mInterceptedBySwipeHelper) {
-            return true;
-        }
-
-        boolean wasScrolling = !mSv.mScroller.isFinished() ||
-                (mSv.mScrollAnimator != null && mSv.mScrollAnimator.isRunning());
-        int action = ev.getAction();
-        switch (action & MotionEvent.ACTION_MASK) {
-            case MotionEvent.ACTION_DOWN: {
-                // Save the touch down info
-                mInitialMotionX = mLastMotionX = (int) ev.getX();
-                mInitialMotionY = mLastMotionY = (int) ev.getY();
-                mActivePointerId = ev.getPointerId(0);
-                mActiveTaskView = findViewAtPoint(mLastMotionX, mLastMotionY);
-                // Stop the current scroll if it is still flinging
-                mSv.abortScroller();
-                mSv.abortBoundScrollAnimation();
-                // Initialize the velocity tracker
-                initOrResetVelocityTracker();
-                mVelocityTracker.addMovement(ev);
-                // Check if the scroller is finished yet
-                mIsScrolling = !mSv.mScroller.isFinished();
-                break;
-            }
-            case MotionEvent.ACTION_MOVE: {
-                if (mActivePointerId == INACTIVE_POINTER_ID) break;
-
-                int activePointerIndex = ev.findPointerIndex(mActivePointerId);
-                int y = (int) ev.getY(activePointerIndex);
-                int x = (int) ev.getX(activePointerIndex);
-                if (Math.abs(y - mInitialMotionY) > mScrollTouchSlop) {
-                    // Save the touch move info
-                    mIsScrolling = true;
-                    // Initialize the velocity tracker if necessary
-                    initVelocityTrackerIfNotExists();
-                    mVelocityTracker.addMovement(ev);
-                    // Disallow parents from intercepting touch events
-                    final ViewParent parent = mSv.getParent();
-                    if (parent != null) {
-                        parent.requestDisallowInterceptTouchEvent(true);
-                    }
-                    // Enable HW layers
-                    mSv.addHwLayersRefCount("stackScroll");
-                }
-
-                mLastMotionX = x;
-                mLastMotionY = y;
-                break;
-            }
-            case MotionEvent.ACTION_CANCEL:
-            case MotionEvent.ACTION_UP: {
-                // Animate the scroll back if we've cancelled
-                mSv.animateBoundScroll();
-                // Disable HW layers
-                if (mIsScrolling) {
-                    mSv.decHwLayersRefCount("stackScroll");
-                }
-                // Reset the drag state and the velocity tracker
-                mIsScrolling = false;
-                mActivePointerId = INACTIVE_POINTER_ID;
-                mActiveTaskView = null;
-                mTotalScrollMotion = 0;
-                recycleVelocityTracker();
-                break;
-            }
-        }
-
-        return wasScrolling || mIsScrolling;
-    }
-
-    /** Handles touch events once we have intercepted them */
-    public boolean onTouchEvent(MotionEvent ev) {
-        if (Console.Enabled) {
-            Console.log(Constants.Log.UI.TouchEvents,
-                    "[TaskStackViewTouchHandler|touchEvent]",
-                    Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
-        }
-
-        // Short circuit if we have no children
-        boolean hasChildren = (mSv.getChildCount() > 0);
-        if (!hasChildren) {
-            return false;
-        }
-
-        // Pass through to swipe helper if we are swiping
-        if (mInterceptedBySwipeHelper && mSwipeHelper.onTouchEvent(ev)) {
-            return true;
-        }
-
-        // Update the velocity tracker
-        initVelocityTrackerIfNotExists();
-        mVelocityTracker.addMovement(ev);
-
-        int action = ev.getAction();
-        switch (action & MotionEvent.ACTION_MASK) {
-            case MotionEvent.ACTION_DOWN: {
-                // Save the touch down info
-                mInitialMotionX = mLastMotionX = (int) ev.getX();
-                mInitialMotionY = mLastMotionY = (int) ev.getY();
-                mActivePointerId = ev.getPointerId(0);
-                mActiveTaskView = findViewAtPoint(mLastMotionX, mLastMotionY);
-                // Stop the current scroll if it is still flinging
-                mSv.abortScroller();
-                mSv.abortBoundScrollAnimation();
-                // Initialize the velocity tracker
-                initOrResetVelocityTracker();
-                mVelocityTracker.addMovement(ev);
-                // Disallow parents from intercepting touch events
-                final ViewParent parent = mSv.getParent();
-                if (parent != null) {
-                    parent.requestDisallowInterceptTouchEvent(true);
-                }
-                break;
-            }
-            case MotionEvent.ACTION_POINTER_DOWN: {
-                final int index = ev.getActionIndex();
-                mActivePointerId = ev.getPointerId(index);
-                mLastMotionX = (int) ev.getX(index);
-                mLastMotionY = (int) ev.getY(index);
-                break;
-            }
-            case MotionEvent.ACTION_MOVE: {
-                if (mActivePointerId == INACTIVE_POINTER_ID) break;
-
-                int activePointerIndex = ev.findPointerIndex(mActivePointerId);
-                int x = (int) ev.getX(activePointerIndex);
-                int y = (int) ev.getY(activePointerIndex);
-                int yTotal = Math.abs(y - mInitialMotionY);
-                int deltaY = mLastMotionY - y;
-                if (!mIsScrolling) {
-                    if (yTotal > mScrollTouchSlop) {
-                        mIsScrolling = true;
-                        // Initialize the velocity tracker
-                        initOrResetVelocityTracker();
-                        mVelocityTracker.addMovement(ev);
-                        // Disallow parents from intercepting touch events
-                        final ViewParent parent = mSv.getParent();
-                        if (parent != null) {
-                            parent.requestDisallowInterceptTouchEvent(true);
-                        }
-                        // Enable HW layers
-                        mSv.addHwLayersRefCount("stackScroll");
-                    }
-                }
-                if (mIsScrolling) {
-                    int curStackScroll = mSv.getStackScroll();
-                    int overScrollAmount = mSv.getScrollAmountOutOfBounds(curStackScroll + deltaY);
-                    if (overScrollAmount != 0) {
-                        // Bound the overscroll to a fixed amount, and inversely scale the y-movement
-                        // relative to how close we are to the max overscroll
-                        float maxOverScroll = mSv.mTaskRect.height() / 3f;
-                        deltaY = Math.round(deltaY * (1f - (Math.min(maxOverScroll, overScrollAmount)
-                                / maxOverScroll)));
-                    }
-                    mSv.setStackScroll(curStackScroll + deltaY);
-                    if (mSv.isScrollOutOfBounds()) {
-                        mVelocityTracker.clear();
-                    }
-                }
-                mLastMotionX = x;
-                mLastMotionY = y;
-                mTotalScrollMotion += Math.abs(deltaY);
-                break;
-            }
-            case MotionEvent.ACTION_UP: {
-                final VelocityTracker velocityTracker = mVelocityTracker;
-                velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
-                int velocity = (int) velocityTracker.getYVelocity(mActivePointerId);
-
-                if (mIsScrolling && (Math.abs(velocity) > mMinimumVelocity)) {
-                    // Enable HW layers on the stack
-                    mSv.addHwLayersRefCount("flingScroll");
-                    // XXX: Make this animation a function of the velocity AND distance
-                    int overscrollRange = (int) (Math.min(1f,
-                            Math.abs((float) velocity / mMaximumVelocity)) *
-                            Constants.Values.TaskStackView.TaskStackOverscrollRange);
-
-                    if (Console.Enabled) {
-                        Console.log(Constants.Log.UI.TouchEvents,
-                                "[TaskStackViewTouchHandler|fling]",
-                                "scroll: " + mSv.getStackScroll() + " velocity: " + velocity +
-                                        " maxVelocity: " + mMaximumVelocity +
-                                        " overscrollRange: " + overscrollRange,
-                                Console.AnsiGreen);
-                    }
-
-                    // Fling scroll
-                    mSv.mScroller.fling(0, mSv.getStackScroll(),
-                            0, -velocity,
-                            0, 0,
-                            mSv.mMinScroll, mSv.mMaxScroll,
-                            0, overscrollRange);
-                    // Invalidate to kick off computeScroll
-                    mSv.invalidate(mSv.mStackRect);
-                } else if (mSv.isScrollOutOfBounds()) {
-                    // Animate the scroll back into bounds
-                    // XXX: Make this animation a function of the velocity OR distance
-                    mSv.animateBoundScroll();
-                }
-
-                if (mIsScrolling) {
-                    // Disable HW layers
-                    mSv.decHwLayersRefCount("stackScroll");
-                }
-                mActivePointerId = INACTIVE_POINTER_ID;
-                mIsScrolling = false;
-                mTotalScrollMotion = 0;
-                recycleVelocityTracker();
-                break;
-            }
-            case MotionEvent.ACTION_POINTER_UP: {
-                int pointerIndex = ev.getActionIndex();
-                int pointerId = ev.getPointerId(pointerIndex);
-                if (pointerId == mActivePointerId) {
-                    // Select a new active pointer id and reset the motion state
-                    final int newPointerIndex = (pointerIndex == 0) ? 1 : 0;
-                    mActivePointerId = ev.getPointerId(newPointerIndex);
-                    mLastMotionX = (int) ev.getX(newPointerIndex);
-                    mLastMotionY = (int) ev.getY(newPointerIndex);
-                    mVelocityTracker.clear();
-                }
-                break;
-            }
-            case MotionEvent.ACTION_CANCEL: {
-                if (mIsScrolling) {
-                    // Disable HW layers
-                    mSv.decHwLayersRefCount("stackScroll");
-                }
-                if (mSv.isScrollOutOfBounds()) {
-                    // Animate the scroll back into bounds
-                    // XXX: Make this animation a function of the velocity OR distance
-                    mSv.animateBoundScroll();
-                }
-                mActivePointerId = INACTIVE_POINTER_ID;
-                mIsScrolling = false;
-                mTotalScrollMotion = 0;
-                recycleVelocityTracker();
-                break;
-            }
-        }
-        return true;
-    }
-
-    /**** SwipeHelper Implementation ****/
-
-    @Override
-    public View getChildAtPosition(MotionEvent ev) {
-        return findViewAtPoint((int) ev.getX(), (int) ev.getY());
-    }
-
-    @Override
-    public boolean canChildBeDismissed(View v) {
-        return true;
-    }
-
-    @Override
-    public void onBeginDrag(View v) {
-        // Enable HW layers
-        mSv.addHwLayersRefCount("swipeBegin");
-        // Disable clipping with the stack while we are swiping
-        TaskView tv = (TaskView) v;
-        tv.setClipViewInStack(false);
-        // Disallow parents from intercepting touch events
-        final ViewParent parent = mSv.getParent();
-        if (parent != null) {
-            parent.requestDisallowInterceptTouchEvent(true);
-        }
-    }
-
-    @Override
-    public void onSwipeChanged(View v, float delta) {
-        // Do nothing
-    }
-
-    @Override
-    public void onChildDismissed(View v) {
-        TaskView tv = (TaskView) v;
-        mSv.onTaskDismissed(tv);
-
-        // Re-enable clipping with the stack (we will reuse this view)
-        tv.setClipViewInStack(true);
-
-        // Disable HW layers
-        mSv.decHwLayersRefCount("swipeComplete");
-    }
-
-    @Override
-    public void onSnapBackCompleted(View v) {
-        // Re-enable clipping with the stack
-        TaskView tv = (TaskView) v;
-        tv.setClipViewInStack(true);
-    }
-
-    @Override
-    public void onDragCancelled(View v) {
-        // Disable HW layers
-        mSv.decHwLayersRefCount("swipeCancelled");
-    }
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
new file mode 100644
index 0000000..d2f18ae
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -0,0 +1,415 @@
+/*
+ * 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.
+ */
+
+package com.android.systemui.recents.views;
+
+import android.content.Context;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewParent;
+import com.android.systemui.recents.Console;
+import com.android.systemui.recents.Constants;
+
+/* Handles touch events for a TaskStackView. */
+class TaskStackViewTouchHandler implements SwipeHelper.Callback {
+    static int INACTIVE_POINTER_ID = -1;
+
+    TaskStackView mSv;
+    VelocityTracker mVelocityTracker;
+
+    boolean mIsScrolling;
+
+    int mInitialMotionX, mInitialMotionY;
+    int mLastMotionX, mLastMotionY;
+    int mActivePointerId = INACTIVE_POINTER_ID;
+    TaskView mActiveTaskView = null;
+
+    int mTotalScrollMotion;
+    int mMinimumVelocity;
+    int mMaximumVelocity;
+    // The scroll touch slop is used to calculate when we start scrolling
+    int mScrollTouchSlop;
+    // The page touch slop is used to calculate when we start swiping
+    float mPagingTouchSlop;
+
+    SwipeHelper mSwipeHelper;
+    boolean mInterceptedBySwipeHelper;
+
+    public TaskStackViewTouchHandler(Context context, TaskStackView sv) {
+        ViewConfiguration configuration = ViewConfiguration.get(context);
+        mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
+        mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
+        mScrollTouchSlop = configuration.getScaledTouchSlop();
+        mPagingTouchSlop = configuration.getScaledPagingTouchSlop();
+        mSv = sv;
+
+
+        float densityScale = context.getResources().getDisplayMetrics().density;
+        mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, mPagingTouchSlop);
+        mSwipeHelper.setMinAlpha(1f);
+    }
+
+    /** Velocity tracker helpers */
+    void initOrResetVelocityTracker() {
+        if (mVelocityTracker == null) {
+            mVelocityTracker = VelocityTracker.obtain();
+        } else {
+            mVelocityTracker.clear();
+        }
+    }
+    void initVelocityTrackerIfNotExists() {
+        if (mVelocityTracker == null) {
+            mVelocityTracker = VelocityTracker.obtain();
+        }
+    }
+    void recycleVelocityTracker() {
+        if (mVelocityTracker != null) {
+            mVelocityTracker.recycle();
+            mVelocityTracker = null;
+        }
+    }
+
+    /** Returns the view at the specified coordinates */
+    TaskView findViewAtPoint(int x, int y) {
+        int childCount = mSv.getChildCount();
+        for (int i = childCount - 1; i >= 0; i--) {
+            TaskView tv = (TaskView) mSv.getChildAt(i);
+            if (tv.getVisibility() == View.VISIBLE) {
+                if (mSv.isTransformedTouchPointInView(x, y, tv)) {
+                    return tv;
+                }
+            }
+        }
+        return null;
+    }
+
+    /** Touch preprocessing for handling below */
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        if (Console.Enabled) {
+            Console.log(Constants.Log.UI.TouchEvents,
+                    "[TaskStackViewTouchHandler|interceptTouchEvent]",
+                    Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+        }
+
+        // Return early if we have no children
+        boolean hasChildren = (mSv.getChildCount() > 0);
+        if (!hasChildren) {
+            return false;
+        }
+
+        // Pass through to swipe helper if we are swiping
+        mInterceptedBySwipeHelper = mSwipeHelper.onInterceptTouchEvent(ev);
+        if (mInterceptedBySwipeHelper) {
+            return true;
+        }
+
+        boolean wasScrolling = !mSv.mScroller.isFinished() ||
+                (mSv.mScrollAnimator != null && mSv.mScrollAnimator.isRunning());
+        int action = ev.getAction();
+        switch (action & MotionEvent.ACTION_MASK) {
+            case MotionEvent.ACTION_DOWN: {
+                // Save the touch down info
+                mInitialMotionX = mLastMotionX = (int) ev.getX();
+                mInitialMotionY = mLastMotionY = (int) ev.getY();
+                mActivePointerId = ev.getPointerId(0);
+                mActiveTaskView = findViewAtPoint(mLastMotionX, mLastMotionY);
+                // Stop the current scroll if it is still flinging
+                mSv.abortScroller();
+                mSv.abortBoundScrollAnimation();
+                // Initialize the velocity tracker
+                initOrResetVelocityTracker();
+                mVelocityTracker.addMovement(ev);
+                // Check if the scroller is finished yet
+                mIsScrolling = !mSv.mScroller.isFinished();
+                break;
+            }
+            case MotionEvent.ACTION_MOVE: {
+                if (mActivePointerId == INACTIVE_POINTER_ID) break;
+
+                int activePointerIndex = ev.findPointerIndex(mActivePointerId);
+                int y = (int) ev.getY(activePointerIndex);
+                int x = (int) ev.getX(activePointerIndex);
+                if (Math.abs(y - mInitialMotionY) > mScrollTouchSlop) {
+                    // Save the touch move info
+                    mIsScrolling = true;
+                    // Initialize the velocity tracker if necessary
+                    initVelocityTrackerIfNotExists();
+                    mVelocityTracker.addMovement(ev);
+                    // Disallow parents from intercepting touch events
+                    final ViewParent parent = mSv.getParent();
+                    if (parent != null) {
+                        parent.requestDisallowInterceptTouchEvent(true);
+                    }
+                    // Enable HW layers
+                    mSv.addHwLayersRefCount("stackScroll");
+                }
+
+                mLastMotionX = x;
+                mLastMotionY = y;
+                break;
+            }
+            case MotionEvent.ACTION_CANCEL:
+            case MotionEvent.ACTION_UP: {
+                // Animate the scroll back if we've cancelled
+                mSv.animateBoundScroll();
+                // Disable HW layers
+                if (mIsScrolling) {
+                    mSv.decHwLayersRefCount("stackScroll");
+                }
+                // Reset the drag state and the velocity tracker
+                mIsScrolling = false;
+                mActivePointerId = INACTIVE_POINTER_ID;
+                mActiveTaskView = null;
+                mTotalScrollMotion = 0;
+                recycleVelocityTracker();
+                break;
+            }
+        }
+
+        return wasScrolling || mIsScrolling;
+    }
+
+    /** Handles touch events once we have intercepted them */
+    public boolean onTouchEvent(MotionEvent ev) {
+        if (Console.Enabled) {
+            Console.log(Constants.Log.UI.TouchEvents,
+                    "[TaskStackViewTouchHandler|touchEvent]",
+                    Console.motionEventActionToString(ev.getAction()), Console.AnsiBlue);
+        }
+
+        // Short circuit if we have no children
+        boolean hasChildren = (mSv.getChildCount() > 0);
+        if (!hasChildren) {
+            return false;
+        }
+
+        // Pass through to swipe helper if we are swiping
+        if (mInterceptedBySwipeHelper && mSwipeHelper.onTouchEvent(ev)) {
+            return true;
+        }
+
+        // Update the velocity tracker
+        initVelocityTrackerIfNotExists();
+        mVelocityTracker.addMovement(ev);
+
+        int action = ev.getAction();
+        switch (action & MotionEvent.ACTION_MASK) {
+            case MotionEvent.ACTION_DOWN: {
+                // Save the touch down info
+                mInitialMotionX = mLastMotionX = (int) ev.getX();
+                mInitialMotionY = mLastMotionY = (int) ev.getY();
+                mActivePointerId = ev.getPointerId(0);
+                mActiveTaskView = findViewAtPoint(mLastMotionX, mLastMotionY);
+                // Stop the current scroll if it is still flinging
+                mSv.abortScroller();
+                mSv.abortBoundScrollAnimation();
+                // Initialize the velocity tracker
+                initOrResetVelocityTracker();
+                mVelocityTracker.addMovement(ev);
+                // Disallow parents from intercepting touch events
+                final ViewParent parent = mSv.getParent();
+                if (parent != null) {
+                    parent.requestDisallowInterceptTouchEvent(true);
+                }
+                break;
+            }
+            case MotionEvent.ACTION_POINTER_DOWN: {
+                final int index = ev.getActionIndex();
+                mActivePointerId = ev.getPointerId(index);
+                mLastMotionX = (int) ev.getX(index);
+                mLastMotionY = (int) ev.getY(index);
+                break;
+            }
+            case MotionEvent.ACTION_MOVE: {
+                if (mActivePointerId == INACTIVE_POINTER_ID) break;
+
+                int activePointerIndex = ev.findPointerIndex(mActivePointerId);
+                int x = (int) ev.getX(activePointerIndex);
+                int y = (int) ev.getY(activePointerIndex);
+                int yTotal = Math.abs(y - mInitialMotionY);
+                int deltaY = mLastMotionY - y;
+                if (!mIsScrolling) {
+                    if (yTotal > mScrollTouchSlop) {
+                        mIsScrolling = true;
+                        // Initialize the velocity tracker
+                        initOrResetVelocityTracker();
+                        mVelocityTracker.addMovement(ev);
+                        // Disallow parents from intercepting touch events
+                        final ViewParent parent = mSv.getParent();
+                        if (parent != null) {
+                            parent.requestDisallowInterceptTouchEvent(true);
+                        }
+                        // Enable HW layers
+                        mSv.addHwLayersRefCount("stackScroll");
+                    }
+                }
+                if (mIsScrolling) {
+                    int curStackScroll = mSv.getStackScroll();
+                    int overScrollAmount = mSv.getScrollAmountOutOfBounds(curStackScroll + deltaY);
+                    if (overScrollAmount != 0) {
+                        // Bound the overscroll to a fixed amount, and inversely scale the y-movement
+                        // relative to how close we are to the max overscroll
+                        float maxOverScroll = mSv.mTaskRect.height() / 3f;
+                        deltaY = Math.round(deltaY * (1f - (Math.min(maxOverScroll, overScrollAmount)
+                                / maxOverScroll)));
+                    }
+                    mSv.setStackScroll(curStackScroll + deltaY);
+                    if (mSv.isScrollOutOfBounds()) {
+                        mVelocityTracker.clear();
+                    }
+                }
+                mLastMotionX = x;
+                mLastMotionY = y;
+                mTotalScrollMotion += Math.abs(deltaY);
+                break;
+            }
+            case MotionEvent.ACTION_UP: {
+                final VelocityTracker velocityTracker = mVelocityTracker;
+                velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+                int velocity = (int) velocityTracker.getYVelocity(mActivePointerId);
+
+                if (mIsScrolling && (Math.abs(velocity) > mMinimumVelocity)) {
+                    // Enable HW layers on the stack
+                    mSv.addHwLayersRefCount("flingScroll");
+                    // XXX: Make this animation a function of the velocity AND distance
+                    int overscrollRange = (int) (Math.min(1f,
+                            Math.abs((float) velocity / mMaximumVelocity)) *
+                            Constants.Values.TaskStackView.TaskStackOverscrollRange);
+
+                    if (Console.Enabled) {
+                        Console.log(Constants.Log.UI.TouchEvents,
+                                "[TaskStackViewTouchHandler|fling]",
+                                "scroll: " + mSv.getStackScroll() + " velocity: " + velocity +
+                                        " maxVelocity: " + mMaximumVelocity +
+                                        " overscrollRange: " + overscrollRange,
+                                Console.AnsiGreen);
+                    }
+
+                    // Fling scroll
+                    mSv.mScroller.fling(0, mSv.getStackScroll(),
+                            0, -velocity,
+                            0, 0,
+                            mSv.mMinScroll, mSv.mMaxScroll,
+                            0, overscrollRange);
+                    // Invalidate to kick off computeScroll
+                    mSv.invalidate(mSv.mStackRect);
+                } else if (mSv.isScrollOutOfBounds()) {
+                    // Animate the scroll back into bounds
+                    // XXX: Make this animation a function of the velocity OR distance
+                    mSv.animateBoundScroll();
+                }
+
+                if (mIsScrolling) {
+                    // Disable HW layers
+                    mSv.decHwLayersRefCount("stackScroll");
+                }
+                mActivePointerId = INACTIVE_POINTER_ID;
+                mIsScrolling = false;
+                mTotalScrollMotion = 0;
+                recycleVelocityTracker();
+                break;
+            }
+            case MotionEvent.ACTION_POINTER_UP: {
+                int pointerIndex = ev.getActionIndex();
+                int pointerId = ev.getPointerId(pointerIndex);
+                if (pointerId == mActivePointerId) {
+                    // Select a new active pointer id and reset the motion state
+                    final int newPointerIndex = (pointerIndex == 0) ? 1 : 0;
+                    mActivePointerId = ev.getPointerId(newPointerIndex);
+                    mLastMotionX = (int) ev.getX(newPointerIndex);
+                    mLastMotionY = (int) ev.getY(newPointerIndex);
+                    mVelocityTracker.clear();
+                }
+                break;
+            }
+            case MotionEvent.ACTION_CANCEL: {
+                if (mIsScrolling) {
+                    // Disable HW layers
+                    mSv.decHwLayersRefCount("stackScroll");
+                }
+                if (mSv.isScrollOutOfBounds()) {
+                    // Animate the scroll back into bounds
+                    // XXX: Make this animation a function of the velocity OR distance
+                    mSv.animateBoundScroll();
+                }
+                mActivePointerId = INACTIVE_POINTER_ID;
+                mIsScrolling = false;
+                mTotalScrollMotion = 0;
+                recycleVelocityTracker();
+                break;
+            }
+        }
+        return true;
+    }
+
+    /**** SwipeHelper Implementation ****/
+
+    @Override
+    public View getChildAtPosition(MotionEvent ev) {
+        return findViewAtPoint((int) ev.getX(), (int) ev.getY());
+    }
+
+    @Override
+    public boolean canChildBeDismissed(View v) {
+        return true;
+    }
+
+    @Override
+    public void onBeginDrag(View v) {
+        // Enable HW layers
+        mSv.addHwLayersRefCount("swipeBegin");
+        // Disable clipping with the stack while we are swiping
+        TaskView tv = (TaskView) v;
+        tv.setClipViewInStack(false);
+        // Disallow parents from intercepting touch events
+        final ViewParent parent = mSv.getParent();
+        if (parent != null) {
+            parent.requestDisallowInterceptTouchEvent(true);
+        }
+    }
+
+    @Override
+    public void onSwipeChanged(View v, float delta) {
+        // Do nothing
+    }
+
+    @Override
+    public void onChildDismissed(View v) {
+        TaskView tv = (TaskView) v;
+        mSv.onTaskDismissed(tv);
+
+        // Re-enable clipping with the stack (we will reuse this view)
+        tv.setClipViewInStack(true);
+
+        // Disable HW layers
+        mSv.decHwLayersRefCount("swipeComplete");
+    }
+
+    @Override
+    public void onSnapBackCompleted(View v) {
+        // Re-enable clipping with the stack
+        TaskView tv = (TaskView) v;
+        tv.setClipViewInStack(true);
+    }
+
+    @Override
+    public void onDragCancelled(View v) {
+        // Disable HW layers
+        mSv.decHwLayersRefCount("swipeCancelled");
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java b/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java
index b5e8ffd..13407aa 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/ViewAnimation.java
@@ -25,7 +25,7 @@
     /* The animation context for a task view animation into Recents */
     public static class TaskViewEnterContext {
         // The full screenshot view that we are animating down
-        FullScreenTransitionView fullScreenshot;
+        FullscreenTransitionOverlayView fullScreenshot;
         // The transform of the current task view
         TaskViewTransform transform;
         // The stack rect that the transform is relative to
@@ -39,7 +39,7 @@
         // Whether this is the front most task view
         boolean isFrontMost;
 
-        public TaskViewEnterContext(FullScreenTransitionView fss) {
+        public TaskViewEnterContext(FullscreenTransitionOverlayView fss) {
             fullScreenshot = fss;
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 5bad602..5981898 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -212,13 +212,6 @@
         return mShowingPublic ? mRowMinHeight : mMaxExpandHeight;
     }
 
-    /**
-     * @return the potential height this view could expand in addition.
-     */
-    public int getExpandPotential() {
-        return getIntrinsicHeight() - getActualHeight();
-    }
-
     @Override
     public boolean isContentExpandable() {
         NotificationContentView showingLayout = getShowingLayout();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 5cde979..f919501 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -17,12 +17,16 @@
 package com.android.systemui.statusbar;
 
 import android.content.Context;
+import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
 import android.util.AttributeSet;
-import android.view.Gravity;
 import android.view.View;
-
+import android.view.animation.Interpolator;
+import android.view.animation.LinearInterpolator;
 import android.widget.FrameLayout;
+
 import com.android.systemui.R;
 
 /**
@@ -32,6 +36,8 @@
  */
 public class NotificationContentView extends FrameLayout {
 
+    private static final long ANIMATION_DURATION_LENGTH = 170;
+
     private final Rect mClipBounds = new Rect();
 
     private View mContractedChild;
@@ -41,10 +47,17 @@
     private int mClipTopAmount;
     private int mActualHeight;
 
+    private final Interpolator mLinearInterpolator = new LinearInterpolator();
+
+    private boolean mContractedVisible = true;
+
+    private Paint mFadePaint = new Paint();
+
     public NotificationContentView(Context context, AttributeSet attrs) {
         super(context, attrs);
         mSmallHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height);
         mActualHeight = mSmallHeight;
+        mFadePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
     }
 
     @Override
@@ -60,7 +73,7 @@
         sanitizeContractedLayoutParams(child);
         addView(child);
         mContractedChild = child;
-        selectLayout();
+        selectLayout(false /* animate */, true /* force */);
     }
 
     public void setExpandedChild(View child) {
@@ -69,12 +82,12 @@
         }
         addView(child);
         mExpandedChild = child;
-        selectLayout();
+        selectLayout(false /* animate */, true /* force */);
     }
 
     public void setActualHeight(int actualHeight) {
         mActualHeight = actualHeight;
-        selectLayout();
+        selectLayout(true /* animate */, false /* force */);
         updateClipping();
     }
 
@@ -104,26 +117,60 @@
         contractedChild.setLayoutParams(lp);
     }
 
-    private void selectLayout() {
-        if (mActualHeight <= mSmallHeight || mExpandedChild == null) {
-            if (mContractedChild != null && mContractedChild.getVisibility() != View.VISIBLE) {
-                mContractedChild.setVisibility(View.VISIBLE);
-            }
-            if (mExpandedChild != null && mExpandedChild.getVisibility() != View.INVISIBLE) {
-                mExpandedChild.setVisibility(View.INVISIBLE);
-            }
-        } else {
-            if (mExpandedChild.getVisibility() != View.VISIBLE) {
-                mExpandedChild.setVisibility(View.VISIBLE);
-            }
-            if (mContractedChild != null && mContractedChild.getVisibility() != View.INVISIBLE) {
-                mContractedChild.setVisibility(View.INVISIBLE);
+    private void selectLayout(boolean animate, boolean force) {
+        if (mContractedChild == null) {
+            return;
+        }
+        boolean showContractedChild = showContractedChild();
+        if (showContractedChild != mContractedVisible || force) {
+            if (animate && mExpandedChild != null) {
+                runSwitchAnimation(showContractedChild);
+            } else if (mExpandedChild != null) {
+                mContractedChild.setVisibility(showContractedChild ? View.VISIBLE : View.INVISIBLE);
+                mContractedChild.setAlpha(showContractedChild ? 1f : 0f);
+                mExpandedChild.setVisibility(showContractedChild ? View.INVISIBLE : View.VISIBLE);
+                mExpandedChild.setAlpha(showContractedChild ? 0f : 1f);
             }
         }
+        mContractedVisible = showContractedChild;
+    }
+
+    private void runSwitchAnimation(final boolean showContractedChild) {
+        mContractedChild.setVisibility(View.VISIBLE);
+        mExpandedChild.setVisibility(View.VISIBLE);
+        mContractedChild.setLayerType(LAYER_TYPE_HARDWARE, mFadePaint);
+        mExpandedChild.setLayerType(LAYER_TYPE_HARDWARE, mFadePaint);
+        setLayerType(LAYER_TYPE_HARDWARE, null);
+        mContractedChild.animate()
+                .alpha(showContractedChild ? 1f : 0f)
+                .setDuration(ANIMATION_DURATION_LENGTH)
+                .setInterpolator(mLinearInterpolator);
+        mExpandedChild.animate()
+                .alpha(showContractedChild ? 0f : 1f)
+                .setDuration(ANIMATION_DURATION_LENGTH)
+                .setInterpolator(mLinearInterpolator)
+                .withEndAction(new Runnable() {
+                    @Override
+                    public void run() {
+                        mContractedChild.setLayerType(LAYER_TYPE_NONE, null);
+                        mExpandedChild.setLayerType(LAYER_TYPE_NONE, null);
+                        setLayerType(LAYER_TYPE_NONE, null);
+                        mContractedChild.setVisibility(showContractedChild
+                                ? View.VISIBLE
+                                : View.INVISIBLE);
+                        mExpandedChild.setVisibility(showContractedChild
+                                ? View.INVISIBLE
+                                : View.VISIBLE);
+                    }
+                });
+    }
+
+    private boolean showContractedChild() {
+        return mActualHeight <= mSmallHeight || mExpandedChild == null;
     }
 
     public void notifyContentUpdated() {
-        selectLayout();
+        selectLayout(false /* animate */, true /* force */);
     }
 
     public boolean isContentExpandable() {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 637061d..ddfa9c1 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -42,7 +42,6 @@
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.media.AudioManager;
-import android.media.AudioSystem;
 import android.media.IAudioService;
 import android.media.Ringtone;
 import android.media.RingtoneManager;
@@ -51,7 +50,6 @@
 import android.os.FactoryTest;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.IRemoteCallback;
 import android.os.Looper;
 import android.os.Message;
 import android.os.Messenger;
@@ -105,7 +103,6 @@
 import com.android.internal.policy.impl.keyguard.KeyguardServiceDelegate;
 import com.android.internal.policy.impl.keyguard.KeyguardServiceDelegate.ShowListener;
 import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.telephony.ITelephony;
 import com.android.internal.widget.PointerLocationView;
 import com.android.server.LocalServices;
 
@@ -270,10 +267,10 @@
     // The following are only accessed on the mHandler thread.
     boolean mKeyguardDrawComplete;
     boolean mWindowManagerDrawComplete;
-    ArrayList<ScreenOnListener> mScreenOnListeners = new ArrayList<ScreenOnListener>();
-    final IRemoteCallback mWindowManagerDrawCallback = new IRemoteCallback.Stub() {
+    ScreenOnListener mScreenOnListener;
+    final Runnable mWindowManagerDrawCallback = new Runnable() {
         @Override
-        public void sendResult(Bundle data) {
+        public void run() {
             if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for display!");
             mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE);
         }
@@ -521,6 +518,7 @@
     private static final int MSG_KEYGUARD_DRAWN_TIMEOUT = 6;
     private static final int MSG_WINDOW_MANAGER_DRAWN_COMPLETE = 7;
     private static final int MSG_WAKING_UP = 8;
+    private static final int MSG_DISPATCH_SHOW_RECENTS = 9;
 
     private class PolicyHandler extends Handler {
         @Override
@@ -538,6 +536,9 @@
                 case MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK:
                     dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj);
                     break;
+                case MSG_DISPATCH_SHOW_RECENTS:
+                    showRecentApps(false);
+                    break;
                 case MSG_KEYGUARD_DRAWN_COMPLETE:
                     if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mKeyguardDrawComplete");
                     mKeyguardDrawComplete = true;
@@ -2589,6 +2590,12 @@
         }
     }
 
+    @Override
+    public void showRecentApps() {
+        mHandler.removeMessages(MSG_DISPATCH_SHOW_RECENTS);
+        mHandler.sendEmptyMessage(MSG_DISPATCH_SHOW_RECENTS);
+    }
+
     private void showRecentApps(boolean triggeredFromAltTab) {
         mPreloadedRecentApps = false; // preloading no longer needs to be canceled
         try {
@@ -2639,19 +2646,22 @@
                     }
                 }
             });
-        } else if (mRecentsVisible) {
-            // Recents is started on top of Home, so when we launch home while recents is open, let
-            // it do its own animation and then finish itself
-            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
-            hideRecentApps(false);
         } else {
             // no keyguard stuff to worry about, just launch home!
             try {
                 ActivityManagerNative.getDefault().stopAppSwitches();
             } catch (RemoteException e) {
             }
-            sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
-            startDockOrHome();
+            if (mRecentsVisible) {
+                // Hide Recents and notify it to launch Home
+                awakenDreams();
+                sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
+                hideRecentApps(false);
+            } else {
+                // Otherwise, just launch Home
+                sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
+                startDockOrHome();
+            }
         }
     }
 
@@ -4099,6 +4109,9 @@
         // If the key would be handled globally, just return the result, don't worry about special
         // key processing.
         if (mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
+            if (isWakeKey) {
+                mPowerManager.wakeUp(event.getEventTime());
+            }
             return result;
         }
 
@@ -4543,7 +4556,7 @@
     // Called on the mHandler thread.
     private void handleWakingUp(final ScreenOnListener screenOnListener) {
         if (screenOnListener != null) {
-            mScreenOnListeners.add(screenOnListener);
+            mScreenOnListener = screenOnListener;
         }
 
         synchronized (mLock) {
@@ -4575,8 +4588,11 @@
             return;
         }
 
+        ScreenOnListener screenOnListener;
         synchronized (mLock) {
             mScreenOnFully = true;
+            screenOnListener = mScreenOnListener;
+            mScreenOnListener = null;
         }
 
         try {
@@ -4584,8 +4600,8 @@
         } catch (RemoteException unhandled) {
         }
 
-        for (int i = mScreenOnListeners.size() - 1; i >=0; --i) {
-            mScreenOnListeners.remove(i).onScreenOn();
+        if (screenOnListener != null) {
+            screenOnListener.onScreenOn();
         }
 
         setKeyguardDrawn();
diff --git a/rs/java/android/renderscript/FieldPacker.java b/rs/java/android/renderscript/FieldPacker.java
index f39aa5f..20b07e7 100644
--- a/rs/java/android/renderscript/FieldPacker.java
+++ b/rs/java/android/renderscript/FieldPacker.java
@@ -36,10 +36,15 @@
     }
 
     public FieldPacker(byte[] data) {
-        mPos = 0;
+        // Advance mPos to the end of the buffer, since we are copying in the
+        // full data input.
+        mPos = data.length;
         mLen = data.length;
         mData = data;
         mAlignment = new BitSet();
+        // TODO: We should either have an actual FieldPacker copy constructor
+        // or drop support for computing alignment like this. As it stands,
+        // subAlign() can never work correctly for copied FieldPacker objects.
     }
 
     public void align(int v) {
diff --git a/services/core/java/com/android/server/DisplayThread.java b/services/core/java/com/android/server/DisplayThread.java
index 528ba0a..aa0a805 100644
--- a/services/core/java/com/android/server/DisplayThread.java
+++ b/services/core/java/com/android/server/DisplayThread.java
@@ -41,14 +41,14 @@
     }
 
     public static DisplayThread get() {
-        synchronized (UiThread.class) {
+        synchronized (DisplayThread.class) {
             ensureThreadLocked();
             return sInstance;
         }
     }
 
     public static Handler getHandler() {
-        synchronized (UiThread.class) {
+        synchronized (DisplayThread.class) {
             ensureThreadLocked();
             return sHandler;
         }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 57b56b4..3bff2ad 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1832,8 +1832,7 @@
                         final int N = mProcessCpuTracker.countStats();
                         for (int j=0; j<N; j++) {
                             ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(j);
-                            if (st.vsize <= 0 || st.uid >= Process.FIRST_APPLICATION_UID
-                                    || st.uid == Process.SYSTEM_UID) {
+                            if (st.vsize <= 0 || st.uid >= Process.FIRST_APPLICATION_UID) {
                                 // This is definitely an application process; skip it.
                                 continue;
                             }
@@ -1851,8 +1850,7 @@
                         if (DEBUG_PSS) Slog.d(TAG, "Collected native and kernel memory in "
                                 + (SystemClock.uptimeMillis()-start) + "ms");
                         mProcessStats.addSysMemUsageLocked(memInfo.getCachedSizeKb(),
-                                memInfo.getFreeSizeKb(),
-                                memInfo.getSwapTotalSizeKb()-memInfo.getSwapFreeSizeKb(),
+                                memInfo.getFreeSizeKb(), memInfo.getZramTotalSizeKb(),
                                 memInfo.getBuffersSizeKb()+memInfo.getShmemSizeKb()
                                         +memInfo.getSlabSizeKb(),
                                 nativeTotalPss);
@@ -7230,7 +7228,7 @@
         // Compose the recent task info
         ActivityManager.RecentTaskInfo rti
                 = new ActivityManager.RecentTaskInfo();
-        rti.id = tr.mActivities.isEmpty() ? -1 : tr.taskId;
+        rti.id = tr.getTopActivity() == null ? -1 : tr.taskId;
         rti.persistentId = tr.taskId;
         rti.baseIntent = new Intent(tr.getBaseIntent());
         rti.origActivity = tr.origActivity;
@@ -7297,6 +7295,12 @@
                             continue;
                         }
                     }
+                    if (tr.intent != null &&
+                            (tr.intent.getFlags() & Intent.FLAG_ACTIVITY_AUTO_REMOVE_FROM_RECENTS)
+                            != 0 && tr.getTopActivity() == null) {
+                        // Don't include auto remove tasks that are finished or finishing.
+                        continue;
+                    }
 
                     ActivityManager.RecentTaskInfo rti = createRecentTaskInfoFromTaskRecord(tr);
                     if (!detailed) {
@@ -7516,6 +7520,10 @@
                     Slog.e(TAG, "moveTaskToFront: Attempt to violate Lock Task Mode");
                     return;
                 }
+                final ActivityRecord prev = mStackSupervisor.topRunningActivityLocked();
+                if (prev != null && prev.isRecentsActivity()) {
+                    task.setTaskToReturnTo(ActivityRecord.RECENTS_ACTIVITY_TYPE);
+                }
                 mStackSupervisor.findTaskToMoveToFrontLocked(task, flags, options);
             } finally {
                 Binder.restoreCallingIdentity(origId);
@@ -12817,8 +12825,7 @@
             if (nativeProcTotalPss > 0) {
                 synchronized (this) {
                     mProcessStats.addSysMemUsageLocked(memInfo.getCachedSizeKb(),
-                            memInfo.getFreeSizeKb(),
-                            memInfo.getSwapTotalSizeKb()-memInfo.getSwapFreeSizeKb(),
+                            memInfo.getFreeSizeKb(), memInfo.getZramTotalSizeKb(),
                             memInfo.getBuffersSizeKb()+memInfo.getShmemSizeKb()+memInfo.getSlabSizeKb(),
                             nativeProcTotalPss);
                 }
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index fe2a473..e1c7da9 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -30,6 +30,10 @@
 import static com.android.server.am.ActivityManagerService.DEBUG_VISBILITY;
 import static com.android.server.am.ActivityManagerService.VALIDATE_TOKENS;
 
+import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
+import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
+import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
+
 import static com.android.server.am.ActivityStackSupervisor.DEBUG_ADD_REMOVE;
 import static com.android.server.am.ActivityStackSupervisor.DEBUG_APP;
 import static com.android.server.am.ActivityStackSupervisor.DEBUG_CONTAINERS;
@@ -1095,7 +1099,8 @@
         for (int i = mStacks.indexOf(this) + 1; i < mStacks.size(); i++) {
             final ArrayList<TaskRecord> tasks = mStacks.get(i).getAllTasks();
             for (int taskNdx = 0; taskNdx < tasks.size(); taskNdx++) {
-                final ArrayList<ActivityRecord> activities = tasks.get(taskNdx).mActivities;
+                final TaskRecord task = tasks.get(taskNdx);
+                final ArrayList<ActivityRecord> activities = task.mActivities;
                 for (int activityNdx = 0; activityNdx < activities.size(); activityNdx++) {
                     final ActivityRecord r = activities.get(activityNdx);
 
@@ -1106,7 +1111,7 @@
                     // - Full Screen Activity OR
                     // - On top of Home and our stack is NOT home
                     if (!r.finishing && r.visible && (r.fullscreen ||
-                            (!isHomeStack() && r.frontOfTask && tasks.get(taskNdx).mOnTopOfHome))) {
+                            (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()))) {
                         return false;
                     }
                 }
@@ -1234,7 +1239,7 @@
                         // At this point, nothing else needs to be shown
                         if (DEBUG_VISBILITY) Slog.v(TAG, "Fullscreen: at " + r);
                         behindFullscreen = true;
-                    } else if (!isHomeStack() && r.frontOfTask && task.mOnTopOfHome) {
+                    } else if (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()) {
                         if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r);
                         behindFullscreen = true;
                     }
@@ -1388,6 +1393,7 @@
         final boolean userLeaving = mStackSupervisor.mUserLeaving;
         mStackSupervisor.mUserLeaving = false;
 
+        final TaskRecord prevTask = prev != null ? prev.task : null;
         if (next == null) {
             // There are no more activities!  Let's just start up the
             // Launcher...
@@ -1395,7 +1401,10 @@
             if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home");
             if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
             // Only resume home if on home display
-            return isOnHomeDisplay() && mStackSupervisor.resumeHomeActivity(prev);
+            final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
+                    HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
+            return isOnHomeDisplay() &&
+                    mStackSupervisor.resumeHomeStackTask(returnTaskType, prev);
         }
 
         next.delayedResume = false;
@@ -1414,22 +1423,24 @@
         }
 
         final TaskRecord nextTask = next.task;
-        final TaskRecord prevTask = prev != null ? prev.task : null;
         if (prevTask != null && prevTask.stack == this &&
-                prevTask.mOnTopOfHome && prev.finishing && prev.frontOfTask) {
+                prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) {
             if (DEBUG_STACK)  mStackSupervisor.validateTopActivitiesLocked();
             if (prevTask == nextTask) {
                 prevTask.setFrontOfTask();
             } else if (prevTask != topTask()) {
-                // This task is going away but it was supposed to return to the home task.
+                // This task is going away but it was supposed to return to the home stack.
                 // Now the task above it has to return to the home task instead.
                 final int taskNdx = mTaskHistory.indexOf(prevTask) + 1;
-                mTaskHistory.get(taskNdx).mOnTopOfHome = true;
+                mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE);
             } else {
                 if (DEBUG_STATES && isOnHomeDisplay()) Slog.d(TAG,
                         "resumeTopActivityLocked: Launching home next");
                 // Only resume home if on home display
-                return isOnHomeDisplay() && mStackSupervisor.resumeHomeActivity(prev);
+                final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
+                        HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
+                return isOnHomeDisplay() &&
+                        mStackSupervisor.resumeHomeStackTask(returnTaskType, prev);
             }
         }
 
@@ -1800,10 +1811,11 @@
             ActivityStack lastStack = mStackSupervisor.getLastStack();
             final boolean fromHome = lastStack.isHomeStack();
             if (!isHomeStack() && (fromHome || topTask() != task)) {
-                task.mOnTopOfHome = fromHome;
+                task.setTaskToReturnTo(fromHome ?
+                        lastStack.topTask().taskType : APPLICATION_ACTIVITY_TYPE);
             }
         } else {
-            task.mOnTopOfHome = false;
+            task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
         }
 
         mTaskHistory.remove(task);
@@ -2350,8 +2362,8 @@
             ActivityRecord next = topRunningActivityLocked(null);
             if (next != r) {
                 final TaskRecord task = r.task;
-                if (r.frontOfTask && task == topTask() && task.mOnTopOfHome) {
-                    mStackSupervisor.moveHomeToTop();
+                if (r.frontOfTask && task == topTask() && task.isOverHomeStack()) {
+                    mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo());
                 }
             }
             ActivityRecord top = mStackSupervisor.topRunningActivityLocked();
@@ -2843,8 +2855,9 @@
         if (task != null && task.removeActivity(r)) {
             if (DEBUG_STACK) Slog.i(TAG,
                     "removeActivityFromHistoryLocked: last activity removed from " + this);
-            if (mStackSupervisor.isFrontStack(this) && task == topTask() && task.mOnTopOfHome) {
-                mStackSupervisor.moveHomeToTop();
+            if (mStackSupervisor.isFrontStack(this) && task == topTask() &&
+                    task.isOverHomeStack()) {
+                mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo());
             }
             removeTask(task);
         }
@@ -3160,12 +3173,13 @@
         }
     }
 
-    void moveHomeTaskToTop() {
+    void moveHomeStackTaskToTop(int homeStackTaskType) {
         final int top = mTaskHistory.size() - 1;
         for (int taskNdx = top; taskNdx >= 0; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
-            if (task.isHomeTask()) {
-                if (DEBUG_TASKS || DEBUG_STACK) Slog.d(TAG, "moveHomeTaskToTop: moving " + task);
+            if (task.taskType == homeStackTaskType) {
+                if (DEBUG_TASKS || DEBUG_STACK)
+                    Slog.d(TAG, "moveHomeStackTaskToTop: moving " + task);
                 mTaskHistory.remove(taskNdx);
                 mTaskHistory.add(top, task);
                 updateTaskMovement(task, true);
@@ -3277,12 +3291,12 @@
         int numTasks = mTaskHistory.size();
         for (int taskNdx = numTasks - 1; taskNdx >= 1; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
-            if (task.mOnTopOfHome) {
+            if (task.isOverHomeStack()) {
                 break;
             }
             if (taskNdx == 1) {
                 // Set the last task before tr to go to home.
-                task.mOnTopOfHome = true;
+                task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
             }
         }
 
@@ -3303,9 +3317,10 @@
         }
 
         final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null;
-        if (task == tr && tr.mOnTopOfHome || numTasks <= 1 && isOnHomeDisplay()) {
-            tr.mOnTopOfHome = false;
-            return mStackSupervisor.resumeHomeActivity(null);
+        if (task == tr && tr.isOverHomeStack() || numTasks <= 1 && isOnHomeDisplay()) {
+            final int taskToReturnTo = tr.getTaskToReturnTo();
+            tr.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
+            return mStackSupervisor.resumeHomeStackTask(taskToReturnTo, null);
         }
 
         mStackSupervisor.resumeTopActivitiesLocked();
@@ -3746,8 +3761,11 @@
 
         final int taskNdx = mTaskHistory.indexOf(task);
         final int topTaskNdx = mTaskHistory.size() - 1;
-        if (task.mOnTopOfHome && taskNdx < topTaskNdx) {
-            mTaskHistory.get(taskNdx + 1).mOnTopOfHome = true;
+        if (task.isOverHomeStack() && taskNdx < topTaskNdx) {
+            final TaskRecord nextTask = mTaskHistory.get(taskNdx + 1);
+            if (!nextTask.isOverHomeStack()) {
+                nextTask.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
+            }
         }
         mTaskHistory.remove(task);
         updateTaskMovement(task, true);
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 4be208b..e7f5720 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -31,6 +31,9 @@
 import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING;
 import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
 import static com.android.server.am.ActivityManagerService.TAG;
+import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
+import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
+import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
 
 import android.app.Activity;
 import android.app.ActivityManager;
@@ -382,17 +385,27 @@
         }
     }
 
-    void moveHomeToTop() {
+    void moveHomeStackTaskToTop(int homeStackTaskType) {
+        if (homeStackTaskType == RECENTS_ACTIVITY_TYPE) {
+            mWindowManager.showRecentApps();
+            return;
+        }
         moveHomeStack(true);
-        mHomeStack.moveHomeTaskToTop();
+        mHomeStack.moveHomeStackTaskToTop(homeStackTaskType);
     }
 
-    boolean resumeHomeActivity(ActivityRecord prev) {
-        moveHomeToTop();
-        if (prev != null) {
-            prev.task.mOnTopOfHome = false;
+    boolean resumeHomeStackTask(int homeStackTaskType, ActivityRecord prev) {
+        if (homeStackTaskType == RECENTS_ACTIVITY_TYPE) {
+            mWindowManager.showRecentApps();
+            return false;
         }
+        moveHomeStackTaskToTop(homeStackTaskType);
+        if (prev != null) {
+            prev.task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
+        }
+
         ActivityRecord r = mHomeStack.topRunningActivityLocked(null);
+        // if (r != null && (r.isHomeActivity() || r.isRecentsActivity())) {
         if (r != null && r.isHomeActivity()) {
             mService.setFocusedActivityLocked(r);
             return resumeTopActivitiesLocked(mHomeStack, prev, null);
@@ -747,7 +760,7 @@
     }
 
     void startHomeActivity(Intent intent, ActivityInfo aInfo) {
-        moveHomeToTop();
+        moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE);
         startActivityLocked(null, intent, null, aInfo, null, null, null, null, 0, 0, 0, null, 0,
                 null, false, null, null);
     }
@@ -1697,7 +1710,7 @@
                                     (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
                                     == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
                                 // Caller wants to appear on home activity.
-                                intentActivity.task.mOnTopOfHome = true;
+                                intentActivity.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
                             }
                             options = null;
                         }
@@ -1893,7 +1906,7 @@
                         == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
                     // Caller wants to appear on home activity, so before starting
                     // their own activity we will bring home to the front.
-                    r.task.mOnTopOfHome = r.task.stack.isOnHomeDisplay();
+                    r.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
                 }
             }
         } else if (sourceRecord != null) {
@@ -1968,6 +1981,9 @@
         mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
                 intent, r.getUriPermissionsLocked(), r.userId);
 
+        if (sourceRecord != null && sourceRecord.isRecentsActivity()) {
+            r.task.setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
+        }
         if (newTask) {
             EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
         }
@@ -2244,7 +2260,7 @@
         if ((flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
             // Caller wants the home activity moved with it.  To accomplish this,
             // we'll just indicate that this task returns to the home task.
-            task.mOnTopOfHome = true;
+            task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
         }
         task.stack.moveTaskToFrontLocked(task, null, options);
         if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack="
@@ -2356,7 +2372,7 @@
             }
             mWindowManager.addTask(taskId, stackId, false);
         }
-        resumeHomeActivity(null);
+        resumeHomeStackTask(HOME_ACTIVITY_TYPE, null);
     }
 
     void moveTaskToStack(int taskId, int stackId, boolean toTop) {
@@ -2618,7 +2634,7 @@
             }
         } else {
             // Stack was moved to another display while user was swapped out.
-            resumeHomeActivity(null);
+            resumeHomeStackTask(HOME_ACTIVITY_TYPE, null);
         }
         return homeInFront;
     }
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 65d6e2f..a301c4b 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -17,6 +17,9 @@
 package com.android.server.am;
 
 import static com.android.server.am.ActivityManagerService.TAG;
+import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
+import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
+import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityStackSupervisor.DEBUG_ADD_REMOVE;
 
 import android.app.Activity;
@@ -53,7 +56,6 @@
     private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode";
     private static final String ATTR_USERID = "user_id";
     private static final String ATTR_TASKTYPE = "task_type";
-    private static final String ATTR_ONTOPOFHOME = "on_top_of_home";
     private static final String ATTR_LASTDESCRIPTION = "last_description";
     private static final String ATTR_LASTTIMEMOVED = "last_time_moved";
     private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity";
@@ -107,9 +109,10 @@
     /** True if persistable, has changed, and has not yet been persisted */
     boolean needsPersisting = false;
 
-    /** Launch the home activity when leaving this task. Will be false for tasks that are not on
-     * Display.DEFAULT_DISPLAY. */
-    boolean mOnTopOfHome = false;
+    /** Indication of what to run next when task exits. Use ActivityRecord types.
+     * ActivityRecord.APPLICATION_ACTIVITY_TYPE indicates to resume the task below this one in the
+     * task stack. */
+    private int mTaskToReturnTo = APPLICATION_ACTIVITY_TYPE;
 
     /** If original intent did not allow relinquishing task identity, save that information */
     boolean mNeverRelinquishIdentity = true;
@@ -132,9 +135,9 @@
 
     TaskRecord(ActivityManagerService service, int _taskId, Intent _intent, Intent _affinityIntent,
             String _affinity, ComponentName _realActivity, ComponentName _origActivity,
-            boolean _rootWasReset, boolean _askedCompatMode, int _taskType, boolean _onTopOfHome,
-            int _userId, String _lastDescription, ArrayList<ActivityRecord> activities,
-            long lastTimeMoved, boolean neverRelinquishIdentity) {
+            boolean _rootWasReset, boolean _askedCompatMode, int _taskType, int _userId,
+            String _lastDescription, ArrayList<ActivityRecord> activities, long lastTimeMoved,
+            boolean neverRelinquishIdentity) {
         mService = service;
         taskId = _taskId;
         intent = _intent;
@@ -147,7 +150,7 @@
         rootWasReset = _rootWasReset;
         askedCompatMode = _askedCompatMode;
         taskType = _taskType;
-        mOnTopOfHome = _onTopOfHome;
+        mTaskToReturnTo = HOME_ACTIVITY_TYPE;
         userId = _userId;
         lastDescription = _lastDescription;
         mActivities = activities;
@@ -224,6 +227,14 @@
         }
     }
 
+    void setTaskToReturnTo(int taskToReturnTo) {
+        mTaskToReturnTo = taskToReturnTo;
+    }
+
+    int getTaskToReturnTo() {
+        return mTaskToReturnTo;
+    }
+
     void disposeThumbnail() {
         super.disposeThumbnail();
         for (int i=mActivities.size()-1; i>=0; i--) {
@@ -286,6 +297,11 @@
                 foundFront = true;
             }
         }
+        if (!foundFront && numActivities > 0) {
+            // All activities of this task are finishing. As we ought to have a frontOfTask
+            // activity, make the bottom activity front.
+            mActivities.get(0).frontOfTask = true;
+        }
     }
 
     /**
@@ -509,11 +525,15 @@
     }
 
     boolean isHomeTask() {
-        return taskType == ActivityRecord.HOME_ACTIVITY_TYPE;
+        return taskType == HOME_ACTIVITY_TYPE;
     }
 
     boolean isApplicationTask() {
-        return taskType == ActivityRecord.APPLICATION_ACTIVITY_TYPE;
+        return taskType == APPLICATION_ACTIVITY_TYPE;
+    }
+
+    boolean isOverHomeStack() {
+        return mTaskToReturnTo == HOME_ACTIVITY_TYPE || mTaskToReturnTo == RECENTS_ACTIVITY_TYPE;
     }
 
     public TaskAccessInfo getTaskAccessInfoLocked() {
@@ -683,7 +703,6 @@
         out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode));
         out.attribute(null, ATTR_USERID, String.valueOf(userId));
         out.attribute(null, ATTR_TASKTYPE, String.valueOf(taskType));
-        out.attribute(null, ATTR_ONTOPOFHOME, String.valueOf(mOnTopOfHome));
         out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved));
         out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity));
         if (lastDescription != null) {
@@ -732,7 +751,6 @@
         boolean rootHasReset = false;
         boolean askedCompatMode = false;
         int taskType = ActivityRecord.APPLICATION_ACTIVITY_TYPE;
-        boolean onTopOfHome = true;
         int userId = 0;
         String lastDescription = null;
         long lastTimeOnTop = 0;
@@ -761,8 +779,6 @@
                 userId = Integer.valueOf(attrValue);
             } else if (ATTR_TASKTYPE.equals(attrName)) {
                 taskType = Integer.valueOf(attrValue);
-            } else if (ATTR_ONTOPOFHOME.equals(attrName)) {
-                onTopOfHome = Boolean.valueOf(attrValue);
             } else if (ATTR_LASTDESCRIPTION.equals(attrName)) {
                 lastDescription = attrValue;
             } else if (ATTR_LASTTIMEMOVED.equals(attrName)) {
@@ -802,8 +818,8 @@
 
         final TaskRecord task = new TaskRecord(stackSupervisor.mService, taskId, intent,
                 affinityIntent, affinity, realActivity, origActivity, rootHasReset,
-                askedCompatMode, taskType, onTopOfHome, userId, lastDescription, activities,
-                lastTimeOnTop, neverRelinquishIdentity);
+                askedCompatMode, taskType, userId, lastDescription, activities, lastTimeOnTop,
+                neverRelinquishIdentity);
 
         for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
             final ActivityRecord r = activities.get(activityNdx);
@@ -822,7 +838,7 @@
                     pw.print(" userId="); pw.print(userId);
                     pw.print(" taskType="); pw.print(taskType);
                     pw.print(" numFullscreen="); pw.print(numFullscreen);
-                    pw.print(" mOnTopOfHome="); pw.println(mOnTopOfHome);
+                    pw.print(" mTaskToReturnTo="); pw.println(mTaskToReturnTo);
         }
         if (affinity != null) {
             pw.print(prefix); pw.print("affinity="); pw.println(affinity);
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index b03c247..1332898 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -78,6 +78,6 @@
 
     public String name() {
         return "NetworkAgentInfo [" + networkInfo.getTypeName() + " (" +
-                networkInfo.getSubtypeName() + ")]";
+                networkInfo.getSubtypeName() + ") - " + network.toString() + "]";
     }
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiAnnotations.java b/services/core/java/com/android/server/hdmi/HdmiAnnotations.java
new file mode 100644
index 0000000..969595d
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/HdmiAnnotations.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+package com.android.server.hdmi;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation container for Hdmi control service package.
+ */
+public class HdmiAnnotations {
+    /**
+     * Annotation type to used to mark a method which should be run on service thread.
+     * This annotation should go with {@code assertRunOnServiceThread} used to verify
+     * whether it's called from service thread.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.METHOD)
+    public @interface ServiceThreadOnly {
+    }
+
+    /**
+     * Annotation type to used to mark a method which should be run on io thread.
+     * This annotation should go with {@code assertRunOnIoThread} used to verify
+     * whether it's called from io thread.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.METHOD)
+    public @interface IoThreadOnly {
+    }
+}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index 6d05e82..4fbe845 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -26,6 +26,8 @@
 import android.util.SparseArray;
 
 import com.android.internal.util.Predicate;
+import com.android.server.hdmi.HdmiAnnotations.IoThreadOnly;
+import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
 import com.android.server.hdmi.HdmiControlService.DevicePollingCallback;
 
 import libcore.util.EmptyArray;
@@ -144,7 +146,9 @@
         mNativePtr = nativePtr;
     }
 
+    @ServiceThreadOnly
     void addLocalDevice(int deviceType, HdmiCecLocalDevice device) {
+        assertRunOnServiceThread();
         mLocalDevices.put(deviceType, device);
     }
 
@@ -161,6 +165,7 @@
      *                         Otherwise, scan address will start from {@code preferredAddress}
      * @param callback callback interface to report allocated logical address to caller
      */
+    @ServiceThreadOnly
     void allocateLogicalAddress(final int deviceType, final int preferredAddress,
             final AllocateAddressCallback callback) {
         assertRunOnServiceThread();
@@ -173,6 +178,7 @@
         });
     }
 
+    @IoThreadOnly
     private void handleAllocateLogicalAddress(final int deviceType, int preferredAddress,
             final AllocateAddressCallback callback) {
         assertRunOnIoThread();
@@ -245,6 +251,7 @@
      * @param newLogicalAddress a logical address to be added
      * @return 0 on success. Otherwise, returns negative value
      */
+    @ServiceThreadOnly
     int addLogicalAddress(int newLogicalAddress) {
         assertRunOnServiceThread();
         if (HdmiCec.isValidAddress(newLogicalAddress)) {
@@ -259,6 +266,7 @@
      *
      * <p>Declared as package-private. accessed by {@link HdmiControlService} only.
      */
+    @ServiceThreadOnly
     void clearLogicalAddress() {
         assertRunOnServiceThread();
         // TODO: consider to backup logical address so that new logical address
@@ -277,6 +285,7 @@
      * @return CEC physical address of the device. The range of success address
      *         is between 0x0000 and 0xFFFF. If failed it returns -1
      */
+    @ServiceThreadOnly
     int getPhysicalAddress() {
         assertRunOnServiceThread();
         return nativeGetPhysicalAddress(mNativePtr);
@@ -287,6 +296,7 @@
      *
      * <p>Declared as package-private. accessed by {@link HdmiControlService} only.
      */
+    @ServiceThreadOnly
     int getVersion() {
         assertRunOnServiceThread();
         return nativeGetVersion(mNativePtr);
@@ -297,6 +307,7 @@
      *
      * <p>Declared as package-private. accessed by {@link HdmiControlService} only.
      */
+    @ServiceThreadOnly
     int getVendorId() {
         assertRunOnServiceThread();
         return nativeGetVendorId(mNativePtr);
@@ -311,6 +322,7 @@
      * @param value a value of option. Actual value varies flag. For more
      *        details, look at description of flags
      */
+    @ServiceThreadOnly
     void setOption(int flag, int value) {
         assertRunOnServiceThread();
         nativeSetOption(mNativePtr, flag, value);
@@ -321,6 +333,7 @@
      *
      * @param enabled whether to enable/disable ARC
      */
+    @ServiceThreadOnly
     void setAudioReturnChannel(boolean enabled) {
         assertRunOnServiceThread();
         nativeSetAudioReturnChannel(mNativePtr, enabled);
@@ -332,6 +345,7 @@
      * @param port port number to check connection status
      * @return true if connected; otherwise, return false
      */
+    @ServiceThreadOnly
     boolean isConnected(int port) {
         assertRunOnServiceThread();
         return nativeIsConnected(mNativePtr, port);
@@ -347,6 +361,7 @@
      * @param pickStrategy strategy how to pick polling candidates
      * @param retryCount the number of retry used to send polling message to remote devices
      */
+    @ServiceThreadOnly
     void pollDevices(DevicePollingCallback callback, int pickStrategy, int retryCount) {
         assertRunOnServiceThread();
 
@@ -360,6 +375,7 @@
      *
      * <p>Declared as package-private. accessed by {@link HdmiControlService} only.
      */
+    @ServiceThreadOnly
     List<HdmiCecLocalDevice> getLocalDeviceList() {
         assertRunOnServiceThread();
         return HdmiUtils.sparseArrayToList(mLocalDevices);
@@ -400,7 +416,9 @@
         return pollingCandidates;
     }
 
+    @ServiceThreadOnly
     private boolean isAllocatedLocalDeviceAddress(int address) {
+        assertRunOnServiceThread();
         for (int i = 0; i < mLocalDevices.size(); ++i) {
             if (mLocalDevices.valueAt(i).isAddressOf(address)) {
                 return true;
@@ -409,6 +427,7 @@
         return false;
     }
 
+    @ServiceThreadOnly
     private void runDevicePolling(final List<Integer> candidates, final int retryCount,
             final DevicePollingCallback callback) {
         assertRunOnServiceThread();
@@ -433,6 +452,7 @@
         });
     }
 
+    @IoThreadOnly
     private boolean sendPollMessage(int address, int retryCount) {
         assertRunOnIoThread();
         for (int i = 0; i < retryCount; ++i) {
@@ -480,6 +500,7 @@
         return isAllocatedLocalDeviceAddress(address);
     }
 
+    @ServiceThreadOnly
     private void onReceiveCommand(HdmiCecMessage message) {
         assertRunOnServiceThread();
         if (isAcceptableAddress(message.getDestination())
@@ -493,16 +514,20 @@
             HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildFeatureAbortCommand(
                     sourceAddress, message.getSource(), message.getOpcode(),
                     HdmiConstants.ABORT_REFUSED);
-            sendCommand(cecMessage, null);
+            sendCommand(cecMessage);
         }
     }
 
+    @ServiceThreadOnly
     void sendCommand(HdmiCecMessage cecMessage) {
+        assertRunOnServiceThread();
         sendCommand(cecMessage, null);
     }
 
+    @ServiceThreadOnly
     void sendCommand(final HdmiCecMessage cecMessage,
             final HdmiControlService.SendMessageCallback callback) {
+        assertRunOnServiceThread();
         runOnIoThread(new Runnable() {
             @Override
             public void run() {
@@ -527,6 +552,7 @@
     /**
      * Called by native when incoming CEC message arrived.
      */
+    @ServiceThreadOnly
     private void handleIncomingCecCommand(int srcAddress, int dstAddress, byte[] body) {
         assertRunOnServiceThread();
         onReceiveCommand(HdmiCecMessageBuilder.of(srcAddress, dstAddress, body));
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
index f86d655..6f7f5c2 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevice.java
@@ -23,6 +23,7 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
 
 import java.util.ArrayList;
 import java.util.Iterator;
@@ -87,7 +88,9 @@
         }
     }
 
+    @ServiceThreadOnly
     void init() {
+        assertRunOnServiceThread();
         mPreferredAddress = HdmiCec.ADDR_UNREGISTERED;
         // TODO: load preferred address from permanent storage.
     }
@@ -103,9 +106,9 @@
      * @param message incoming message
      * @return true if consumed a message; otherwise, return false.
      */
+    @ServiceThreadOnly
     final boolean dispatchMessage(HdmiCecMessage message) {
         assertRunOnServiceThread();
-
         int dest = message.getDestination();
         if (dest != mAddress && dest != HdmiCec.ADDR_BROADCAST) {
             return false;
@@ -115,9 +118,9 @@
         return onMessage(message);
     }
 
+    @ServiceThreadOnly
     protected final boolean onMessage(HdmiCecMessage message) {
         assertRunOnServiceThread();
-
         if (dispatchMessageToAction(message)) {
             return true;
         }
@@ -147,7 +150,9 @@
         }
     }
 
+    @ServiceThreadOnly
     private boolean dispatchMessageToAction(HdmiCecMessage message) {
+        assertRunOnServiceThread();
         for (FeatureAction action : mActions) {
             if (action.processCommand(message)) {
                 return true;
@@ -156,6 +161,7 @@
         return false;
     }
 
+    @ServiceThreadOnly
     protected boolean handleGivePhysicalAddress() {
         assertRunOnServiceThread();
 
@@ -166,9 +172,9 @@
         return true;
     }
 
+    @ServiceThreadOnly
     protected boolean handleGiveDeviceVendorId() {
         assertRunOnServiceThread();
-
         int vendorId = mService.getVendorId();
         HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildDeviceVendorIdCommand(
                 mAddress, vendorId);
@@ -176,9 +182,9 @@
         return true;
     }
 
+    @ServiceThreadOnly
     protected boolean handleGetCecVersion(HdmiCecMessage message) {
         assertRunOnServiceThread();
-
         int version = mService.getCecVersion();
         HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildCecVersion(message.getDestination(),
                 message.getSource(), version);
@@ -186,9 +192,9 @@
         return true;
     }
 
+    @ServiceThreadOnly
     protected boolean handleGetMenuLanguage(HdmiCecMessage message) {
         assertRunOnServiceThread();
-
         Slog.w(TAG, "Only TV can handle <Get Menu Language>:" + message.toString());
         mService.sendCecCommand(
                 HdmiCecMessageBuilder.buildFeatureAbortCommand(mAddress,
@@ -197,9 +203,9 @@
         return true;
     }
 
+    @ServiceThreadOnly
     protected boolean handleGiveOsdName(HdmiCecMessage message) {
         assertRunOnServiceThread();
-
         // Note that since this method is called after logical address allocation is done,
         // mDeviceInfo should not be null.
         HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildSetOsdNameCommand(
@@ -236,45 +242,52 @@
         return false;
     }
 
+    @ServiceThreadOnly
     final void handleAddressAllocated(int logicalAddress) {
         assertRunOnServiceThread();
-
         mAddress = mPreferredAddress = logicalAddress;
         onAddressAllocated(logicalAddress);
     }
 
+    @ServiceThreadOnly
     HdmiCecDeviceInfo getDeviceInfo() {
         assertRunOnServiceThread();
         return mDeviceInfo;
     }
 
+    @ServiceThreadOnly
     void setDeviceInfo(HdmiCecDeviceInfo info) {
         assertRunOnServiceThread();
         mDeviceInfo = info;
     }
 
     // Returns true if the logical address is same as the argument.
+    @ServiceThreadOnly
     boolean isAddressOf(int addr) {
         assertRunOnServiceThread();
         return addr == mAddress;
     }
 
     // Resets the logical address to unregistered(15), meaning the logical device is invalid.
+    @ServiceThreadOnly
     void clearAddress() {
         assertRunOnServiceThread();
         mAddress = HdmiCec.ADDR_UNREGISTERED;
     }
 
+    @ServiceThreadOnly
     void setPreferredAddress(int addr) {
         assertRunOnServiceThread();
         mPreferredAddress = addr;
     }
 
+    @ServiceThreadOnly
     int getPreferredAddress() {
         assertRunOnServiceThread();
         return mPreferredAddress;
     }
 
+    @ServiceThreadOnly
     void addAndStartAction(final FeatureAction action) {
         assertRunOnServiceThread();
         mActions.add(action);
@@ -282,6 +295,7 @@
     }
 
     // See if we have an action of a given type in progress.
+    @ServiceThreadOnly
     <T extends FeatureAction> boolean hasAction(final Class<T> clazz) {
         assertRunOnServiceThread();
         for (FeatureAction action : mActions) {
@@ -293,6 +307,7 @@
     }
 
     // Returns all actions matched with given class type.
+    @ServiceThreadOnly
     <T extends FeatureAction> List<T> getActions(final Class<T> clazz) {
         assertRunOnServiceThread();
         ArrayList<T> actions = new ArrayList<>();
@@ -309,17 +324,21 @@
      *
      * @param action {@link FeatureAction} to remove
      */
+    @ServiceThreadOnly
     void removeAction(final FeatureAction action) {
         assertRunOnServiceThread();
         mActions.remove(action);
     }
 
     // Remove all actions matched with the given Class type.
+    @ServiceThreadOnly
     <T extends FeatureAction> void removeAction(final Class<T> clazz) {
+        assertRunOnServiceThread();
         removeActionExcept(clazz, null);
     }
 
     // Remove all actions matched with the given Class type besides |exception|.
+    @ServiceThreadOnly
     <T extends FeatureAction> void removeActionExcept(final Class<T> clazz,
             final FeatureAction exception) {
         assertRunOnServiceThread();
@@ -352,7 +371,9 @@
         return mService;
     }
 
+    @ServiceThreadOnly
     final boolean isConnectedToArcPort(int path) {
+        assertRunOnServiceThread();
         return mService.isConnectedToArcPort(path);
     }
 
@@ -442,11 +463,13 @@
         }
     }
 
+    @ServiceThreadOnly
     HdmiCecMessageCache getCecMessageCache() {
         assertRunOnServiceThread();
         return mCecMessageCache;
     }
 
+    @ServiceThreadOnly
     int pathToPortId(int newPath) {
         assertRunOnServiceThread();
         return mService.pathToPortId(newPath);
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index 01345ef..d7e36b3 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -21,6 +21,8 @@
 import android.os.RemoteException;
 import android.util.Slog;
 
+import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
+
 /**
  * Represent a logical device of type Playback residing in Android system.
  */
@@ -32,11 +34,14 @@
     }
 
     @Override
+    @ServiceThreadOnly
     protected void onAddressAllocated(int logicalAddress) {
+        assertRunOnServiceThread();
         mService.sendCecCommand(HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
                 mAddress, mService.getPhysicalAddress(), mDeviceType));
     }
 
+    @ServiceThreadOnly
     void oneTouchPlay(IHdmiControlCallback callback) {
         assertRunOnServiceThread();
         if (hasAction(OneTouchPlayAction.class)) {
@@ -56,6 +61,7 @@
         addAndStartAction(action);
     }
 
+    @ServiceThreadOnly
     void queryDisplayStatus(IHdmiControlCallback callback) {
         assertRunOnServiceThread();
         if (hasAction(DevicePowerStatusAction.class)) {
@@ -73,7 +79,9 @@
         addAndStartAction(action);
     }
 
+    @ServiceThreadOnly
     private void invokeCallback(IHdmiControlCallback callback, int result) {
+        assertRunOnServiceThread();
         try {
             callback.onComplete(result);
         } catch (RemoteException e) {
@@ -82,7 +90,9 @@
     }
 
     @Override
+    @ServiceThreadOnly
     void onHotplug(int portId, boolean connected) {
+        assertRunOnServiceThread();
         // TODO: clear devices connected to the given port id.
         mCecMessageCache.flushAll();
     }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 420304e..2b53895 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -26,6 +26,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.server.hdmi.DeviceDiscoveryAction.DeviceDiscoveryCallback;
+import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -42,12 +43,21 @@
     @GuardedBy("mLock")
     private boolean mArcStatusEnabled = false;
 
-    @GuardedBy("mLock")
     // Whether SystemAudioMode is "On" or not.
+    @GuardedBy("mLock")
     private boolean mSystemAudioMode;
 
+
+    // Copy of mDeviceInfos to guarantee thread-safety.
+    @GuardedBy("mLock")
+    private List<HdmiCecDeviceInfo> mSafeAllDeviceInfos = Collections.emptyList();
+    // All external cec device which excludes local devices.
+    @GuardedBy("mLock")
+    private List<HdmiCecDeviceInfo> mSafeExternalDeviceInfos = Collections.emptyList();
+
     // Map-like container of all cec devices including local ones.
     // A logical address of device is used as key of container.
+    // This is not thread-safe. For external purpose use mSafeDeviceInfos.
     private final SparseArray<HdmiCecDeviceInfo> mDeviceInfos = new SparseArray<>();
 
     HdmiCecLocalDeviceTv(HdmiControlService service) {
@@ -57,6 +67,7 @@
     }
 
     @Override
+    @ServiceThreadOnly
     protected void onAddressAllocated(int logicalAddress) {
         assertRunOnServiceThread();
         // TODO: vendor-specific initialization here.
@@ -67,7 +78,7 @@
                 mAddress, mService.getVendorId()));
 
         launchDeviceDiscovery();
-        // TODO: Start routing control action, device discovery action.
+        // TODO: Start routing control action
     }
 
     /**
@@ -76,6 +87,7 @@
      * @param targetAddress logical address of the device to select
      * @param callback callback object to report the result with
      */
+    @ServiceThreadOnly
     void deviceSelect(int targetAddress, IHdmiControlCallback callback) {
         assertRunOnServiceThread();
         HdmiCecDeviceInfo targetDevice = getDeviceInfo(targetAddress);
@@ -93,6 +105,7 @@
      * @param portId new HDMI port to route to
      * @param callback callback object to report the result with
      */
+    @ServiceThreadOnly
     void portSelect(int portId, IHdmiControlCallback callback) {
         assertRunOnServiceThread();
         if (isInPresetInstallationMode()) {
@@ -124,9 +137,10 @@
     /**
      * Sends key to a target CEC device.
      *
-     * @param keyCode key code to send. Defined in {@link KeyEvent}.
+     * @param keyCode key code to send. Defined in {@link android.view.KeyEvent}.
      * @param isPressed true if this is keypress event
      */
+    @ServiceThreadOnly
     void sendKeyEvent(int keyCode, boolean isPressed) {
         assertRunOnServiceThread();
         List<SendKeyAction> action = getActions(SendKeyAction.class);
@@ -153,6 +167,7 @@
     }
 
     @Override
+    @ServiceThreadOnly
     protected boolean handleGetMenuLanguage(HdmiCecMessage message) {
         assertRunOnServiceThread();
         HdmiCecMessage command = HdmiCecMessageBuilder.buildSetMenuLanguageCommand(
@@ -167,6 +182,7 @@
     }
 
     @Override
+    @ServiceThreadOnly
     protected boolean handleReportPhysicalAddress(HdmiCecMessage message) {
         assertRunOnServiceThread();
         // Ignore if [Device Discovery Action] is going on.
@@ -189,6 +205,7 @@
     }
 
     @Override
+    @ServiceThreadOnly
     protected boolean handleVendorSpecificCommand(HdmiCecMessage message) {
         assertRunOnServiceThread();
         List<VendorSpecificAction> actions = Collections.emptyList();
@@ -214,6 +231,7 @@
         return true;
     }
 
+    @ServiceThreadOnly
     private void launchDeviceDiscovery() {
         assertRunOnServiceThread();
         clearDeviceInfoList();
@@ -248,11 +266,14 @@
     }
 
     // Clear all device info.
+    @ServiceThreadOnly
     private void clearDeviceInfoList() {
         assertRunOnServiceThread();
         mDeviceInfos.clear();
+        updateSafeDeviceInfoList();
     }
 
+    @ServiceThreadOnly
     void changeSystemAudioMode(boolean enabled, IHdmiControlCallback callback) {
         assertRunOnServiceThread();
         HdmiCecDeviceInfo avr = getAvrDeviceInfo();
@@ -263,11 +284,6 @@
 
         addAndStartAction(
                 new SystemAudioActionFromTv(this, avr.getLogicalAddress(), enabled, callback));
-   }
-
-    boolean canChangeSystemAudioMode() {
-        // TODO: once have immutable device info, test whether avr info exists or not.
-        return false;
     }
 
     void setSystemAudioMode(boolean on) {
@@ -314,11 +330,13 @@
         }
     }
 
+    @ServiceThreadOnly
     void setAudioStatus(boolean mute, int volume) {
         mService.setAudioStatus(mute, volume);
     }
 
     @Override
+    @ServiceThreadOnly
     protected boolean handleInitiateArc(HdmiCecMessage message) {
         assertRunOnServiceThread();
         // In case where <Initiate Arc> is started by <Request ARC Initiation>
@@ -331,6 +349,7 @@
     }
 
     @Override
+    @ServiceThreadOnly
     protected boolean handleTerminateArc(HdmiCecMessage message) {
         assertRunOnServiceThread();
         // In case where <Terminate Arc> is started by <Request ARC Termination>
@@ -345,6 +364,7 @@
     }
 
     @Override
+    @ServiceThreadOnly
     protected boolean handleSetSystemAudioMode(HdmiCecMessage message) {
         assertRunOnServiceThread();
         if (!isMessageForSystemAudio(message)) {
@@ -357,6 +377,7 @@
     }
 
     @Override
+    @ServiceThreadOnly
     protected boolean handleSystemAudioModeStatus(HdmiCecMessage message) {
         assertRunOnServiceThread();
         if (!isMessageForSystemAudio(message)) {
@@ -386,6 +407,7 @@
      * @return {@code null} if it is new device. Otherwise, returns old {@HdmiCecDeviceInfo}
      *         that has the same logical address as new one has.
      */
+    @ServiceThreadOnly
     HdmiCecDeviceInfo addDeviceInfo(HdmiCecDeviceInfo deviceInfo) {
         assertRunOnServiceThread();
         HdmiCecDeviceInfo oldDeviceInfo = getDeviceInfo(deviceInfo.getLogicalAddress());
@@ -393,6 +415,7 @@
             removeDeviceInfo(deviceInfo.getLogicalAddress());
         }
         mDeviceInfos.append(deviceInfo.getLogicalAddress(), deviceInfo);
+        updateSafeDeviceInfoList();
         return oldDeviceInfo;
     }
 
@@ -405,12 +428,14 @@
      * @param logicalAddress logical address of device to be removed
      * @return removed {@link HdmiCecDeviceInfo} it exists. Otherwise, returns {@code null}
      */
+    @ServiceThreadOnly
     HdmiCecDeviceInfo removeDeviceInfo(int logicalAddress) {
         assertRunOnServiceThread();
         HdmiCecDeviceInfo deviceInfo = mDeviceInfos.get(logicalAddress);
         if (deviceInfo != null) {
             mDeviceInfos.remove(logicalAddress);
         }
+        updateSafeDeviceInfoList();
         return deviceInfo;
     }
 
@@ -418,13 +443,14 @@
      * Return a list of all {@link HdmiCecDeviceInfo}.
      *
      * <p>Declared as package-private. accessed by {@link HdmiControlService} only.
+     * This is not thread-safe. For thread safety, call {@link #getSafeDeviceInfoList(boolean)}.
      */
+    @ServiceThreadOnly
     List<HdmiCecDeviceInfo> getDeviceInfoList(boolean includelLocalDevice) {
         assertRunOnServiceThread();
         if (includelLocalDevice) {
-                return HdmiUtils.sparseArrayToList(mDeviceInfos);
+            return HdmiUtils.sparseArrayToList(mDeviceInfos);
         } else {
-
             ArrayList<HdmiCecDeviceInfo> infoList = new ArrayList<>();
             for (int i = 0; i < mDeviceInfos.size(); ++i) {
                 HdmiCecDeviceInfo info = mDeviceInfos.valueAt(i);
@@ -436,6 +462,33 @@
         }
     }
 
+    /**
+     * Return a list of  {@link HdmiCecDeviceInfo}.
+     *
+     * @param includeLocalDevice whether to include local device in result.
+     */
+    List<HdmiCecDeviceInfo> getSafeDeviceInfoList(boolean includeLocalDevice) {
+        synchronized (mLock) {
+            if (includeLocalDevice) {
+                return mSafeAllDeviceInfos;
+            } else {
+                return mSafeExternalDeviceInfos;
+            }
+        }
+    }
+
+    @ServiceThreadOnly
+    private void updateSafeDeviceInfoList() {
+        assertRunOnServiceThread();
+        List<HdmiCecDeviceInfo> copiedDevices = HdmiUtils.sparseArrayToList(mDeviceInfos);
+        List<HdmiCecDeviceInfo> externalDeviceInfos = getDeviceInfoList(false);
+        synchronized (mLock) {
+            mSafeAllDeviceInfos = copiedDevices;
+            mSafeExternalDeviceInfos = externalDeviceInfos;
+        }
+    }
+
+    @ServiceThreadOnly
     private boolean isLocalDeviceAddress(int address) {
         assertRunOnServiceThread();
         for (HdmiCecLocalDevice device : mService.getAllLocalDevices()) {
@@ -446,23 +499,47 @@
         return false;
     }
 
+    @ServiceThreadOnly
+    HdmiCecDeviceInfo getAvrDeviceInfo() {
+        assertRunOnServiceThread();
+        return getDeviceInfo(HdmiCec.ADDR_AUDIO_SYSTEM);
+    }
+
     /**
      * Return a {@link HdmiCecDeviceInfo} corresponding to the given {@code logicalAddress}.
      *
      * <p>Declared as package-private. accessed by {@link HdmiControlService} only.
+     * This is not thread-safe. For thread safety, call {@link #getSafeDeviceInfo(int)}.
      *
      * @param logicalAddress logical address to be retrieved
      * @return {@link HdmiCecDeviceInfo} matched with the given {@code logicalAddress}.
      *         Returns null if no logical address matched
      */
+    @ServiceThreadOnly
     HdmiCecDeviceInfo getDeviceInfo(int logicalAddress) {
         assertRunOnServiceThread();
         return mDeviceInfos.get(logicalAddress);
     }
 
-    HdmiCecDeviceInfo getAvrDeviceInfo() {
-        assertRunOnServiceThread();
-        return getDeviceInfo(HdmiCec.ADDR_AUDIO_SYSTEM);
+    boolean hasSystemAudioDevice() {
+        return getSafeAvrDeviceInfo() != null;
+    }
+
+    HdmiCecDeviceInfo getSafeAvrDeviceInfo() {
+        return getSafeDeviceInfo(HdmiCec.ADDR_AUDIO_SYSTEM);
+    }
+
+    /**
+     * Thread safe version of {@link #getDeviceInfo(int)}.
+     *
+     * @param logicalAddress logical address to be retrieved
+     * @return {@link HdmiCecDeviceInfo} matched with the given {@code logicalAddress}.
+     *         Returns null if no logical address matched
+     */
+    HdmiCecDeviceInfo getSafeDeviceInfo(int logicalAddress) {
+        synchronized (mLock) {
+            return mSafeAllDeviceInfos.get(logicalAddress);
+        }
     }
 
     /**
@@ -470,6 +547,7 @@
      *
      * @param info device info of a new device.
      */
+    @ServiceThreadOnly
     final void addCecDevice(HdmiCecDeviceInfo info) {
         assertRunOnServiceThread();
         addDeviceInfo(info);
@@ -485,6 +563,7 @@
      *
      * @param address a logical address of a device to be removed
      */
+    @ServiceThreadOnly
     final void removeCecDevice(int address) {
         assertRunOnServiceThread();
         HdmiCecDeviceInfo info = removeDeviceInfo(address);
@@ -500,6 +579,7 @@
      * @param path routing path or physical address
      * @return {@link HdmiCecDeviceInfo} if the matched info is found; otherwise null
      */
+    @ServiceThreadOnly
     final HdmiCecDeviceInfo getDeviceInfoByPath(int path) {
         assertRunOnServiceThread();
         for (HdmiCecDeviceInfo info : getDeviceInfoList(false)) {
@@ -519,6 +599,7 @@
      * @param logicalAddress logical address of a device to be searched
      * @return true if exist; otherwise false
      */
+    @ServiceThreadOnly
     boolean isInDeviceList(int physicalAddress, int logicalAddress) {
         assertRunOnServiceThread();
         HdmiCecDeviceInfo device = getDeviceInfo(logicalAddress);
@@ -529,6 +610,7 @@
     }
 
     @Override
+    @ServiceThreadOnly
     void onHotplug(int portNo, boolean connected) {
         assertRunOnServiceThread();
         // TODO: delegate onHotplug event to each local device.
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 7774878..1a18c10 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -40,6 +40,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.server.SystemService;
+import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
 import com.android.server.hdmi.HdmiCecController.AllocateAddressCallback;
 
 import java.util.ArrayList;
@@ -163,7 +164,9 @@
         // start to monitor the preference value and invoke SystemAudioActionFromTv if needed.
     }
 
+    @ServiceThreadOnly
     private void initializeLocalDevices(final List<Integer> deviceTypes) {
+        assertRunOnServiceThread();
         // A container for [Logical Address, Local device info].
         final SparseArray<HdmiCecLocalDevice> devices = new SparseArray<>();
         final SparseIntArray finished = new SparseIntArray();
@@ -195,7 +198,9 @@
         }
     }
 
+    @ServiceThreadOnly
     private void notifyAddressAllocated(SparseArray<HdmiCecLocalDevice> devices) {
+        assertRunOnServiceThread();
         for (int i = 0; i < devices.size(); ++i) {
             int address = devices.keyAt(i);
             HdmiCecLocalDevice device = devices.valueAt(i);
@@ -205,7 +210,9 @@
 
     // Initialize HDMI port information. Combine the information from CEC and MHL HAL and
     // keep them in one place.
+    @ServiceThreadOnly
     private List<HdmiPortInfo> initPortInfo() {
+        assertRunOnServiceThread();
         HdmiPortInfo[] cecPortInfo = null;
 
         // CEC HAL provides majority of the info while MHL does only MHL support flag for
@@ -325,6 +332,7 @@
         return mCecController.getVendorId();
     }
 
+    @ServiceThreadOnly
     HdmiCecDeviceInfo getDeviceInfo(int logicalAddress) {
         assertRunOnServiceThread();
         HdmiCecLocalDeviceTv tv = tv();
@@ -374,15 +382,21 @@
      * @param command CEC command to send out
      * @param callback interface used to the result of send command
      */
+    @ServiceThreadOnly
     void sendCecCommand(HdmiCecMessage command, @Nullable SendMessageCallback callback) {
+        assertRunOnServiceThread();
         mCecController.sendCommand(command, callback);
     }
 
+    @ServiceThreadOnly
     void sendCecCommand(HdmiCecMessage command) {
+        assertRunOnServiceThread();
         mCecController.sendCommand(command, null);
     }
 
+    @ServiceThreadOnly
     boolean handleCecCommand(HdmiCecMessage message) {
+        assertRunOnServiceThread();
         return dispatchMessageToLocalDevice(message);
     }
 
@@ -390,7 +404,9 @@
         mCecController.setAudioReturnChannel(enabled);
     }
 
+    @ServiceThreadOnly
     private boolean dispatchMessageToLocalDevice(HdmiCecMessage message) {
+        assertRunOnServiceThread();
         for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {
             if (device.dispatchMessage(message)
                     && message.getDestination() != HdmiCec.ADDR_BROADCAST) {
@@ -408,13 +424,12 @@
      * @param portNo hdmi port number where hot plug event issued.
      * @param connected whether to be plugged in or not
      */
+    @ServiceThreadOnly
     void onHotplug(int portNo, boolean connected) {
         assertRunOnServiceThread();
-
         for (HdmiCecLocalDevice device : mCecController.getLocalDeviceList()) {
             device.onHotplug(portNo, connected);
         }
-
         announceHotplugEvent(portNo, connected);
     }
 
@@ -427,7 +442,9 @@
      * @param retryCount the number of retry used to send polling message to remote devices
      * @throw IllegalArgumentException if {@code pickStrategy} is invalid value
      */
+    @ServiceThreadOnly
     void pollDevices(DevicePollingCallback callback, int pickStrategy, int retryCount) {
+        assertRunOnServiceThread();
         mCecController.pollDevices(callback, checkPollStrategy(pickStrategy), retryCount);
     }
 
@@ -655,7 +672,7 @@
             if (tv == null) {
                 return false;
             }
-            return tv.canChangeSystemAudioMode();
+            return tv.hasSystemAudioDevice();
         }
 
         @Override
@@ -700,6 +717,7 @@
         }
     }
 
+    @ServiceThreadOnly
     private void oneTouchPlay(final IHdmiControlCallback callback) {
         assertRunOnServiceThread();
         HdmiCecLocalDevicePlayback source = playback();
@@ -711,6 +729,7 @@
         source.oneTouchPlay(callback);
     }
 
+    @ServiceThreadOnly
     private void queryDisplayStatus(final IHdmiControlCallback callback) {
         assertRunOnServiceThread();
         HdmiCecLocalDevicePlayback source = playback();
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 685717f..c0b7d68 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -383,6 +383,9 @@
             // You may not access another user's content as an enabled listener.
             return false;
         }
+        if (DEBUG) {
+            Log.d(TAG, "Checking if enabled notification listener " + compName);
+        }
         if (compName != null) {
             final String enabledNotifListeners = Settings.Secure.getStringForUser(mContentResolver,
                     Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index c0f1eec..7189960 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -27,6 +27,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.List;
 
 public final class Installer extends SystemService {
     private static final String TAG = "Installer";
@@ -345,8 +346,8 @@
         }
     }
 
-    public int pruneDexCache() {
-        return execute("prunedexcache");
+    public int pruneDexCache(String cacheSubDir) {
+        return execute("prunedexcache " + cacheSubDir);
     }
 
     public int freeCache(long freeStorageSize) {
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 25ebfc0..65cb6c9 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -197,7 +197,8 @@
             mainIntent.setPackage(packageName);
             long ident = Binder.clearCallingIdentity();
             try {
-                List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(mainIntent, 0,
+                List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(mainIntent,
+                        PackageManager.NO_CROSS_PROFILE, // We only want the apps for this user
                         user.getIdentifier());
                 return apps;
             } finally {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 41fe327..179b6e9 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -621,10 +621,10 @@
         private final AtomicLong mLastWritten = new AtomicLong(0);
         private final AtomicBoolean mBackgroundWriteRunning = new AtomicBoolean(false);
 
-        private boolean mIsFirstBoot = false;
+        private boolean mIsHistoricalPackageUsageAvailable = true;
 
-        boolean isFirstBoot() {
-            return mIsFirstBoot;
+        boolean isHistoricalPackageUsageAvailable() {
+            return mIsHistoricalPackageUsageAvailable;
         }
 
         void write(boolean force) {
@@ -715,7 +715,7 @@
                         pkg.mLastPackageUsageTimeInMills = timeInMillis;
                     }
                 } catch (FileNotFoundException expected) {
-                    mIsFirstBoot = true;
+                    mIsHistoricalPackageUsageAvailable = false;
                 } catch (IOException e) {
                     Log.w(TAG, "Failed to read package usage times", e);
                 } finally {
@@ -1488,9 +1488,6 @@
                 // changed. Consider this significant, and wipe away all other
                 // existing dexopt files to ensure we don't leave any dangling around.
                 //
-                // Additionally, delete all dex files from the root directory
-                // since there shouldn't be any there anyway.
-                //
                 // TODO: This should be revisited because it isn't as good an indicator
                 // as it used to be. It used to include the boot classpath but at some point
                 // DexFile.isDexOptNeeded started returning false for the boot
@@ -1498,7 +1495,15 @@
                 // small maintenance release update that the library and tool
                 // jars may be unchanged but APK could be removed resulting in
                 // unused dalvik-cache files.
-                mInstaller.pruneDexCache();
+                for (String instructionSet : instructionSets) {
+                    mInstaller.pruneDexCache(instructionSet);
+                }
+
+                // Additionally, delete all dex files from the root directory
+                // since there shouldn't be any there anyway, unless we're upgrading
+                // from an older OS version or a build that contained the "old" style
+                // flat scheme.
+                mInstaller.pruneDexCache(".");
             }
 
             // Collect vendor overlay packages.
@@ -1742,7 +1747,7 @@
 
     @Override
     public boolean isFirstBoot() {
-        return !mRestoredSettings || mPackageUsage.isFirstBoot();
+        return !mRestoredSettings;
     }
 
     @Override
@@ -3420,31 +3425,35 @@
         // reader
         synchronized (mPackages) {
             final String pkgName = intent.getPackage();
+            boolean queryCrossProfile = (flags & PackageManager.NO_CROSS_PROFILE) == 0;
             if (pkgName == null) {
-                //Check if the intent needs to be forwarded to another user for this package
-                ArrayList<ResolveInfo> crossProfileResult =
-                        queryIntentActivitiesCrossProfilePackage(
-                                intent, resolvedType, flags, userId);
-                if (!crossProfileResult.isEmpty()) {
-                    // Skip the current profile
-                    return crossProfileResult;
-                }
-                List<ResolveInfo> result;
-                List<CrossProfileIntentFilter> matchingFilters =
-                        getMatchingCrossProfileIntentFilters(intent, resolvedType, userId);
-                // Check for results that need to skip the current profile.
-                ResolveInfo resolveInfo = querySkipCurrentProfileIntents(matchingFilters, intent,
-                        resolvedType, flags, userId);
-                if (resolveInfo != null) {
-                    result = new ArrayList<ResolveInfo>(1);
-                    result.add(resolveInfo);
-                    return result;
+                ResolveInfo resolveInfo;
+                if (queryCrossProfile) {
+                    // Check if the intent needs to be forwarded to another user for this package
+                    ArrayList<ResolveInfo> crossProfileResult =
+                            queryIntentActivitiesCrossProfilePackage(
+                                    intent, resolvedType, flags, userId);
+                    if (!crossProfileResult.isEmpty()) {
+                        // Skip the current profile
+                        return crossProfileResult;
+                    }
+                    List<CrossProfileIntentFilter> matchingFilters =
+                            getMatchingCrossProfileIntentFilters(intent, resolvedType, userId);
+                    // Check for results that need to skip the current profile.
+                    resolveInfo = querySkipCurrentProfileIntents(matchingFilters, intent,
+                            resolvedType, flags, userId);
+                    if (resolveInfo != null) {
+                        List<ResolveInfo> result = new ArrayList<ResolveInfo>(1);
+                        result.add(resolveInfo);
+                        return result;
+                    }
+                    // Check for cross profile results.
+                    resolveInfo = queryCrossProfileIntents(
+                            matchingFilters, intent, resolvedType, flags, userId);
                 }
                 // Check for results in the current profile.
-                result = mActivities.queryIntent(intent, resolvedType, flags, userId);
-                // Check for cross profile results.
-                resolveInfo = queryCrossProfileIntents(
-                        matchingFilters, intent, resolvedType, flags, userId);
+                List<ResolveInfo> result = mActivities.queryIntent(
+                        intent, resolvedType, flags, userId);
                 if (resolveInfo != null) {
                     result.add(resolveInfo);
                 }
@@ -3452,12 +3461,14 @@
             }
             final PackageParser.Package pkg = mPackages.get(pkgName);
             if (pkg != null) {
-                ArrayList<ResolveInfo> crossProfileResult =
-                        queryIntentActivitiesCrossProfilePackage(
-                                intent, resolvedType, flags, userId, pkg, pkgName);
-                if (!crossProfileResult.isEmpty()) {
-                    // Skip the current profile
-                    return crossProfileResult;
+                if (queryCrossProfile) {
+                    ArrayList<ResolveInfo> crossProfileResult =
+                            queryIntentActivitiesCrossProfilePackage(
+                                    intent, resolvedType, flags, userId, pkg, pkgName);
+                    if (!crossProfileResult.isEmpty()) {
+                        // Skip the current profile
+                        return crossProfileResult;
+                    }
                 }
                 return mActivities.queryIntentForPackage(intent, resolvedType, flags,
                         pkg.activities, userId);
@@ -3479,8 +3490,7 @@
                     ResolveInfo resolveInfo = checkTargetCanHandle(filter, intent, resolvedType,
                             flags, sourceUserId);
                     if (resolveInfo != null) {
-                        return createForwardingResolveInfo(
-                                filter, sourceUserId, filter.getTargetUserId());
+                        return resolveInfo;
                     }
                 }
             }
@@ -3577,9 +3587,11 @@
 
     private ResolveInfo createForwardingResolveInfo(IntentFilter filter,
             int sourceUserId, int targetUserId) {
+        ResolveInfo forwardingResolveInfo = new ResolveInfo();
         String className;
         if (targetUserId == UserHandle.USER_OWNER) {
             className = FORWARD_INTENT_TO_USER_OWNER;
+            forwardingResolveInfo.showTargetUserIcon = true;
         } else {
             className = FORWARD_INTENT_TO_MANAGED_PROFILE;
         }
@@ -3587,13 +3599,13 @@
                 mAndroidApplication.packageName, className);
         ActivityInfo forwardingActivityInfo = getActivityInfo(forwardingActivityComponentName, 0,
                 sourceUserId);
-        ResolveInfo forwardingResolveInfo = new ResolveInfo();
         forwardingResolveInfo.activityInfo = forwardingActivityInfo;
         forwardingResolveInfo.priority = 0;
         forwardingResolveInfo.preferredOrder = 0;
         forwardingResolveInfo.match = 0;
         forwardingResolveInfo.isDefault = true;
         forwardingResolveInfo.filter = filter;
+        forwardingResolveInfo.targetUserId = targetUserId;
         return forwardingResolveInfo;
     }
 
@@ -4622,7 +4634,7 @@
             // The exception is first boot of a non-eng device, which
             // should do a full dexopt.
             boolean eng = "eng".equals(SystemProperties.get("ro.build.type"));
-            if (eng || !isFirstBoot()) {
+            if (eng || (!isFirstBoot() && mPackageUsage.isHistoricalPackageUsageAvailable())) {
                 // TODO: add a property to control this?
                 long dexOptLRUThresholdInMinutes;
                 if (eng) {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 1839259..a0cb098 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -412,13 +412,17 @@
 
     @Override
     public Bitmap getUserIcon(int userId) {
-        checkManageUsersPermission("read users");
         synchronized (mPackagesLock) {
             UserInfo info = mUsers.get(userId);
             if (info == null || info.partial) {
                 Slog.w(LOG_TAG, "getUserIcon: unknown user #" + userId);
                 return null;
             }
+            int callingGroupId = mUsers.get(UserHandle.getCallingUserId()).profileGroupId;
+            if (callingGroupId == UserInfo.NO_PROFILE_GROUP_ID
+                    || callingGroupId != info.profileGroupId) {
+                checkManageUsersPermission("get the icon of a user who is not related");
+            }
             if (info.iconPath == null) {
                 return null;
             }
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index b9ef492..32546df 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -186,16 +186,12 @@
                 if (resolveInfo.serviceInfo == null) continue;
 
                 String packageName = resolveInfo.serviceInfo.packageName;
-                // STOPSHIP Reenable this check once the GMS Core prebuild library has the
-                // permission.
-                /*
                 if (pm.checkPermission(PERMISSION_PROVIDE_AGENT, packageName)
                         != PackageManager.PERMISSION_GRANTED) {
                     Log.w(TAG, "Skipping agent because package " + packageName
                             + " does not have permission " + PERMISSION_PROVIDE_AGENT + ".");
                     continue;
                 }
-                */
 
                 ComponentName name = getComponentName(resolveInfo);
                 if (!enabledAgents.contains(name)) continue;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index d04d668..1d85723 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -411,7 +411,7 @@
     /**
      * And the callback to make when they've all been drawn.
      */
-    IRemoteCallback mWaitingForDrawnCallback;
+    Runnable mWaitingForDrawnCallback;
 
     /**
      * Windows that have called relayout() while we were running animations,
@@ -7561,7 +7561,7 @@
                 }
 
                 case WAITING_FOR_DRAWN_TIMEOUT: {
-                    IRemoteCallback callback = null;
+                    Runnable callback = null;
                     synchronized (mWindowMap) {
                         Slog.w(TAG, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn);
                         mWaitingForDrawn.clear();
@@ -7569,10 +7569,7 @@
                         mWaitingForDrawnCallback = null;
                     }
                     if (callback != null) {
-                        try {
-                            callback.sendResult(null);
-                        } catch (RemoteException e) {
-                        }
+                        callback.run();
                     }
                     break;
                 }
@@ -7626,16 +7623,13 @@
                     }
                     break;
                 case ALL_WINDOWS_DRAWN: {
-                    IRemoteCallback callback;
+                    Runnable callback;
                     synchronized (mWindowMap) {
                         callback = mWaitingForDrawnCallback;
                         mWaitingForDrawnCallback = null;
                     }
                     if (callback != null) {
-                        try {
-                            callback.sendResult(null);
-                        } catch (RemoteException e) {
-                        }
+                        callback.run();
                     }
                 }
                 case NEW_ANIMATOR_SCALE: {
@@ -9555,8 +9549,9 @@
             }
         }
 
-        if (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded
-                && !mInnerFields.mUpdateRotation) {
+        if (mWaitingForDrawnCallback != null ||
+                (mInnerFields.mOrientationChangeComplete && !defaultDisplay.layoutNeeded &&
+                        !mInnerFields.mUpdateRotation)) {
             checkDrawnWindowsLocked();
         }
 
@@ -10321,6 +10316,10 @@
         mPolicy.lockNow(options);
     }
 
+    public void showRecentApps() {
+        mPolicy.showRecentApps();
+    }
+
     @Override
     public boolean isSafeModeEnabled() {
         return mSafeMode;
@@ -11141,24 +11140,31 @@
             }
         }
 
-        public void waitForAllWindowsDrawn(IRemoteCallback callback, long timeout) {
+        public void waitForAllWindowsDrawn(Runnable callback, long timeout) {
             synchronized (mWindowMap) {
                 mWaitingForDrawnCallback = callback;
                 final WindowList windows = getDefaultWindowListLocked();
                 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
                     final WindowState win = windows.get(winNdx);
-                    if (win.mHasSurface) {
-                        win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
+                    if (win.mHasSurface && win.isWinVisibleLw()) {
+                        if (!win.mIsWallpaper) {
+                            // Don't force wallpaper to redraw.
+                            win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
+                        }
                         // Force add to mResizingWindows.
                         win.mLastContentInsets.set(-1, -1, -1, -1);
                         mWaitingForDrawn.add(win);
                     }
                 }
                 requestTraversalLocked();
-                mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
-                mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
             }
-            checkDrawnWindowsLocked();
+            mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
+            if (mWaitingForDrawn.isEmpty()) {
+                callback.run();
+            } else {
+                mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
+                checkDrawnWindowsLocked();
+            }
         }
     }
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 2801f4f..9c38bbc 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3732,7 +3732,7 @@
     /**
      * Sets which packages may enter lock task mode.
      *
-     * This function can only be called by the device owner or the profile owner.
+     * This function can only be called by the device owner.
      * @param components The list of components allowed to enter lock task mode.
      */
     public void setLockTaskPackages(String[] packages) throws SecurityException {
@@ -3741,15 +3741,13 @@
         String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
 
         synchronized (this) {
-            // Check whether any of the package name is the device owner or the profile owner.
+            // Check whether any of the package name is the device owner.
             for (int i=0; i<packageNames.length; i++) {
                 String packageName = packageNames[i];
                 int userHandle = UserHandle.getUserId(uid);
-                String profileOwnerPackage = getProfileOwner(userHandle);
-                if (isDeviceOwner(packageName) ||
-                    (profileOwnerPackage != null && profileOwnerPackage.equals(packageName))) {
+                if (isDeviceOwner(packageName)) {
 
-                    // If a package name is the device owner or the profile owner,
+                    // If a package name is the device owner,
                     // we update the component list.
                     DevicePolicyData policy = getUserData(userHandle);
                     policy.mLockTaskPackages.clear();
diff --git a/telecomm/java/android/telecomm/CallInfo.java b/telecomm/java/android/telecomm/CallInfo.java
index cb7f2dc..4de9373 100644
--- a/telecomm/java/android/telecomm/CallInfo.java
+++ b/telecomm/java/android/telecomm/CallInfo.java
@@ -52,8 +52,7 @@
     private final GatewayInfo mGatewayInfo;
 
     /**
-     * Additional information that can be persisted. For example, extra handoff information can
-     * attached to a call using {@link CallServiceSelectorAdapter#setHandoffInfo(String,Uri,Bundle).
+     * Additional information that can be persisted.
      */
     private final Bundle mExtras;
 
diff --git a/telecomm/java/android/telecomm/CallService.java b/telecomm/java/android/telecomm/CallService.java
index 0b5981c..12ba1ff 100644
--- a/telecomm/java/android/telecomm/CallService.java
+++ b/telecomm/java/android/telecomm/CallService.java
@@ -27,8 +27,6 @@
 import com.android.internal.telecomm.ICallService;
 import com.android.internal.telecomm.ICallServiceAdapter;
 
-import java.util.List;
-
 /**
  * Base implementation of CallService which can be used to provide calls for the system
  * in-call UI. CallService is a one-way service from the framework's CallsManager to any app
@@ -49,21 +47,20 @@
 public abstract class CallService extends Service {
 
     private static final int MSG_SET_CALL_SERVICE_ADAPTER = 1;
-    private static final int MSG_IS_COMPATIBLE_WITH = 2;
-    private static final int MSG_CALL = 3;
-    private static final int MSG_ABORT = 4;
-    private static final int MSG_SET_INCOMING_CALL_ID = 5;
-    private static final int MSG_ANSWER = 6;
-    private static final int MSG_REJECT = 7;
-    private static final int MSG_DISCONNECT = 8;
-    private static final int MSG_HOLD = 9;
-    private static final int MSG_UNHOLD = 10;
-    private static final int MSG_ON_AUDIO_STATE_CHANGED = 11;
-    private static final int MSG_PLAY_DTMF_TONE = 12;
-    private static final int MSG_STOP_DTMF_TONE = 13;
-    private static final int MSG_CONFERENCE = 14;
-    private static final int MSG_SPLIT_FROM_CONFERENCE = 15;
-    private static final int MSG_ON_POST_DIAL_CONTINUE = 16;
+    private static final int MSG_CALL = 2;
+    private static final int MSG_ABORT = 3;
+    private static final int MSG_SET_INCOMING_CALL_ID = 4;
+    private static final int MSG_ANSWER = 5;
+    private static final int MSG_REJECT = 6;
+    private static final int MSG_DISCONNECT = 7;
+    private static final int MSG_HOLD = 8;
+    private static final int MSG_UNHOLD = 9;
+    private static final int MSG_ON_AUDIO_STATE_CHANGED = 10;
+    private static final int MSG_PLAY_DTMF_TONE = 11;
+    private static final int MSG_STOP_DTMF_TONE = 12;
+    private static final int MSG_CONFERENCE = 13;
+    private static final int MSG_SPLIT_FROM_CONFERENCE = 14;
+    private static final int MSG_ON_POST_DIAL_CONTINUE = 15;
 
     /**
      * Default Handler used to consolidate binder method calls onto a single thread.
@@ -73,12 +70,9 @@
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case MSG_SET_CALL_SERVICE_ADAPTER:
-                    mAdapter = new CallServiceAdapter((ICallServiceAdapter) msg.obj);
+                    mAdapter.addAdapter((ICallServiceAdapter) msg.obj);
                     onAdapterAttached(mAdapter);
                     break;
-                case MSG_IS_COMPATIBLE_WITH:
-                    isCompatibleWith((CallInfo) msg.obj);
-                    break;
                 case MSG_CALL:
                     call((CallInfo) msg.obj);
                     break;
@@ -170,11 +164,6 @@
         }
 
         @Override
-        public void isCompatibleWith(CallInfo callInfo) {
-            mMessageHandler.obtainMessage(MSG_IS_COMPATIBLE_WITH, callInfo).sendToTarget();
-        }
-
-        @Override
         public void call(CallInfo callInfo) {
             mMessageHandler.obtainMessage(MSG_CALL, callInfo).sendToTarget();
         }
@@ -268,7 +257,7 @@
      */
     private final CallServiceBinder mBinder = new CallServiceBinder();
 
-    private CallServiceAdapter mAdapter = null;
+    private CallServiceAdapter mAdapter = new CallServiceAdapter();
 
     /** {@inheritDoc} */
     @Override
@@ -300,21 +289,10 @@
     }
 
     /**
-     * Determines if the CallService can place the specified call. Response is sent via
-     * {@link CallServiceAdapter#setIsCompatibleWith}. When responding, the correct call ID must be
-     * specified.  Only used in the context of outgoing calls and call switching (handoff).
-     *
-     * @param callInfo The details of the relevant call.
-     */
-    public abstract void isCompatibleWith(CallInfo callInfo);
-
-    /**
      * Attempts to call the relevant party using the specified call's handle, be it a phone number,
      * SIP address, or some other kind of user ID.  Note that the set of handle types is
      * dynamically extensible since call providers should be able to implement arbitrary
-     * handle-calling systems.  See {@link #isCompatibleWith}. It is expected that the
-     * call service respond via {@link CallServiceAdapter#handleSuccessfulOutgoingCall(String)}
-     * if it can successfully make the call.  Only used in the context of outgoing calls.
+     * handle-calling systems.
      *
      * @param callInfo The details of the relevant call.
      */
diff --git a/telecomm/java/android/telecomm/CallServiceAdapter.java b/telecomm/java/android/telecomm/CallServiceAdapter.java
index 0ba8161..30084d0 100644
--- a/telecomm/java/android/telecomm/CallServiceAdapter.java
+++ b/telecomm/java/android/telecomm/CallServiceAdapter.java
@@ -16,54 +16,86 @@
 
 package android.telecomm;
 
+import android.content.ComponentName;
+import android.os.IBinder;
+import android.os.IBinder.DeathRecipient;
 import android.os.RemoteException;
 
+import com.android.internal.telecomm.ICallService;
 import com.android.internal.telecomm.ICallServiceAdapter;
+import com.android.internal.telecomm.RemoteServiceCallback;
 
+import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 /**
  * Provides methods for ICallService implementations to interact with the system phone app.
  * TODO(santoscordon): Need final public-facing comments in this file.
+ * TODO(santoscordon): Rename this to CallServiceAdapterDemultiplexer (or something).
  */
-public final class CallServiceAdapter {
-    private final ICallServiceAdapter mAdapter;
+public final class CallServiceAdapter implements DeathRecipient {
+    private final Set<ICallServiceAdapter> mAdapters = new HashSet<>();
 
     /**
-     * {@hide}
+     * @hide
      */
-    public CallServiceAdapter(ICallServiceAdapter adapter) {
-        mAdapter = adapter;
+    public CallServiceAdapter() {
     }
 
     /**
-     * Receives confirmation of a call service's ability to place a call. This method is used in
-     * response to {@link CallService#isCompatibleWith}.
-     *
-     * @param callId The identifier of the call for which compatibility is being received. This ID
-     *     should correspond to the ID given as part of the call information in
-     *     {@link CallService#isCompatibleWith}.
-     * @param isCompatible True if the call service can place the call.
+     * @hide
      */
-    public void setIsCompatibleWith(String callId, boolean isCompatible) {
-        try {
-            mAdapter.setIsCompatibleWith(callId, isCompatible);
-        } catch (RemoteException e) {
+    public void addAdapter(ICallServiceAdapter adapter) {
+        if (mAdapters.add(adapter)) {
+            try {
+                adapter.asBinder().linkToDeath(this, 0);
+            } catch (RemoteException e) {
+                mAdapters.remove(adapter);
+            }
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public void removeAdapter(ICallServiceAdapter adapter) {
+        if (mAdapters.remove(adapter)) {
+            adapter.asBinder().unlinkToDeath(this, 0);
+        }
+    }
+
+    /** ${inheritDoc} */
+    @Override
+    public void binderDied() {
+        ICallServiceAdapter adapterToRemove = null;
+        for (ICallServiceAdapter adapter : mAdapters) {
+            if (!adapter.asBinder().isBinderAlive()) {
+                adapterToRemove = adapter;
+                break;
+            }
+        }
+
+        if (adapterToRemove != null) {
+            removeAdapter(adapterToRemove);
         }
     }
 
     /**
      * Provides Telecomm with the details of an incoming call. An invocation of this method must
-     * follow {@link CallService#setIncomingCallId} and use the call ID specified therein. Upon
-     * the invocation of this method, Telecomm will bring up the incoming-call interface where the
-     * user can elect to answer or reject a call.
+     * follow {@link CallService#setIncomingCallId} and use the call ID specified therein. Upon the
+     * invocation of this method, Telecomm will bring up the incoming-call interface where the user
+     * can elect to answer or reject a call.
      *
      * @param callInfo The details of the relevant call.
      */
     public void notifyIncomingCall(CallInfo callInfo) {
-        try {
-            mAdapter.notifyIncomingCall(callInfo);
-        } catch (RemoteException e) {
+        for (ICallServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.notifyIncomingCall(callInfo);
+            } catch (RemoteException e) {
+            }
         }
     }
 
@@ -75,9 +107,11 @@
      * @param callId The ID of the outgoing call.
      */
     public void handleSuccessfulOutgoingCall(String callId) {
-        try {
-            mAdapter.handleSuccessfulOutgoingCall(callId);
-        } catch (RemoteException e) {
+        for (ICallServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.handleSuccessfulOutgoingCall(callId);
+            } catch (RemoteException e) {
+            }
         }
     }
 
@@ -92,9 +126,11 @@
             ConnectionRequest request,
             int errorCode,
             String errorMsg) {
-        try {
-            mAdapter.handleFailedOutgoingCall(request, errorCode, errorMsg);
-        } catch (RemoteException e) {
+        for (ICallServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.handleFailedOutgoingCall(request, errorCode, errorMsg);
+            } catch (RemoteException e) {
+            }
         }
     }
 
@@ -105,9 +141,11 @@
      * @param callId The unique ID of the call whose state is changing to active.
      */
     public void setActive(String callId) {
-        try {
-            mAdapter.setActive(callId);
-        } catch (RemoteException e) {
+        for (ICallServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.setActive(callId);
+            } catch (RemoteException e) {
+            }
         }
     }
 
@@ -117,9 +155,11 @@
      * @param callId The unique ID of the call whose state is changing to ringing.
      */
     public void setRinging(String callId) {
-        try {
-            mAdapter.setRinging(callId);
-        } catch (RemoteException e) {
+        for (ICallServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.setRinging(callId);
+            } catch (RemoteException e) {
+            }
         }
     }
 
@@ -129,9 +169,11 @@
      * @param callId The unique ID of the call whose state is changing to dialing.
      */
     public void setDialing(String callId) {
-        try {
-            mAdapter.setDialing(callId);
-        } catch (RemoteException e) {
+        for (ICallServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.setDialing(callId);
+            } catch (RemoteException e) {
+            }
         }
     }
 
@@ -140,13 +182,15 @@
      *
      * @param callId The unique ID of the call whose state is changing to disconnected.
      * @param disconnectCause The reason for the disconnection, any of
-     *         {@link android.telephony.DisconnectCause}.
+     *            {@link android.telephony.DisconnectCause}.
      * @param disconnectMessage Optional call-service-provided message about the disconnect.
      */
     public void setDisconnected(String callId, int disconnectCause, String disconnectMessage) {
-        try {
-            mAdapter.setDisconnected(callId, disconnectCause, disconnectMessage);
-        } catch (RemoteException e) {
+        for (ICallServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.setDisconnected(callId, disconnectCause, disconnectMessage);
+            } catch (RemoteException e) {
+            }
         }
     }
 
@@ -156,9 +200,11 @@
      * @param callId - The unique ID of the call whose state is changing to be on hold.
      */
     public void setOnHold(String callId) {
-        try {
-            mAdapter.setOnHold(callId);
-        } catch (RemoteException e) {
+        for (ICallServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.setOnHold(callId);
+            } catch (RemoteException e) {
+            }
         }
     }
 
@@ -169,9 +215,11 @@
      * @param ringback Whether Telecomm should start playing a ringback tone.
      */
     public void setRequestingRingback(String callId, boolean ringback) {
-        try {
-            mAdapter.setRequestingRingback(callId, ringback);
-        } catch (RemoteException e) {
+        for (ICallServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.setRequestingRingback(callId, ringback);
+            } catch (RemoteException e) {
+            }
         }
     }
 
@@ -183,9 +231,11 @@
      * @hide
      */
     public void setCanConference(String callId, boolean canConference) {
-        try {
-            mAdapter.setCanConference(callId, canConference);
-        } catch (RemoteException ignored) {
+        for (ICallServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.setCanConference(callId, canConference);
+            } catch (RemoteException ignored) {
+            }
         }
     }
 
@@ -195,13 +245,15 @@
      *
      * @param callId The unique ID of the call being conferenced.
      * @param conferenceCallId The unique ID of the conference call. Null if call is not
-     *         conferenced.
+     *            conferenced.
      * @hide
      */
     public void setIsConferenced(String callId, String conferenceCallId) {
-        try {
-            mAdapter.setIsConferenced(callId, conferenceCallId);
-        } catch (RemoteException ignored) {
+        for (ICallServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.setIsConferenced(callId, conferenceCallId);
+            } catch (RemoteException ignored) {
+            }
         }
     }
 
@@ -213,16 +265,20 @@
      * @hide
      */
     public void removeCall(String callId) {
-        try {
-            mAdapter.removeCall(callId);
-        } catch (RemoteException ignored) {
+        for (ICallServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.removeCall(callId);
+            } catch (RemoteException ignored) {
+            }
         }
     }
 
     public void onPostDialWait(String callId, String remaining) {
-        try {
-            mAdapter.onPostDialWait(callId, remaining);
-        } catch (RemoteException ignored) {
+        for (ICallServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.onPostDialWait(callId, remaining);
+            } catch (RemoteException ignored) {
+            }
         }
     }
 
@@ -232,9 +288,11 @@
      * @param callId The identifier of the call to handoff.
      */
     public void handoffCall(String callId) {
-        try {
-            mAdapter.handoffCall(callId);
-        } catch (RemoteException e) {
+        for (ICallServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.handoffCall(callId);
+            } catch (RemoteException e) {
+            }
         }
     }
 
@@ -244,9 +302,26 @@
      * @param callId The unique ID of the conference call.
      */
     public void addConferenceCall(String callId) {
-        try {
-            mAdapter.addConferenceCall(callId, null);
-        } catch (RemoteException ignored) {
+        for (ICallServiceAdapter adapter : mAdapters) {
+            try {
+                adapter.addConferenceCall(callId, null);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    /**
+     * Retrieves a list of remote connection services usable to place calls.
+     * @hide
+     */
+    public void queryRemoteConnectionServices(RemoteServiceCallback callback) {
+        // Only supported when there is only one adapter.
+        if (mAdapters.size() == 1) {
+            try {
+                mAdapters.iterator().next().queryRemoteConnectionServices(callback);
+            } catch (RemoteException e) {
+                Log.e(this, e, "Exception trying to query for remote CSs");
+            }
         }
     }
 }
diff --git a/telecomm/java/android/telecomm/CallServiceSelector.java b/telecomm/java/android/telecomm/CallServiceSelector.java
deleted file mode 100644
index c9c6ff6..0000000
--- a/telecomm/java/android/telecomm/CallServiceSelector.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * 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.
- */
-
-package android.telecomm;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-
-import com.android.internal.os.SomeArgs;
-import com.android.internal.telecomm.ICallServiceSelector;
-import com.android.internal.telecomm.ICallServiceSelectorAdapter;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * Allows for the organization of {@link CallService}s for outbound calls. Given a call and list of
- * {@link CallService} IDs, order the list in terms of priority and return it using
- * {@link #select(CallInfo, List)}.
- */
-public abstract class CallServiceSelector extends Service {
-    private static final int MSG_SET_CALL_SERVICE_SELECTOR_ADAPTER = 0;
-    private static final int MSG_SELECT = 1;
-
-    private final HashMap<String, CallInfo> mCalls = new HashMap<String, CallInfo>();
-
-    /** Handler to move client-bound method calls to the main thread. */
-    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_SET_CALL_SERVICE_SELECTOR_ADAPTER:
-                    mAdapter = new CallServiceSelectorAdapter(
-                            (ICallServiceSelectorAdapter) msg.obj);
-                    onAdapterAttached(mAdapter);
-                    break;
-                case MSG_SELECT:
-                    SomeArgs args = (SomeArgs) msg.obj;
-                    try {
-                        select((CallInfo) args.arg1, (List<CallServiceDescriptor>) args.arg2);
-                    } finally {
-                        args.recycle();
-                    }
-                    break;
-            }
-        }
-    };
-
-    /** Manages the binder calls so that the implementor does not need to deal with it. */
-    private final class CallServiceSelectorBinder extends ICallServiceSelector.Stub {
-        @Override
-        public void setCallServiceSelectorAdapter(ICallServiceSelectorAdapter adapter) {
-            mHandler.obtainMessage(MSG_SET_CALL_SERVICE_SELECTOR_ADAPTER, adapter)
-                    .sendToTarget();
-        }
-
-        @Override
-        public void select(CallInfo callInfo, List<CallServiceDescriptor> descriptors) {
-            SomeArgs args = SomeArgs.obtain();
-            args.arg1 = callInfo;
-            args.arg2 = descriptors;
-            mHandler.obtainMessage(MSG_SELECT, args).sendToTarget();
-        }
-
-        @Override
-        public void onCallUpdated(CallInfo callInfo) {
-            mCalls.put(callInfo.getId(), callInfo);
-        }
-
-        @Override
-        public void onCallRemoved(String callId) {
-            mCalls.remove(callId);
-        }
-    }
-
-    private final CallServiceSelectorBinder mBinder;
-
-    private CallServiceSelectorAdapter mAdapter = null;
-
-    protected CallServiceSelector() {
-        mBinder = new CallServiceSelectorBinder();
-    }
-
-    @Override
-    public final IBinder onBind(Intent intent) {
-        return mBinder;
-    }
-
-    /**
-     * Returns a list of all calls managed by this selector.
-     */
-    protected final Collection<CallInfo> getCalls() {
-        return Collections.unmodifiableCollection(mCalls.values());
-    }
-
-    /**
-     * @return The attached {@link CallServiceSelectorAdapter} if attached, or null otherwise.
-     */
-    protected final CallServiceSelectorAdapter getAdapter() {
-        return mAdapter;
-    }
-
-    /**
-     * Cancel the outgoing call. Any subsequent calls to {@link #select(CallInfo, List)} will be
-     * ignored.
-     *
-     * @param callInfo The call to canceled.
-     */
-    protected final void cancelOutgoingCall(CallInfo callInfo) {
-        getAdapter().cancelOutgoingCall(callInfo.getId());
-    }
-
-    /**
-     * Lifecycle callback which is called when this {@link CallServiceSelector} has been attached
-     * to a {@link CallServiceSelectorAdapter}, indicating {@link #getAdapter()} is now safe to use.
-     *
-     * @param adapter The adapter now attached to this call service selector.
-     */
-    protected void onAdapterAttached(CallServiceSelectorAdapter adapter) {
-    }
-
-    /**
-     * Given a list of {@link CallServiceDescriptor}s, order them into a prioritized list and return
-     * them through
-     * {@link CallServiceSelectorAdapter#setSelectedCallServices(String,List)}.
-     *
-     * @param callInfo The call being placed using the {@link CallService}s.
-     * @param descriptors The descriptors of the available {@link CallService}s with which to place
-     *            the call.
-     */
-    protected abstract void select(CallInfo callInfo, List<CallServiceDescriptor> descriptors);
-}
diff --git a/telecomm/java/android/telecomm/CallServiceSelectorAdapter.java b/telecomm/java/android/telecomm/CallServiceSelectorAdapter.java
deleted file mode 100644
index 4d2e8aa..0000000
--- a/telecomm/java/android/telecomm/CallServiceSelectorAdapter.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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.
- */
-
-package android.telecomm;
-
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.RemoteException;
-import android.telecomm.CallServiceDescriptor;
-
-import com.android.internal.telecomm.ICallServiceSelectorAdapter;
-
-import java.util.List;
-
-/**
- * Provides methods for ICallServiceSelector implementations to interact with Telecomm.
- */
-public final class CallServiceSelectorAdapter {
-    private final ICallServiceSelectorAdapter mAdapter;
-
-    /**
-     * {@hide}
-     */
-    public CallServiceSelectorAdapter(ICallServiceSelectorAdapter adapter) {
-        mAdapter = adapter;
-    }
-
-    /**
-     * Records the sorted set of call services that are preferred by the corresponding
-     * call-service selector.
-     *
-     * @param callId The ID of the call to complete.
-     * @param selectedCallServiceDescriptors The prioritized list of preferred call-service
-     *        descriptors to use for completing the call.
-     */
-    public void setSelectedCallServices(
-            String callId,
-            List<CallServiceDescriptor> selectedCallServiceDescriptors) {
-        try {
-            mAdapter.setSelectedCallServices(callId, selectedCallServiceDescriptors);
-        } catch (RemoteException e) {
-        }
-    }
-
-    /**
-     * Cancels the specified outgoing call.
-     *
-     * @param callId The ID of the call to cancel.
-     */
-    public void cancelOutgoingCall(String callId) {
-        try {
-            mAdapter.cancelOutgoingCall(callId);
-        } catch (RemoteException e) {
-        }
-    }
-
-    /**
-     * Associates handoff information with an ongoing call. Calls can switch from one call service
-     * to another. Setting handle to a non-null value marks the call as switchable.
-     *
-     * @param callId The ID of the call to set handoff information for.
-     * @param handle The handle used to place the call when switching.
-     * @param extras Optional extra that's attached to the call.
-     */
-    public void setHandoffInfo(String callId, Uri handle, Bundle extras) {
-        try {
-            mAdapter.setHandoffInfo(callId, handle, extras);
-        } catch (RemoteException e) {
-        }
-    }
-}
diff --git a/telecomm/java/android/telecomm/Connection.java b/telecomm/java/android/telecomm/Connection.java
index 164eeff..1783327 100644
--- a/telecomm/java/android/telecomm/Connection.java
+++ b/telecomm/java/android/telecomm/Connection.java
@@ -356,6 +356,13 @@
     }
 
     /**
+     * Returns whether this connection is capable of being conferenced.
+     */
+    public boolean isConferenceCapable() {
+        return mIsConferenceCapable;
+    }
+
+    /**
      * Sets the value of the {@link #getHandle()} property and notifies listeners.
      *
      * @param handle The new handle.
diff --git a/telecomm/java/android/telecomm/ConnectionRequest.java b/telecomm/java/android/telecomm/ConnectionRequest.java
index bf5727b..61ac816 100644
--- a/telecomm/java/android/telecomm/ConnectionRequest.java
+++ b/telecomm/java/android/telecomm/ConnectionRequest.java
@@ -33,18 +33,29 @@
     private final String mCallId;
     private final Uri mHandle;
     private final Bundle mExtras;
+    private final Subscription mSubscription;
 
     public ConnectionRequest(Uri handle, Bundle extras) {
         this(null, handle, extras);
     }
 
     public ConnectionRequest(String callId, Uri handle, Bundle extras) {
+        this(null, callId, handle, extras);
+    }
+
+    public ConnectionRequest(Subscription subscription, String callId, Uri handle, Bundle extras) {
         mCallId = callId;
         mHandle = handle;
         mExtras = extras;
+        mSubscription = subscription;
     }
 
     /**
+     * The subscription which should be used to place the call.
+     */
+    public Subscription getSubscription() { return mSubscription; }
+
+    /**
      * An identifier for this call.
      */
     public String getCallId() { return mCallId; }
diff --git a/telecomm/java/android/telecomm/ConnectionService.java b/telecomm/java/android/telecomm/ConnectionService.java
index 8a4e123..4b69a3c 100644
--- a/telecomm/java/android/telecomm/ConnectionService.java
+++ b/telecomm/java/android/telecomm/ConnectionService.java
@@ -16,12 +16,21 @@
 
 package android.telecomm;
 
+import android.content.ComponentName;
 import android.net.Uri;
 import android.os.Bundle;
+
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
 import android.telephony.DisconnectCause;
 
+import com.android.internal.telecomm.ICallService;
+import com.android.internal.telecomm.RemoteServiceCallback;
+
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -36,6 +45,12 @@
     // Mappings from Connections to IDs as understood by the current CallService implementation
     private final Map<String, Connection> mConnectionById = new HashMap<>();
     private final Map<Connection, String> mIdByConnection = new HashMap<>();
+    private final RemoteConnectionManager mRemoteConnectionManager = new RemoteConnectionManager();
+    private final Handler mHandler = new Handler(Looper.getMainLooper());
+
+    private SimpleResponse<Uri, List<Subscription>> mSubscriptionLookupResponse;
+    private Uri mSubscriptionLookupHandle;
+    private boolean mAreSubscriptionsInitialized = false;
 
     private final Connection.Listener mConnectionListener = new Connection.Listener() {
         @Override
@@ -114,28 +129,6 @@
     };
 
     @Override
-    public final void isCompatibleWith(final CallInfo callInfo) {
-        Log.d(this, "isCompatibleWith %s", callInfo);
-        onFindSubscriptions(
-                callInfo.getHandle(),
-                new Response<Uri, Subscription>() {
-                    @Override
-                    public void onResult(Uri handle, Subscription... result) {
-                        boolean isCompatible = result.length > 0;
-                        Log.d(this, "adapter setIsCompatibleWith ");
-                        getAdapter().setIsCompatibleWith(callInfo.getId(), isCompatible);
-                    }
-
-                    @Override
-                    public void onError(Uri handle, int code, String msg) {
-                        Log.w(this, "Error in onFindSubscriptions %s %d %s", handle, code, msg);
-                        getAdapter().setIsCompatibleWith(callInfo.getId(), false);
-                    }
-                }
-        );
-    }
-
-    @Override
     public final void call(final CallInfo callInfo) {
         Log.d(this, "call %s", callInfo);
         onCreateConnections(
@@ -336,6 +329,71 @@
     }
 
     /**
+     * @hide
+     */
+    @Override
+    protected void onAdapterAttached(CallServiceAdapter adapter) {
+        if (mAreSubscriptionsInitialized) {
+            // No need to query again if we already did it.
+            return;
+        }
+
+        getAdapter().queryRemoteConnectionServices(new RemoteServiceCallback.Stub() {
+            @Override
+            public void onResult(
+                    final List<ComponentName> componentNames,
+                    final List<IBinder> callServices) {
+                mHandler.post(new Runnable() {
+                    @Override public void run() {
+                        for (int i = 0; i < componentNames.size() && i < callServices.size(); i++) {
+                            mRemoteConnectionManager.addConnectionService(
+                                    componentNames.get(i),
+                                    ICallService.Stub.asInterface(callServices.get(i)));
+                        }
+                        mAreSubscriptionsInitialized = true;
+                        Log.d(this, "remote call services found: " + callServices);
+                        maybeRespondToSubscriptionLookup();
+                    }
+                });
+            }
+
+            @Override
+            public void onError() {
+                mHandler.post(new Runnable() {
+                    @Override public void run() {
+                        mAreSubscriptionsInitialized = true;
+                        maybeRespondToSubscriptionLookup();
+                    }
+                });
+            }
+        });
+    }
+
+    public void lookupRemoteSubscriptions(
+            Uri handle, SimpleResponse<Uri, List<Subscription>> response) {
+        mSubscriptionLookupResponse = response;
+        mSubscriptionLookupHandle = handle;
+        maybeRespondToSubscriptionLookup();
+    }
+
+    public void maybeRespondToSubscriptionLookup() {
+        if (mAreSubscriptionsInitialized && mSubscriptionLookupResponse != null) {
+            mSubscriptionLookupResponse.onResult(
+                    mSubscriptionLookupHandle,
+                    mRemoteConnectionManager.getSubscriptions(mSubscriptionLookupHandle));
+
+            mSubscriptionLookupHandle = null;
+            mSubscriptionLookupResponse = null;
+        }
+    }
+
+    public void createRemoteOutgoingConnection(
+            ConnectionRequest request,
+            SimpleResponse<ConnectionRequest, RemoteConnection> response) {
+        mRemoteConnectionManager.createOutgoingConnection(request, response);
+    }
+
+    /**
      * Returns all connections currently associated with this connection service.
      */
     public Collection<Connection> getAllConnections() {
@@ -343,16 +401,6 @@
     }
 
     /**
-     * Find a set of Subscriptions matching a given handle (e.g. phone number).
-     *
-     * @param handle A handle (e.g. phone number) with which to connect.
-     * @param callback A callback for providing the result.
-     */
-    public void onFindSubscriptions(
-            Uri handle,
-            Response<Uri, Subscription> callback) {}
-
-    /**
      * Create a Connection given a request.
      *
      * @param request Data encapsulating details of the desired Connection.
diff --git a/telecomm/java/android/telecomm/InCallService.java b/telecomm/java/android/telecomm/InCallService.java
index c7dd23a..31291fb 100644
--- a/telecomm/java/android/telecomm/InCallService.java
+++ b/telecomm/java/android/telecomm/InCallService.java
@@ -156,7 +156,7 @@
     }
 
     /**
-     * @return The attached {@link CallServiceSelectorAdapter} if attached, or null otherwise.
+     * @return The attached {@link InCallAdapter} if attached, or null otherwise.
      */
     protected final InCallAdapter getAdapter() {
         return mAdapter;
diff --git a/telecomm/java/android/telecomm/RemoteConnection.java b/telecomm/java/android/telecomm/RemoteConnection.java
new file mode 100644
index 0000000..92db0d8
--- /dev/null
+++ b/telecomm/java/android/telecomm/RemoteConnection.java
@@ -0,0 +1,227 @@
+/*
+ * 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.
+ */
+
+package android.telecomm;
+
+import android.net.Uri;
+
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.telephony.DisconnectCause;
+
+import com.android.internal.telecomm.ICallService;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * RemoteConnection object used by RemoteConnectionService.
+ */
+public final class RemoteConnection {
+    public interface Listener {
+        void onStateChanged(RemoteConnection connection, int state);
+        void onAudioStateChanged(RemoteConnection connection, CallAudioState state);
+        void onDisconnected(RemoteConnection connection, int cause, String message);
+        void onRequestingRingback(RemoteConnection connection, boolean ringback);
+        void onPostDialWait(RemoteConnection connection, String remainingDigits);
+        void onDestroyed(RemoteConnection connection);
+    }
+
+    private final ICallService mCallService;
+    private final String mConnectionId;
+    private final Set<Listener> mListeners = new HashSet<>();
+
+    private int mState;
+    private int mDisconnectCause = DisconnectCause.NOT_VALID;
+    private String mDisconnectMessage;
+    private boolean mRequestingRingback;
+    private boolean mConnected;
+
+    /**
+     * @hide
+     */
+    RemoteConnection(ICallService callService, String connectionId) {
+        mCallService = callService;
+        mConnectionId = connectionId;
+
+        mConnected = true;
+    }
+
+    public void addListener(Listener listener) {
+        mListeners.add(listener);
+    }
+
+    public void removeListener(Listener listener) {
+        mListeners.remove(listener);
+    }
+
+    public int getDisconnectCause() {
+        return mDisconnectCause;
+    }
+
+    public String getDisconnectMessage() {
+        return mDisconnectMessage;
+    }
+
+    public void answer() {
+        try {
+            if (mConnected) {
+                mCallService.answer(mConnectionId);
+            }
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    public void reject() {
+        try {
+            if (mConnected) {
+                mCallService.reject(mConnectionId);
+            }
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    public void hold() {
+        try {
+            if (mConnected) {
+                mCallService.hold(mConnectionId);
+            }
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    public void unhold() {
+        try {
+            if (mConnected) {
+                mCallService.unhold(mConnectionId);
+            }
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    public void disconnect() {
+        try {
+            if (mConnected) {
+                mCallService.disconnect(mConnectionId);
+            }
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    public void playDtmf(char digit) {
+        try {
+            if (mConnected) {
+                mCallService.playDtmfTone(mConnectionId, digit);
+            }
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    public void stopDtmf() {
+        try {
+            if (mConnected) {
+                mCallService.stopDtmfTone(mConnectionId);
+            }
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    public void postDialContinue(boolean proceed) {
+        try {
+            if (mConnected) {
+                mCallService.onPostDialContinue(mConnectionId, proceed);
+            }
+        } catch (RemoteException ignored) {
+        }
+    }
+
+    /**
+     * @hide
+     */
+    void setState(int state) {
+        if (mState != state) {
+            mState = state;
+            for (Listener l: mListeners) {
+                l.onStateChanged(this, state);
+            }
+        }
+    }
+
+    /**
+     * @hide
+     */
+    void setAudioState(CallAudioState state) {
+        for (Listener l: mListeners) {
+            l.onAudioStateChanged(this, state);
+        }
+    }
+
+    /**
+     * @hide
+     */
+    void setDisconnected(int cause, String message) {
+        if (mState != Connection.State.DISCONNECTED) {
+            mState = Connection.State.DISCONNECTED;
+            mDisconnectCause = cause;
+            mDisconnectMessage = message;
+
+            for (Listener l : mListeners) {
+                l.onDisconnected(this, cause, message);
+            }
+        }
+    }
+
+    /**
+     * @hide
+     */
+    void setRequestingRingback(boolean ringback) {
+        if (mRequestingRingback != ringback) {
+            mRequestingRingback = ringback;
+            for (Listener l : mListeners) {
+                l.onRequestingRingback(this, ringback);
+            }
+        }
+    }
+
+    /**
+     * @hide
+     */
+    void setDestroyed() {
+        if (!mListeners.isEmpty()) {
+            // Make sure that the listeners are notified that the call is destroyed first.
+            if (mState != Connection.State.DISCONNECTED) {
+                setDisconnected(DisconnectCause.ERROR_UNSPECIFIED, "Connection destroyed.");
+            }
+
+            Set<Listener> listeners = new HashSet<Listener>(mListeners);
+            mListeners.clear();
+            for (Listener l : listeners) {
+                l.onDestroyed(this);
+            }
+
+            mConnected = false;
+        }
+    }
+
+    /**
+     * @hide
+     */
+    void setPostDialWait(String remainingDigits) {
+        for (Listener l : mListeners) {
+            l.onPostDialWait(this, remainingDigits);
+        }
+    }
+}
diff --git a/telecomm/java/android/telecomm/RemoteConnectionManager.java b/telecomm/java/android/telecomm/RemoteConnectionManager.java
new file mode 100644
index 0000000..4201f23
--- /dev/null
+++ b/telecomm/java/android/telecomm/RemoteConnectionManager.java
@@ -0,0 +1,74 @@
+/*
+ * 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
+ R* limitations under the License.
+ */
+
+package android.telecomm;
+
+import android.content.ComponentName;
+import android.net.Uri;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import com.android.internal.telecomm.ICallService;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @hide
+ */
+public class RemoteConnectionManager {
+    private Map<ComponentName, RemoteConnectionService> mRemoteConnectionServices = new HashMap<>();
+
+    void addConnectionService(ComponentName componentName, ICallService callService) {
+        if (!mRemoteConnectionServices.containsKey(componentName)) {
+            try {
+                RemoteConnectionService remoteConnectionService =
+                        new RemoteConnectionService(componentName, callService);
+                mRemoteConnectionServices.put(componentName, remoteConnectionService);
+            } catch (RemoteException ignored) {
+            }
+        }
+    }
+
+    List<Subscription> getSubscriptions(Uri handle) {
+        List<Subscription> subscriptions = new LinkedList<>();
+        Log.d(this, "Getting subscriptions: " + mRemoteConnectionServices.keySet());
+        for (RemoteConnectionService remoteService : mRemoteConnectionServices.values()) {
+            // TODO(santoscordon): Eventually this will be async.
+            subscriptions.addAll(remoteService.lookupSubscriptions(handle));
+        }
+        return subscriptions;
+    }
+
+    public void createOutgoingConnection(
+            ConnectionRequest request,
+            final SimpleResponse<ConnectionRequest, RemoteConnection> response) {
+        Subscription subscription = request.getSubscription();
+        if (subscription == null) {
+            throw new IllegalArgumentException("subscription must be specified.");
+        }
+
+        ComponentName componentName = request.getSubscription().getComponentName();
+        if (!mRemoteConnectionServices.containsKey(componentName)) {
+            throw new UnsupportedOperationException("subscription not supported: " + componentName);
+        } else {
+            RemoteConnectionService remoteService = mRemoteConnectionServices.get(componentName);
+            remoteService.createOutgoingConnection(request, response);
+        }
+    }
+}
diff --git a/telecomm/java/android/telecomm/RemoteConnectionService.java b/telecomm/java/android/telecomm/RemoteConnectionService.java
new file mode 100644
index 0000000..86a43cb
--- /dev/null
+++ b/telecomm/java/android/telecomm/RemoteConnectionService.java
@@ -0,0 +1,274 @@
+/*
+ * 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
+ R* limitations under the License.
+ */
+
+package android.telecomm;
+
+import android.content.ComponentName;
+import android.net.Uri;
+import android.os.IBinder.DeathRecipient;
+import android.os.RemoteException;
+import android.telephony.DisconnectCause;
+
+import android.text.TextUtils;
+
+import com.android.internal.telecomm.ICallService;
+import com.android.internal.telecomm.ICallServiceAdapter;
+import com.android.internal.telecomm.RemoteServiceCallback;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Remote connection service which other connection services can use to place calls on their behalf.
+ */
+public class RemoteConnectionService implements DeathRecipient {
+    private final ICallService mCallService;
+    private final ComponentName mComponentName;
+
+    private String mConnectionId;
+    private ConnectionRequest mPendingRequest;
+    private SimpleResponse<ConnectionRequest, RemoteConnection> mPendingResponse;
+    // Remote connection services only support a single connection.
+    private RemoteConnection mConnection;
+
+    private final ICallServiceAdapter mAdapter = new ICallServiceAdapter.Stub() {
+
+        /** ${inheritDoc} */
+            @Override
+        public void notifyIncomingCall(CallInfo callInfo) {
+            Log.w(this, "notifyIncomingCall not implemented in Remote connection");
+        }
+
+        /** ${inheritDoc} */
+            @Override
+        public void handleSuccessfulOutgoingCall(String connectionId) {
+            if (isPendingConnection(connectionId)) {
+                mConnection = new RemoteConnection(mCallService, connectionId);
+                mPendingResponse.onResult(mPendingRequest, mConnection);
+                clearPendingInformation();
+            }
+        }
+
+        /** ${inheritDoc} */
+            @Override
+        public void handleFailedOutgoingCall(
+                ConnectionRequest request, int errorCode, String errorMessage) {
+            if (isPendingConnection(request.getCallId())) {
+                // Use mPendingRequest instead of request so that we use the same object that was
+                // passed in to us.
+                mPendingResponse.onError(request);
+                mConnectionId = null;
+                clearPendingInformation();
+            }
+        }
+
+        /** ${inheritDoc} */
+            @Override
+        public void setActive(String connectionId) {
+            if (isCurrentConnection(connectionId)) {
+                mConnection.setState(Connection.State.ACTIVE);
+            }
+        }
+
+        /** ${inheritDoc} */
+            @Override
+        public void setRinging(String connectionId) {
+            if (isCurrentConnection(connectionId)) {
+                mConnection.setState(Connection.State.RINGING);
+            }
+        }
+
+        /** ${inheritDoc} */
+            @Override
+        public void setDialing(String connectionId) {
+            if (isCurrentConnection(connectionId)) {
+                mConnection.setState(Connection.State.DIALING);
+            }
+        }
+
+        /** ${inheritDoc} */
+            @Override
+        public void setDisconnected(
+                String connectionId, int disconnectCause, String disconnectMessage) {
+            if (isCurrentConnection(connectionId)) {
+                mConnection.setDisconnected(disconnectCause, disconnectMessage);
+            }
+        }
+
+        /** ${inheritDoc} */
+            @Override
+        public void setOnHold(String connectionId) {
+            if (isCurrentConnection(connectionId)) {
+                mConnection.setState(Connection.State.HOLDING);
+            }
+        }
+
+        /** ${inheritDoc} */
+            @Override
+        public void setRequestingRingback(String connectionId, boolean isRequestingRingback) {
+            if (isCurrentConnection(connectionId)) {
+                mConnection.setRequestingRingback(isRequestingRingback);
+            }
+        }
+
+        /** ${inheritDoc} */
+            @Override
+        public void setCanConference(String connectionId, boolean canConference) {
+            // not supported for remote connections.
+        }
+
+        /** ${inheritDoc} */
+            @Override
+        public void setIsConferenced(String connectionId, String conferenceConnectionId) {
+            // not supported for remote connections.
+        }
+
+        /** ${inheritDoc} */
+            @Override
+        public void addConferenceCall(String connectionId, CallInfo callInfo) {
+            // not supported for remote connections.
+        }
+
+        /** ${inheritDoc} */
+            @Override
+        public void removeCall(String connectionId) {
+            if (isCurrentConnection(connectionId)) {
+                destroyConnection();
+            }
+        }
+
+        /** ${inheritDoc} */
+            @Override
+        public void onPostDialWait(String connectionId, String remainingDigits) {
+            if (isCurrentConnection(connectionId)) {
+                mConnection.setPostDialWait(remainingDigits);
+            }
+        }
+
+        /** ${inheritDoc} */
+            @Override
+        public void handoffCall(String connectionId) {
+            // unnecessary.
+        }
+
+        /** ${inheritDoc} */
+        @Override
+        public void queryRemoteConnectionServices(RemoteServiceCallback callback) {
+            try {
+                // Not supported from remote connection service.
+                callback.onError();
+            } catch (RemoteException e) {
+            }
+        }
+    };
+
+    RemoteConnectionService(ComponentName componentName, ICallService callService)
+            throws RemoteException {
+        mComponentName = componentName;
+        mCallService = callService;
+
+        // TODO(santoscordon): Rename from setCallServiceAdapter to addCallServiceAdapter.
+        mCallService.setCallServiceAdapter(mAdapter);
+        mCallService.asBinder().linkToDeath(this, 0);
+    }
+
+    @Override
+    public String toString() {
+        return "[RemoteCS - " + mCallService.asBinder().toString() + "]";
+    }
+
+    /** ${inheritDoc} */
+    @Override
+    public void binderDied() {
+        if (mConnection != null) {
+            destroyConnection();
+        }
+
+        release();
+    }
+
+    /**
+     * Places an outgoing call.
+     */
+    public void createOutgoingConnection(
+            ConnectionRequest request,
+            SimpleResponse<ConnectionRequest, RemoteConnection> response) {
+
+        if (mConnectionId == null) {
+            String id = UUID.randomUUID().toString();
+            CallInfo callInfo = new CallInfo(id, CallState.NEW, request.getHandle());
+            try {
+                mCallService.call(callInfo);
+                mConnectionId = id;
+                mPendingResponse = response;
+                mPendingRequest = request;
+            } catch (RemoteException e) {
+                response.onError(request);
+            }
+        } else {
+            response.onError(request);
+        }
+    }
+
+    // TODO(santoscordon): Handle incoming connections
+    // public void handleIncomingConnection() {}
+
+    public List<Subscription> lookupSubscriptions(Uri handle) {
+        // TODO(santoscordon): Update this so that is actually calls into the RemoteConnection
+        // each time.
+        List<Subscription> subscriptions = new LinkedList<>();
+        subscriptions.add(new Subscription(
+                mComponentName,
+                null /* id */,
+                null /* handle */,
+                0 /* labelResId */,
+                0 /* shortDescriptionResId */,
+                0 /* iconResId */,
+                true /* isEnabled */,
+                false /* isSystemDefault */));
+        return subscriptions;
+    }
+
+    /**
+     * Releases the resources associated with this Remote connection service. Should be called when
+     * the remote service is no longer being used.
+     */
+    void release() {
+        mCallService.asBinder().unlinkToDeath(this, 0);
+    }
+
+    private boolean isPendingConnection(String id) {
+        return TextUtils.equals(mConnectionId, id) && mPendingResponse != null;
+    }
+
+    private boolean isCurrentConnection(String id) {
+        return mConnection != null && TextUtils.equals(mConnectionId, id);
+    }
+
+    private void clearPendingInformation() {
+        mPendingRequest = null;
+        mPendingResponse = null;
+    }
+
+    private void destroyConnection() {
+        mConnection.setDestroyed();
+        mConnection = null;
+        mConnectionId = null;
+    }
+}
diff --git a/telecomm/java/android/telecomm/SimpleResponse.java b/telecomm/java/android/telecomm/SimpleResponse.java
new file mode 100644
index 0000000..8e84adb
--- /dev/null
+++ b/telecomm/java/android/telecomm/SimpleResponse.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+package android.telecomm;
+
+/**
+ * Used to inform a client of asynchronously returned results.
+ */
+public interface SimpleResponse<IN, OUT> {
+
+    /**
+     * Provide a set of results.
+     *
+     * @param request The original request.
+     * @param result The results.
+     */
+    void onResult(IN request, OUT result);
+
+    /**
+     * Indicates the inability to provide results.
+     *
+     * @param request The original request.
+     */
+    void onError(IN request);
+}
diff --git a/telecomm/java/android/telecomm/TelecommConstants.java b/telecomm/java/android/telecomm/TelecommConstants.java
index 0a12c08..4c08da0 100644
--- a/telecomm/java/android/telecomm/TelecommConstants.java
+++ b/telecomm/java/android/telecomm/TelecommConstants.java
@@ -51,11 +51,6 @@
     public static final String ACTION_CALL_SERVICE = CallService.class.getName();
 
     /**
-     * The service action used to bind to {@link CallServiceSelector} implementations.
-     */
-    public static final String ACTION_CALL_SERVICE_SELECTOR = CallServiceSelector.class.getName();
-
-    /**
      * Optional extra for {@link Intent#ACTION_CALL} containing a boolean that determines whether
      * the speakerphone should be automatically turned on for an outgoing call.
      */
diff --git a/telecomm/java/com/android/internal/telecomm/ICallService.aidl b/telecomm/java/com/android/internal/telecomm/ICallService.aidl
index 827f331..62ebd54 100644
--- a/telecomm/java/com/android/internal/telecomm/ICallService.aidl
+++ b/telecomm/java/com/android/internal/telecomm/ICallService.aidl
@@ -32,8 +32,6 @@
 oneway interface ICallService {
     void setCallServiceAdapter(in ICallServiceAdapter callServiceAdapter);
 
-    void isCompatibleWith(in CallInfo callInfo);
-
     void call(in CallInfo callInfo);
 
     void abort(String callId);
diff --git a/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl b/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl
index 6e176eb..87c8859 100644
--- a/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl
@@ -19,6 +19,8 @@
 import android.telecomm.CallInfo;
 import android.telecomm.ConnectionRequest;
 
+import com.android.internal.telecomm.RemoteServiceCallback;
+
 /**
  * Internal remote callback interface for call services.
  *
@@ -27,8 +29,6 @@
  * {@hide}
  */
 oneway interface ICallServiceAdapter {
-    void setIsCompatibleWith(String callId, boolean isCompatible);
-
     void notifyIncomingCall(in CallInfo callInfo);
 
     void handleSuccessfulOutgoingCall(String callId);
@@ -58,4 +58,6 @@
     void onPostDialWait(String callId, String remaining);
 
     void handoffCall(String callId);
+
+    void queryRemoteConnectionServices(RemoteServiceCallback callback);
 }
diff --git a/telecomm/java/com/android/internal/telecomm/ICallServiceSelector.aidl b/telecomm/java/com/android/internal/telecomm/ICallServiceSelector.aidl
deleted file mode 100644
index 9597dc1..0000000
--- a/telecomm/java/com/android/internal/telecomm/ICallServiceSelector.aidl
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.internal.telecomm;
-
-import android.telecomm.CallInfo;
-import android.telecomm.CallServiceDescriptor;
-
-import com.android.internal.telecomm.ICallService;
-import com.android.internal.telecomm.ICallServiceSelectorAdapter;
-
-import java.util.List;
-
-/**
- * Internal remote interface for call service selectors.
- *
- * @see android.telecomm.CallServiceSelector
- *
- * @hide
- */
-oneway interface ICallServiceSelector {
-    void setCallServiceSelectorAdapter(in ICallServiceSelectorAdapter adapter);
-
-    void select(in CallInfo callInfo, in List<CallServiceDescriptor> callServiceDescriptors);
-
-    void onCallUpdated(in CallInfo callInfo);
-
-    void onCallRemoved(String callId);
-}
diff --git a/telecomm/java/com/android/internal/telecomm/ICallServiceSelectorAdapter.aidl b/telecomm/java/com/android/internal/telecomm/ICallServiceSelectorAdapter.aidl
deleted file mode 100644
index ad71e3c..0000000
--- a/telecomm/java/com/android/internal/telecomm/ICallServiceSelectorAdapter.aidl
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.internal.telecomm;
-
-import android.net.Uri;
-import android.os.Bundle;
-import android.telecomm.CallInfo;
-import android.telecomm.CallServiceDescriptor;
-
-import java.util.List;
-
-/**
- * Internal remote interface for call service selector adapter.
- *
- * @see android.telecomm.CallServiceSelectorAdapter
- *
- * @hide
- */
-oneway interface ICallServiceSelectorAdapter {
-    void setSelectedCallServices(
-            String callId,
-            in List<CallServiceDescriptor> selectedCallServiceDescriptors);
-
-    void cancelOutgoingCall(String callId);
-
-    void setHandoffInfo(String callId, in Uri handle, in Bundle extras);
-}
diff --git a/telecomm/java/com/android/internal/telecomm/RemoteServiceCallback.aidl b/telecomm/java/com/android/internal/telecomm/RemoteServiceCallback.aidl
new file mode 100644
index 0000000..42c77d7
--- /dev/null
+++ b/telecomm/java/com/android/internal/telecomm/RemoteServiceCallback.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+package com.android.internal.telecomm;
+
+import android.content.ComponentName;
+
+/**
+ * Simple response callback object.
+ */
+oneway interface RemoteServiceCallback {
+    void onError();
+    void onResult(in List<ComponentName> components, in List<IBinder> callServices);
+}
diff --git a/telephony/java/com/android/internal/telephony/ISms.aidl b/telephony/java/com/android/internal/telephony/ISms.aidl
index 9e975e9..53429b6 100644
--- a/telephony/java/com/android/internal/telephony/ISms.aidl
+++ b/telephony/java/com/android/internal/telephony/ISms.aidl
@@ -223,6 +223,17 @@
     void injectSmsPdu(in byte[] pdu, String format, in PendingIntent receivedIntent);
 
     /**
+     * Update the status of a pending (send-by-IP) SMS message and resend by PSTN if necessary.
+     * This outbound message was handled by the carrier app. If the carrier app fails to send
+     * this message, it would be resent by PSTN.
+     *
+     * @param messageRef the reference number of the SMS message.
+     * @param success True if and only if the message was sent successfully. If its value is
+     *  false, this message should be resent via PSTN.
+     */
+    void updateSmsSendStatus(int messageRef, boolean success);
+
+    /**
      * Send a multi-part text based SMS.
      *
      * @param destinationAddress the address to send the message to
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 2b884ae..1d10729 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -44,6 +44,7 @@
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
+import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.os.UserHandle;
@@ -733,4 +734,11 @@
             int targetUserId) {
         throw new UnsupportedOperationException();
     }
+
+    /**
+     * @hide
+     */
+    public Bitmap getUserIcon(int userId) {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index cc0da15..816033e 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -407,6 +407,8 @@
     ICON_ATTR = 0x01010002,
     NAME_ATTR = 0x01010003,
     PERMISSION_ATTR = 0x01010006,
+    EXPORTED_ATTR = 0x01010010,
+    GRANT_URI_PERMISSIONS_ATTR = 0x0101001b,
     RESOURCE_ATTR = 0x01010025,
     DEBUGGABLE_ATTR = 0x0101000f,
     VALUE_ATTR = 0x01010024,
@@ -582,6 +584,10 @@
     return categories;
 }
 
+static void printComponentPresence(const char* componentName) {
+    printf("provides-component:'%s'\n", componentName);
+}
+
 /*
  * Handle the "dump" command, to extract select data from an archive.
  */
@@ -793,19 +799,27 @@
             bool withinSupportsInput = false;
             bool withinReceiver = false;
             bool withinService = false;
+            bool withinProvider = false;
             bool withinIntentFilter = false;
             bool hasMainActivity = false;
             bool hasOtherActivities = false;
             bool hasOtherReceivers = false;
             bool hasOtherServices = false;
+            bool hasIntentFilter = false;
+
             bool hasWallpaperService = false;
             bool hasImeService = false;
             bool hasAccessibilityService = false;
             bool hasPrintService = false;
             bool hasWidgetReceivers = false;
             bool hasDeviceAdminReceiver = false;
-            bool hasIntentFilter = false;
             bool hasPaymentService = false;
+            bool hasDocumentsProvider = false;
+            bool hasCameraActivity = false;
+            bool hasCameraSecureActivity = false;
+            bool hasLauncher = false;
+            bool hasNotificationListenerService = false;
+
             bool actMainActivity = false;
             bool actWidgetReceivers = false;
             bool actDeviceAdminEnabled = false;
@@ -815,6 +829,11 @@
             bool actPrintService = false;
             bool actHostApduService = false;
             bool actOffHostApduService = false;
+            bool actDocumentsProvider = false;
+            bool actNotificationListenerService = false;
+            bool actCamera = false;
+            bool actCameraSecure = false;
+            bool catLauncher = false;
             bool hasMetaHostPaymentCategory = false;
             bool hasMetaOffHostPaymentCategory = false;
 
@@ -825,6 +844,8 @@
             bool hasBindAccessibilityServicePermission = false;
             bool hasBindPrintServicePermission = false;
             bool hasBindNfcServicePermission = false;
+            bool hasRequiredSafAttributes = false;
+            bool hasBindNotificationListenerServicePermission = false;
 
             // These two implement the implicit permissions that are granted
             // to pre-1.6 applications.
@@ -962,13 +983,17 @@
                         withinActivity = false;
                         withinService = false;
                         withinReceiver = false;
+                        withinProvider = false;
                         hasIntentFilter = false;
                         isMainActivity = isLauncherActivity = isLeanbackLauncherActivity = false;
                     } else if (depth < 4) {
                         if (withinIntentFilter) {
                             if (withinActivity) {
                                 hasMainActivity |= actMainActivity;
-                                hasOtherActivities |= !actMainActivity;
+                                hasLauncher |= catLauncher;
+                                hasCameraActivity |= actCamera;
+                                hasCameraSecureActivity |= actCameraSecure;
+                                hasOtherActivities |= !actMainActivity && !actCamera && !actCameraSecure;
                             } else if (withinReceiver) {
                                 hasWidgetReceivers |= actWidgetReceivers;
                                 hasDeviceAdminReceiver |= (actDeviceAdminEnabled &&
@@ -980,9 +1005,14 @@
                                 hasAccessibilityService |= (actAccessibilityService &&
                                         hasBindAccessibilityServicePermission);
                                 hasPrintService |= (actPrintService && hasBindPrintServicePermission);
+                                hasNotificationListenerService |= actNotificationListenerService &&
+                                        hasBindNotificationListenerServicePermission;
                                 hasOtherServices |= (!actImeService && !actWallpaperService &&
                                         !actAccessibilityService && !actPrintService &&
-                                        !actHostApduService && !actOffHostApduService);
+                                        !actHostApduService && !actOffHostApduService &&
+                                        !actNotificationListenerService);
+                            } else if (withinProvider) {
+                                hasDocumentsProvider |= actDocumentsProvider && hasRequiredSafAttributes;
                             }
                         }
                         withinIntentFilter = false;
@@ -1348,6 +1378,7 @@
                     withinActivity = false;
                     withinReceiver = false;
                     withinService = false;
+                    withinProvider = false;
                     hasIntentFilter = false;
                     hasMetaHostPaymentCategory = false;
                     hasMetaOffHostPaymentCategory = false;
@@ -1356,6 +1387,8 @@
                     hasBindAccessibilityServicePermission = false;
                     hasBindPrintServicePermission = false;
                     hasBindNfcServicePermission = false;
+                    hasRequiredSafAttributes = false;
+                    hasBindNotificationListenerServicePermission = false;
                     if (withinApplication) {
                         if(tag == "activity") {
                             withinActivity = true;
@@ -1451,11 +1484,41 @@
                                     hasBindPrintServicePermission = true;
                                 } else if (permission == "android.permission.BIND_NFC_SERVICE") {
                                     hasBindNfcServicePermission = true;
+                                } else if (permission == "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE") {
+                                    hasBindNotificationListenerServicePermission = true;
                                 }
                             } else {
                                 fprintf(stderr, "ERROR getting 'android:permission' attribute for"
                                         " service '%s': %s\n", serviceName.string(), error.string());
                             }
+                        } else if (tag == "provider") {
+                            withinProvider = true;
+
+                            bool exported = getResolvedIntegerAttribute(&res, tree, EXPORTED_ATTR, &error);
+                            if (error != "") {
+                                fprintf(stderr, "ERROR getting 'android:exported' attribute for provider:"
+                                        " %s\n", error.string());
+                                goto bail;
+                            }
+
+                            bool grantUriPermissions = getResolvedIntegerAttribute(&res, tree,
+                                    GRANT_URI_PERMISSIONS_ATTR, &error);
+                            if (error != "") {
+                                fprintf(stderr, "ERROR getting 'android:grantUriPermissions' attribute for provider:"
+                                        " %s\n", error.string());
+                                goto bail;
+                            }
+
+                            String8 permission = getResolvedAttribute(&res, tree, PERMISSION_ATTR, &error);
+                            if (error != "") {
+                                fprintf(stderr, "ERROR getting 'android:permission' attribute for provider:"
+                                        " %s\n", error.string());
+                                goto bail;
+                            }
+
+                            hasRequiredSafAttributes |= exported && grantUriPermissions &&
+                                permission == "android.permission.MANAGE_DOCUMENTS";
+
                         } else if (bundle->getIncludeMetaData() && tag == "meta-data") {
                             String8 metaDataName = getResolvedAttribute(&res, tree, NAME_ATTR, &error);
                             if (error != "") {
@@ -1504,6 +1567,11 @@
                         actDeviceAdminEnabled = false;
                         actHostApduService = false;
                         actOffHostApduService = false;
+                        actDocumentsProvider = false;
+                        actNotificationListenerService = false;
+                        actCamera = false;
+                        actCameraSecure = false;
+                        catLauncher = false;
                     } else if (withinService && tag == "meta-data") {
                         String8 name = getAttribute(tree, NAME_ATTR, &error);
                         if (error != "") {
@@ -1559,6 +1627,11 @@
                             if (action == "android.intent.action.MAIN") {
                                 isMainActivity = true;
                                 actMainActivity = true;
+                            } else if (action == "android.media.action.STILL_IMAGE_CAMERA" ||
+                                    action == "android.media.action.VIDEO_CAMERA") {
+                                actCamera = true;
+                            } else if (action == "android.media.action.STILL_IMAGE_CAMERA_SECURE") {
+                                actCameraSecure = true;
                             }
                         } else if (withinReceiver) {
                             if (action == "android.appwidget.action.APPWIDGET_UPDATE") {
@@ -1579,6 +1652,12 @@
                                 actHostApduService = true;
                             } else if (action == "android.nfc.cardemulation.action.OFF_HOST_APDU_SERVICE") {
                                 actOffHostApduService = true;
+                            } else if (action == "android.service.notification.NotificationListenerService") {
+                                actNotificationListenerService = true;
+                            }
+                        } else if (withinProvider) {
+                            if (action == "android.content.action.DOCUMENTS_PROVIDER") {
+                                actDocumentsProvider = true;
                             }
                         }
                         if (action == "android.intent.action.SEARCH") {
@@ -1598,6 +1677,8 @@
                                 isLauncherActivity = true;
                             } else if (category == "android.intent.category.LEANBACK_LAUNCHER") {
                                 isLeanbackLauncherActivity = true;
+                            } else if (category == "android.intent.category.HOME") {
+                                catLauncher = true;
                             }
                         }
                     }
@@ -1775,37 +1856,53 @@
                 }
             }
 
-            if (hasMainActivity) {
-                printf("main\n");
-            }
             if (hasWidgetReceivers) {
-                printf("app-widget\n");
+                printComponentPresence("app-widget");
             }
             if (hasDeviceAdminReceiver) {
-                printf("device-admin\n");
+                printComponentPresence("device-admin");
             }
             if (hasImeService) {
-                printf("ime\n");
+                printComponentPresence("ime");
             }
             if (hasWallpaperService) {
-                printf("wallpaper\n");
+                printComponentPresence("wallpaper");
             }
             if (hasAccessibilityService) {
-                printf("accessibility\n");
+                printComponentPresence("accessibility");
             }
             if (hasPrintService) {
-                printf("print\n");
+                printComponentPresence("print-service");
             }
             if (hasPaymentService) {
-                printf("payment\n");
+                printComponentPresence("payment");
+            }
+            if (isSearchable) {
+                printComponentPresence("search");
+            }
+            if (hasDocumentsProvider) {
+                printComponentPresence("document-provider");
+            }
+            if (hasLauncher) {
+                printComponentPresence("launcher");
+            }
+            if (hasNotificationListenerService) {
+                printComponentPresence("notification-listener");
+            }
+            if (hasCameraActivity) {
+                printComponentPresence("camera");
+            }
+            if (hasCameraSecureActivity) {
+                printComponentPresence("camera-secure");
+            }
+
+            if (hasMainActivity) {
+                printf("main\n");
             }
             if (hasOtherActivities) {
                 printf("other-activities\n");
             }
-            if (isSearchable) {
-                printf("search\n");
-            }
-            if (hasOtherReceivers) {
+             if (hasOtherReceivers) {
                 printf("other-receivers\n");
             }
             if (hasOtherServices) {
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi-v21/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/hdpi-v21/ic_sysbar_back.png
new file mode 100644
index 0000000..b28624f
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/hdpi-v21/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi-v21/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/hdpi-v21/ic_sysbar_home.png
new file mode 100644
index 0000000..3f3e288
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/hdpi-v21/ic_sysbar_home.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi-v21/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/hdpi-v21/ic_sysbar_recent.png
new file mode 100644
index 0000000..06dcd20
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/hdpi-v21/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back.png
index b28624f..84e6bc8 100644
--- a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back.png
+++ b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home.png
index 3f3e288..38e4f45 100644
--- a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home.png
+++ b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_home.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent.png
index 06dcd20..bf9f300 100644
--- a/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent.png
+++ b/tools/layoutlib/bridge/resources/bars/hdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/ldrtl-hdpi-v21/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/ldrtl-hdpi-v21/ic_sysbar_back.png
new file mode 100644
index 0000000..e464347
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/ldrtl-hdpi-v21/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/ldrtl-hdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/ldrtl-hdpi/ic_sysbar_back.png
index e464347..782ebfe 100644
--- a/tools/layoutlib/bridge/resources/bars/ldrtl-hdpi/ic_sysbar_back.png
+++ b/tools/layoutlib/bridge/resources/bars/ldrtl-hdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/ldrtl-hdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/ldrtl-hdpi/ic_sysbar_recent.png
new file mode 100644
index 0000000..677b471
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/ldrtl-hdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/ldrtl-mdpi-v21/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/ldrtl-mdpi-v21/ic_sysbar_back.png
new file mode 100644
index 0000000..1b578a6
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/ldrtl-mdpi-v21/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/ldrtl-mdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/ldrtl-mdpi/ic_sysbar_back.png
index 1b578a6..a1b8062 100644
--- a/tools/layoutlib/bridge/resources/bars/ldrtl-mdpi/ic_sysbar_back.png
+++ b/tools/layoutlib/bridge/resources/bars/ldrtl-mdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/ldrtl-mdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/ldrtl-mdpi/ic_sysbar_recent.png
new file mode 100644
index 0000000..fcdbefe
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/ldrtl-mdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi-v21/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi-v21/ic_sysbar_back.png
new file mode 100644
index 0000000..373e84a
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi-v21/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi/ic_sysbar_back.png
index 373e84a..633d864 100644
--- a/tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi/ic_sysbar_back.png
+++ b/tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi/ic_sysbar_recent.png
new file mode 100644
index 0000000..4665e2a
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/ldrtl-xhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi-v21/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/mdpi-v21/ic_sysbar_back.png
new file mode 100644
index 0000000..f878093
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/mdpi-v21/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi-v21/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/mdpi-v21/ic_sysbar_home.png
new file mode 100644
index 0000000..8e9583b
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/mdpi-v21/ic_sysbar_home.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi-v21/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/mdpi-v21/ic_sysbar_recent.png
new file mode 100644
index 0000000..e2a89c3
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/mdpi-v21/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back.png
index f878093..a00bc5b 100644
--- a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back.png
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home.png
index 8e9583b..dc3183b 100644
--- a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home.png
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_home.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent.png
index e2a89c3..b07f611 100644
--- a/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent.png
+++ b/tools/layoutlib/bridge/resources/bars/mdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi-v21/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/xhdpi-v21/ic_sysbar_back.png
new file mode 100644
index 0000000..ec2951d
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/xhdpi-v21/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi-v21/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/xhdpi-v21/ic_sysbar_home.png
new file mode 100644
index 0000000..254f757
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/xhdpi-v21/ic_sysbar_home.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi-v21/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/xhdpi-v21/ic_sysbar_recent.png
new file mode 100644
index 0000000..8a8e941
--- /dev/null
+++ b/tools/layoutlib/bridge/resources/bars/xhdpi-v21/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back.png
index ec2951d..bd60cd6 100644
--- a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back.png
+++ b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_back.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home.png
index 254f757..c5bc5c9 100644
--- a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home.png
+++ b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_home.png
Binary files differ
diff --git a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent.png b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent.png
index 8a8e941..f621d9c 100644
--- a/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent.png
+++ b/tools/layoutlib/bridge/resources/bars/xhdpi/ic_sysbar_recent.png
Binary files differ
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
index 06673c1..9cf777d 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
@@ -16,6 +16,7 @@
 
 package android.graphics;
 
+import com.android.annotations.Nullable;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.impl.DelegateManager;
 import com.android.ninepatch.NinePatchChunk;
@@ -48,7 +49,7 @@
 
     @LayoutlibDelegate
     /*package*/ static Bitmap nativeDecodeStream(InputStream is, byte[] storage,
-            Rect padding, Options opts) {
+            @Nullable Rect padding, @Nullable Options opts) {
         Bitmap bm = null;
 
         Density density = Density.MEDIUM;
@@ -77,18 +78,20 @@
                 // put the chunk in the bitmap
                 bm.setNinePatchChunk(NinePatch_Delegate.serialize(chunk));
 
-                // read the padding
-                int[] paddingarray = chunk.getPadding();
-                padding.left = paddingarray[0];
-                padding.top = paddingarray[1];
-                padding.right = paddingarray[2];
-                padding.bottom = paddingarray[3];
+                if (padding != null) {
+                    // read the padding
+                    int[] paddingArray = chunk.getPadding();
+                    padding.left = paddingArray[0];
+                    padding.top = paddingArray[1];
+                    padding.right = paddingArray[2];
+                    padding.bottom = paddingArray[3];
+                }
             } else {
                 // load the bitmap directly.
                 bm = Bitmap_Delegate.createBitmap(is, bitmapCreateFlags, density);
             }
         } catch (IOException e) {
-            Bridge.getLog().error(null,"Failed to load image" , e, null);
+            Bridge.getLog().error(null, "Failed to load image", e, null);
         }
 
         return bm;
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index cd199dc..2ee06fc 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -627,8 +627,7 @@
                 // set the color
                 graphics.setColor(new Color(color, true /*alpha*/));
 
-                Composite composite = PorterDuffXfermode_Delegate.getComposite(
-                        PorterDuffXfermode_Delegate.getPorterDuffMode(mode), 0xFF);
+                Composite composite = PorterDuffXfermode_Delegate.getComposite(mode, 0xFF);
                 if (composite != null) {
                     graphics.setComposite(composite);
                 }
diff --git a/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java
index bf03a5e..bd934d0 100644
--- a/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/ColorFilter_Delegate.java
@@ -19,6 +19,8 @@
 import com.android.layoutlib.bridge.impl.DelegateManager;
 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
 
+import java.awt.Graphics2D;
+
 /**
  * Delegate implementing the native methods of android.graphics.ColorFilter
  *
@@ -50,9 +52,17 @@
         return sManager.getDelegate(nativeShader);
     }
 
-    public abstract boolean isSupported();
     public abstract String getSupportMessage();
 
+    public boolean isSupported() {
+        return false;
+    }
+
+    public void applyFilter(Graphics2D g, int width, int height) {
+        // This should never be called directly. If supported, the sub class should override this.
+        assert false;
+    }
+
     // ---- native methods ----
 
     @LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java
index 9aac2bd..6739484 100644
--- a/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/ColorMatrixColorFilter_Delegate.java
@@ -43,11 +43,6 @@
     // ---- Public Helper methods ----
 
     @Override
-    public boolean isSupported() {
-        return false;
-    }
-
-    @Override
     public String getSupportMessage() {
         return "ColorMatrix Color Filters are not supported.";
     }
diff --git a/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java
index 501d55c..0dd9703 100644
--- a/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/LightingColorFilter_Delegate.java
@@ -43,11 +43,6 @@
     // ---- Public Helper methods ----
 
     @Override
-    public boolean isSupported() {
-        return false;
-    }
-
-    @Override
     public String getSupportMessage() {
         return "Lighting Color Filters are not supported.";
     }
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
index c7c2e97..5adf4ca 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
@@ -827,8 +827,8 @@
 
         delegate.mColorFilter = ColorFilter_Delegate.getDelegate(filter);
 
-        // since none of those are supported, display a fidelity warning right away
-        if (delegate.mColorFilter != null && delegate.mColorFilter.isSupported() == false) {
+        // Log warning if it's not supported.
+        if (delegate.mColorFilter != null && !delegate.mColorFilter.isSupported()) {
             Bridge.getLog().fidelityWarning(LayoutLog.TAG_COLORFILTER,
                     delegate.mColorFilter.getSupportMessage(), null, null /*data*/);
         }
@@ -873,7 +873,7 @@
         delegate.mMaskFilter = MaskFilter_Delegate.getDelegate(maskfilter);
 
         // since none of those are supported, display a fidelity warning right away
-        if (delegate.mMaskFilter != null && delegate.mMaskFilter.isSupported() == false) {
+        if (delegate.mMaskFilter != null && !delegate.mMaskFilter.isSupported()) {
             Bridge.getLog().fidelityWarning(LayoutLog.TAG_MASKFILTER,
                     delegate.mMaskFilter.getSupportMessage(), null, null /*data*/);
         }
@@ -906,7 +906,7 @@
         delegate.mRasterizer = Rasterizer_Delegate.getDelegate(rasterizer);
 
         // since none of those are supported, display a fidelity warning right away
-        if (delegate.mRasterizer != null && delegate.mRasterizer.isSupported() == false) {
+        if (delegate.mRasterizer != null && !delegate.mRasterizer.isSupported()) {
             Bridge.getLog().fidelityWarning(LayoutLog.TAG_RASTERIZER,
                     delegate.mRasterizer.getSupportMessage(), null, null /*data*/);
         }
diff --git a/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java
index 1bc3033..ee90595 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java
@@ -19,6 +19,15 @@
 import com.android.layoutlib.bridge.impl.DelegateManager;
 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
 
+import android.graphics.PorterDuff.Mode;
+
+import java.awt.AlphaComposite;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+
+import static com.android.layoutlib.bridge.impl.PorterDuffUtility.getAlphaCompositeRule;
+import static com.android.layoutlib.bridge.impl.PorterDuffUtility.getPorterDuffMode;
+
 /**
  * Delegate implementing the native methods of android.graphics.PorterDuffColorFilter
  *
@@ -40,25 +49,102 @@
 
     // ---- delegate data ----
 
+    private final int mSrcColor;
+    private final Mode mMode;
+
+
     // ---- Public Helper methods ----
 
     @Override
     public boolean isSupported() {
-        return false;
+        return getAlphaCompositeRule(mMode) != -1;
     }
 
     @Override
     public String getSupportMessage() {
-        return "PorterDuff Color Filters are not supported.";
+        return "PorterDuff Color Filter is not supported for mode: " + mMode.name() + ".";
+    }
+
+    @Override
+    public void applyFilter(Graphics2D g, int width, int height) {
+        BufferedImage image = createFilterImage(width, height);
+        g.setComposite(getComposite());
+        g.drawImage(image, 0, 0, null);
     }
 
     // ---- native methods ----
 
     @LayoutlibDelegate
     /*package*/ static long native_CreatePorterDuffFilter(int srcColor, int porterDuffMode) {
-        PorterDuffColorFilter_Delegate newDelegate = new PorterDuffColorFilter_Delegate();
+        PorterDuffColorFilter_Delegate newDelegate =
+                new PorterDuffColorFilter_Delegate(srcColor, porterDuffMode);
         return sManager.addNewDelegate(newDelegate);
     }
 
+
     // ---- Private delegate/helper methods ----
+
+    private PorterDuffColorFilter_Delegate(int srcColor, int mode) {
+        mSrcColor = srcColor;
+        mMode = getCompatibleMode(getPorterDuffMode(mode));
+    }
+
+    private BufferedImage createFilterImage(int width, int height) {
+        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+        Graphics2D graphics = image.createGraphics();
+        try {
+            graphics.setColor(new java.awt.Color(mSrcColor, true /* hasAlpha */));
+            graphics.fillRect(0, 0, width, height);
+        } finally {
+            graphics.dispose();
+        }
+        return image;
+    }
+
+    private AlphaComposite getComposite() {
+        return AlphaComposite.getInstance(getAlphaCompositeRule(mMode));
+    }
+
+    // For filtering the colors, the src image should contain the "color" only for pixel values
+    // which are not transparent in the target image. But, we are using a simple rectangular image
+    // completely filled with color. Hence some AlphaComposite rules do not apply as intended.
+    // However, in such cases, they can usually be mapped to some other mode, which produces an
+    // equivalent result.
+    private Mode getCompatibleMode(Mode mode) {
+        Mode m = mode;
+        switch (mode) {
+            // Modes that are directly supported.
+            case CLEAR:
+            case DST:
+            case SRC_IN:
+            case DST_IN:
+            case DST_OUT:
+            case SRC_ATOP:
+                break;
+            // Modes that can be mapped to one of the supported modes.
+            case SRC:
+                m = Mode.SRC_IN;
+                break;
+            case SRC_OVER:
+                m = Mode.SRC_ATOP;
+                break;
+            case DST_OVER:
+                m = Mode.DST;
+                break;
+            case SRC_OUT:
+                m = Mode.CLEAR;
+                break;
+            case DST_ATOP:
+                m = Mode.DST_IN;
+                break;
+            case XOR:
+                m = Mode.DST_OUT;
+                break;
+            // This mode is not supported, but used by Action Bar Overflow Popup Menus. We map this
+            // to the closest supported mode, to prevent showing excessive warnings to the user.
+            case MULTIPLY:
+                m = Mode.SRC_IN;
+        }
+        return m;
+    }
 }
diff --git a/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
index a89fd57..f6c36b6 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PorterDuffXfermode_Delegate.java
@@ -21,9 +21,14 @@
 import com.android.layoutlib.bridge.impl.DelegateManager;
 import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
 
+import android.graphics.PorterDuff.Mode;
+
 import java.awt.AlphaComposite;
 import java.awt.Composite;
 
+import static com.android.layoutlib.bridge.impl.PorterDuffUtility.getAlphaCompositeRule;
+import static com.android.layoutlib.bridge.impl.PorterDuffUtility.getPorterDuffMode;
+
 /**
  * Delegate implementing the native methods of android.graphics.PorterDuffXfermode
  *
@@ -43,17 +48,17 @@
 
     // ---- delegate data ----
 
-    private final int mMode;
+    private final Mode mMode;
 
     // ---- Public Helper methods ----
 
-    public PorterDuff.Mode getMode() {
-        return getPorterDuffMode(mMode);
+    public Mode getMode() {
+        return mMode;
     }
 
     @Override
     public Composite getComposite(int alpha) {
-        return getComposite(getPorterDuffMode(mMode), alpha);
+        return getComposite(mMode, alpha);
     }
 
     @Override
@@ -67,61 +72,8 @@
         return null;
     }
 
-    public static PorterDuff.Mode getPorterDuffMode(int mode) {
-        for (PorterDuff.Mode m : PorterDuff.Mode.values()) {
-            if (m.nativeInt == mode) {
-                return m;
-            }
-        }
-
-        Bridge.getLog().error(LayoutLog.TAG_BROKEN,
-                String.format("Unknown PorterDuff.Mode: %d", mode), null /*data*/);
-        assert false;
-        return PorterDuff.Mode.SRC_OVER;
-    }
-
-    public static Composite getComposite(PorterDuff.Mode mode, int alpha) {
-        float falpha = alpha != 0xFF ? (float)alpha / 255.f : 1.f;
-        switch (mode) {
-            case CLEAR:
-                return AlphaComposite.getInstance(AlphaComposite.CLEAR, falpha);
-            case DARKEN:
-                break;
-            case DST:
-                return AlphaComposite.getInstance(AlphaComposite.DST, falpha);
-            case DST_ATOP:
-                return AlphaComposite.getInstance(AlphaComposite.DST_ATOP, falpha);
-            case DST_IN:
-                return AlphaComposite.getInstance(AlphaComposite.DST_IN, falpha);
-            case DST_OUT:
-                return AlphaComposite.getInstance(AlphaComposite.DST_OUT, falpha);
-            case DST_OVER:
-                return AlphaComposite.getInstance(AlphaComposite.DST_OVER, falpha);
-            case LIGHTEN:
-                break;
-            case MULTIPLY:
-                break;
-            case SCREEN:
-                break;
-            case SRC:
-                return AlphaComposite.getInstance(AlphaComposite.SRC, falpha);
-            case SRC_ATOP:
-                return AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, falpha);
-            case SRC_IN:
-                return AlphaComposite.getInstance(AlphaComposite.SRC_IN, falpha);
-            case SRC_OUT:
-                return AlphaComposite.getInstance(AlphaComposite.SRC_OUT, falpha);
-            case SRC_OVER:
-                return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha);
-            case XOR:
-                return AlphaComposite.getInstance(AlphaComposite.XOR, falpha);
-        }
-
-        Bridge.getLog().fidelityWarning(LayoutLog.TAG_BROKEN,
-                String.format("Unsupported PorterDuff Mode: %s", mode.name()),
-                null, null /*data*/);
-
-        return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, falpha);
+    public static Composite getComposite(int mode, int alpha) {
+        return getComposite(getPorterDuffMode(mode), alpha);
     }
 
     // ---- native methods ----
@@ -135,6 +87,20 @@
     // ---- Private delegate/helper methods ----
 
     private PorterDuffXfermode_Delegate(int mode) {
-        mMode = mode;
+        mMode = getPorterDuffMode(mode);
+    }
+
+    private static Composite getComposite(Mode mode, int alpha255) {
+        float alpha1 = alpha255 != 0xFF ? alpha255 / 255.f : 1.f;
+        int rule = getAlphaCompositeRule(mode);
+        if (rule >= 0) {
+            return AlphaComposite.getInstance(rule, alpha1);
+        }
+
+        Bridge.getLog().fidelityWarning(LayoutLog.TAG_BROKEN,
+                String.format("Unsupported PorterDuff Mode: %1$s", mode.name()),
+                null, null /*data*/);
+
+        return AlphaComposite.getInstance(AlphaComposite.SRC_OVER, alpha1);
     }
 }
diff --git a/tools/layoutlib/bridge/src/android/view/SurfaceView.java b/tools/layoutlib/bridge/src/android/view/SurfaceView.java
index 6aa4b3b..1e7dfbe 100644
--- a/tools/layoutlib/bridge/src/android/view/SurfaceView.java
+++ b/tools/layoutlib/bridge/src/android/view/SurfaceView.java
@@ -45,6 +45,10 @@
         super(context, attrs, defStyle);
     }
 
+    public SurfaceView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
     public SurfaceHolder getHolder() {
         return mSurfaceHolder;
     }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java
index 3d50b2a..4a9f718 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/MockView.java
@@ -31,7 +31,11 @@
 public class MockView extends TextView {
 
     public MockView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
+        this(context, attrs, defStyle, 0);
+    }
+
+    public MockView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
 
         setText(this.getClass().getSimpleName());
         setTextColor(0xFF000000);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 5c51c63..efd55bf 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -598,8 +598,7 @@
 
             if (item != null) {
                 // item is a reference to a style entry. Search for it.
-                item = mRenderResources.findResValue(item.getValue(),
-                        false /*forceFrameworkOnly*/);
+                item = mRenderResources.findResValue(item.getValue(), item.isFramework());
 
                 if (item instanceof StyleResourceValue) {
                     defStyleValues = (StyleResourceValue)item;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
index 86797e5..9bc86a0 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java
@@ -26,7 +26,6 @@
 import com.android.layoutlib.bridge.impl.ResourceHelper;
 import com.android.resources.Density;
 import com.android.resources.LayoutDirection;
-import com.android.resources.ResourceType;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -59,11 +58,14 @@
  */
 abstract class CustomBar extends LinearLayout {
 
+    private final int mSimulatedPlatformVersion;
+
     protected abstract TextView getStyleableTextView();
 
-    protected CustomBar(Context context, Density density, int orientation, String layoutPath,
-            String name) throws XmlPullParserException {
+    protected CustomBar(Context context, int orientation, String layoutPath,
+            String name, int simulatedPlatformVersion) throws XmlPullParserException {
         super(context);
+        mSimulatedPlatformVersion = simulatedPlatformVersion;
         setOrientation(orientation);
         if (orientation == LinearLayout.HORIZONTAL) {
             setGravity(Gravity.CENTER_VERTICAL);
@@ -100,7 +102,8 @@
             pathOut[0] = "/bars/" + density.getResourceValue() + "/" + iconName;
         }
 
-        InputStream stream = getClass().getResourceAsStream(pathOut[0]);
+        // TODO: Change this with a more generic method.
+        InputStream stream = getIconWithApi(pathOut, iconName);
         if (stream == null && tryOtherDensities) {
             for (Density d : Density.values()) {
                 if (d != density) {
@@ -121,6 +124,20 @@
         return stream;
     }
 
+    private InputStream getIconWithApi(String[] pathOut, String iconName) {
+        if (mSimulatedPlatformVersion == 0) {
+            String path = pathOut[0];
+            String dirName = path.substring(0, path.lastIndexOf('/'));
+            path = dirName + "-v21" + "/" + iconName;
+            InputStream stream = getClass().getResourceAsStream(path);
+            if (stream != null) {
+                pathOut[0] = path;
+                return stream;
+            }
+        }
+        return getClass().getResourceAsStream(pathOut[0]);
+    }
+
     protected void loadIcon(int index, String iconName, Density density) {
         loadIcon(index, iconName, density, false);
     }
@@ -158,65 +175,6 @@
         }
     }
 
-    protected void loadIcon(int index, String iconReference) {
-        ResourceValue value = getResourceValue(iconReference);
-        if (value != null) {
-            loadIcon(index, value);
-        }
-    }
-
-    protected void loadIconById(int id, String iconReference) {
-        ResourceValue value = getResourceValue(iconReference);
-        if (value != null) {
-            loadIconById(id, value);
-        }
-    }
-
-
-    protected Drawable loadIcon(int index, ResourceType type, String name) {
-        BridgeContext bridgeContext = (BridgeContext) mContext;
-        RenderResources res = bridgeContext.getRenderResources();
-
-        // find the resource
-        ResourceValue value = res.getFrameworkResource(type, name);
-
-        // resolve it if needed
-        value = res.resolveResValue(value);
-        return loadIcon(index, value);
-    }
-
-    private Drawable loadIcon(int index, ResourceValue value) {
-        View child = getChildAt(index);
-        if (child instanceof ImageView) {
-            ImageView imageView = (ImageView) child;
-
-            return loadIcon(imageView, value);
-        }
-
-        return null;
-    }
-
-    private Drawable loadIconById(int id, ResourceValue value) {
-        View child = findViewById(id);
-        if (child instanceof ImageView) {
-            ImageView imageView = (ImageView) child;
-
-            return loadIcon(imageView, value);
-        }
-
-        return null;
-    }
-
-
-    private Drawable loadIcon(ImageView imageView, ResourceValue value) {
-        Drawable drawable = ResourceHelper.getDrawable(value, (BridgeContext) mContext);
-        if (drawable != null) {
-            imageView.setImageDrawable(drawable);
-        }
-
-        return drawable;
-    }
-
     protected TextView setText(int index, String stringReference) {
         View child = getChildAt(index);
         if (child instanceof TextView) {
@@ -228,17 +186,6 @@
         return null;
     }
 
-    protected TextView setTextById(int id, String stringReference) {
-        View child = findViewById(id);
-        if (child instanceof TextView) {
-            TextView textView = (TextView) child;
-            setText(textView, stringReference);
-            return textView;
-        }
-
-        return null;
-    }
-
     private void setText(TextView textView, String stringReference) {
         ResourceValue value = getResourceValue(stringReference);
         if (value != null) {
@@ -256,7 +203,7 @@
         ResourceValue value = res.findItemInTheme(themeEntryName, true /*isFrameworkAttr*/);
         value = res.resolveResValue(value);
 
-        if (value instanceof StyleResourceValue == false) {
+        if (!(value instanceof StyleResourceValue)) {
             return;
         }
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
index 112c267..283ff57 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/NavigationBar.java
@@ -27,8 +27,9 @@
 public class NavigationBar extends CustomBar {
 
     public NavigationBar(Context context, Density density, int orientation, boolean isRtl,
-            boolean rtlEnabled) throws XmlPullParserException {
-        super(context, density, orientation, "/bars/navigation_bar.xml", "navigation_bar.xml");
+            boolean rtlEnabled, int simulatedPlatformVersion) throws XmlPullParserException {
+        super(context, orientation, "/bars/navigation_bar.xml", "navigation_bar.xml",
+                simulatedPlatformVersion);
 
         setBackgroundColor(0xFF000000);
 
@@ -44,8 +45,11 @@
             recent = 1;
         }
 
+        //noinspection SpellCheckingInspection
         loadIcon(back,   "ic_sysbar_back.png",   density, isRtl);
+        //noinspection SpellCheckingInspection
         loadIcon(2,      "ic_sysbar_home.png",   density, isRtl);
+        //noinspection SpellCheckingInspection
         loadIcon(recent, "ic_sysbar_recent.png", density, isRtl);
     }
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
index 2421f29..c9dd777 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/StatusBar.java
@@ -18,13 +18,10 @@
 
 import com.android.layoutlib.bridge.impl.Config;
 import com.android.resources.Density;
-import com.android.resources.ResourceType;
 
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.content.Context;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LevelListDrawable;
 import android.view.Gravity;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -34,7 +31,8 @@
     public StatusBar(Context context, Density density, int direction, boolean RtlEnabled,
             int simulatedPlatformVersion) throws XmlPullParserException {
         // FIXME: if direction is RTL but it's not enabled in application manifest, mirror this bar.
-        super(context, density, LinearLayout.HORIZONTAL, "/bars/status_bar.xml", "status_bar.xml");
+        super(context, LinearLayout.HORIZONTAL, "/bars/status_bar.xml", "status_bar.xml",
+                simulatedPlatformVersion);
 
         // FIXME: use FILL_H?
         setGravity(Gravity.START | Gravity.TOP | Gravity.RIGHT);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
index c27859f..ff952bd 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TitleBar.java
@@ -16,8 +16,6 @@
 
 package com.android.layoutlib.bridge.bars;
 
-import com.android.resources.Density;
-
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.content.Context;
@@ -28,9 +26,10 @@
 
     private TextView mTextView;
 
-    public TitleBar(Context context, Density density, String label)
+    public TitleBar(Context context, String label, int simulatedPlatformVersion)
             throws XmlPullParserException {
-        super(context, density, LinearLayout.HORIZONTAL, "/bars/title_bar.xml", "title_bar.xml");
+        super(context, LinearLayout.HORIZONTAL, "/bars/title_bar.xml", "title_bar.xml",
+                simulatedPlatformVersion);
 
         // Cannot access the inside items through id because no R.id values have been
         // created for them.
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java
index 21d6b1a..3a0321a 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java
@@ -21,6 +21,7 @@
 
 import android.graphics.Bitmap_Delegate;
 import android.graphics.Canvas;
+import android.graphics.ColorFilter_Delegate;
 import android.graphics.Paint;
 import android.graphics.Paint_Delegate;
 import android.graphics.Rect;
@@ -48,8 +49,8 @@
  * This is based on top of {@link Graphics2D} but can operate independently if none are available
  * yet when setting transforms and clip information.
  * <p>
- * This allows for drawing through {@link #draw(Drawable, Paint_Delegate)} and
- * {@link #draw(Drawable, Paint_Delegate)}
+ * This allows for drawing through {@link #draw(Drawable, Paint_Delegate, boolean, boolean)} and
+ * {@link #draw(Drawable)}
  *
  * Handling of layers (created with {@link Canvas#saveLayer(RectF, Paint, int)}) is handled through
  * a list of Graphics2D for each layers. The class actually maintains a list of {@link Layer}
@@ -203,7 +204,7 @@
      * called before the snapshot can be used to draw. Transform and clip operations are permitted
      * before.
      *
-     * @param image the image to associate to the snapshot or null.
+     * @param bitmap the image to associate to the snapshot or null.
      * @return the root snapshot
      */
     public static GcSnapshot createDefaultSnapshot(Bitmap_Delegate bitmap) {
@@ -557,7 +558,6 @@
      * Executes the Drawable's draw method, with a null paint delegate.
      * <p/>
      * Note that the method can be called several times if there are more than one active layer.
-     * @param drawable
      */
     public void draw(Drawable drawable) {
         draw(drawable, null, false /*compositeOnly*/, false /*forceSrcMode*/);
@@ -567,20 +567,19 @@
      * Executes the Drawable's draw method.
      * <p/>
      * Note that the method can be called several times if there are more than one active layer.
-     * @param drawable
-     * @param paint
      * @param compositeOnly whether the paint is used for composite only. This is typically
      *          the case for bitmaps.
      * @param forceSrcMode if true, this overrides the composite to be SRC
      */
     public void draw(Drawable drawable, Paint_Delegate paint, boolean compositeOnly,
             boolean forceSrcMode) {
+        int forceMode = forceSrcMode ? AlphaComposite.SRC : 0;
         // the current snapshot may not have a mLocalLayer (ie it was created on save() instead
         // of saveLayer(), but that doesn't mean there's no layer.
         // mLayers however saves all the information we need (flags).
         if (mLayers.size() == 1) {
             // no layer, only base layer. easy case.
-            drawInLayer(mLayers.get(0), drawable, paint, compositeOnly, forceSrcMode);
+            drawInLayer(mLayers.get(0), drawable, paint, compositeOnly, forceMode);
         } else {
             // draw in all the layers until the layer save flags tells us to stop (ie drawing
             // in that layer is limited to the layer itself.
@@ -590,7 +589,7 @@
             do {
                 Layer layer = mLayers.get(i);
 
-                drawInLayer(layer, drawable, paint, compositeOnly, forceSrcMode);
+                drawInLayer(layer, drawable, paint, compositeOnly, forceMode);
 
                 // then go to previous layer, only if there are any left, and its flags
                 // doesn't restrict drawing to the layer itself.
@@ -601,20 +600,61 @@
     }
 
     private void drawInLayer(Layer layer, Drawable drawable, Paint_Delegate paint,
-            boolean compositeOnly, boolean forceSrcMode) {
+            boolean compositeOnly, int forceMode) {
         Graphics2D originalGraphics = layer.getGraphics();
-        // get a Graphics2D object configured with the drawing parameters.
-        Graphics2D configuredGraphics2D =
-            paint != null ?
-                    createCustomGraphics(originalGraphics, paint, compositeOnly, forceSrcMode) :
-                        (Graphics2D) originalGraphics.create();
+        if (paint == null) {
+            drawOnGraphics((Graphics2D) originalGraphics.create(), drawable,
+                    null /*paint*/, layer);
+        } else {
+            ColorFilter_Delegate filter = paint.getColorFilter();
+            if (filter == null || !filter.isSupported()) {
+                // get a Graphics2D object configured with the drawing parameters.
+                Graphics2D configuredGraphics = createCustomGraphics(originalGraphics, paint,
+                        compositeOnly, forceMode);
+                drawOnGraphics(configuredGraphics, drawable, paint, layer);
+                return;
+            }
 
+            int width = layer.getImage().getWidth();
+            int height = layer.getImage().getHeight();
+
+            // Create a temporary image to which the color filter will be applied.
+            BufferedImage image = new BufferedImage(width, height,
+                    BufferedImage.TYPE_INT_ARGB);
+            Graphics2D imageBaseGraphics = (Graphics2D) image.getGraphics();
+            // Configure the Graphics2D object with drawing parameters and shader.
+            Graphics2D imageGraphics = createCustomGraphics(
+                    imageBaseGraphics, paint, compositeOnly,
+                    AlphaComposite.SRC_OVER);
+            // get a Graphics2D object configured with the drawing parameters, but no shader.
+            Graphics2D configuredGraphics = createCustomGraphics(originalGraphics, paint,
+                    true /*compositeOnly*/, forceMode);
+            try {
+                // The main draw operation.
+                drawable.draw(imageGraphics, paint);
+
+                // Apply the color filter.
+                filter.applyFilter(imageGraphics, width, height);
+
+                // Draw the tinted image on the main layer.
+                configuredGraphics.drawImage(image, 0, 0, null);
+                layer.change();
+            } finally {
+                // dispose Graphics2D objects
+                imageGraphics.dispose();
+                imageBaseGraphics.dispose();
+                configuredGraphics.dispose();
+            }
+        }
+    }
+
+    private void drawOnGraphics(Graphics2D g, Drawable drawable, Paint_Delegate paint,
+            Layer layer) {
         try {
-            drawable.draw(configuredGraphics2D, paint);
+            drawable.draw(g, paint);
             layer.change();
         } finally {
-            // dispose Graphics2D object
-            configuredGraphics2D.dispose();
+            g.dispose();
         }
     }
 
@@ -685,7 +725,7 @@
         // now draw put the content of the local layer onto the layer,
         // using the paint information
         Graphics2D g = createCustomGraphics(baseGfx, mLocalLayerPaint,
-                true /*alphaOnly*/, false /*forceSrcMode*/);
+                true /*alphaOnly*/, 0 /*forceMode*/);
 
         g.drawImage(mLocalLayer.getImage(),
                 mLayerBounds.left, mLayerBounds.top, mLayerBounds.right, mLayerBounds.bottom,
@@ -701,7 +741,7 @@
      * <p/>The object must be disposed ({@link Graphics2D#dispose()}) after being used.
      */
     private Graphics2D createCustomGraphics(Graphics2D original, Paint_Delegate paint,
-            boolean compositeOnly, boolean forceSrcMode) {
+            boolean compositeOnly, int forceMode) {
         // make new one graphics
         Graphics2D g = (Graphics2D) original.create();
 
@@ -714,70 +754,73 @@
                     RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
         }
 
+        // set the shader first, as it'll replace the color if it can be used it.
         boolean customShader = false;
-
-        // get the shader first, as it'll replace the color if it can be used it.
-        if (compositeOnly == false) {
-            Shader_Delegate shaderDelegate = paint.getShader();
-            if (shaderDelegate != null) {
-                if (shaderDelegate.isSupported()) {
-                    java.awt.Paint shaderPaint = shaderDelegate.getJavaPaint();
-                    assert shaderPaint != null;
-                    if (shaderPaint != null) {
-                        g.setPaint(shaderPaint);
-                        customShader = true;
-                    }
-                } else {
-                    Bridge.getLog().fidelityWarning(LayoutLog.TAG_SHADER,
-                            shaderDelegate.getSupportMessage(),
-                            null /*throwable*/, null /*data*/);
-                }
-            }
-
-            // if no shader, use the paint color
-            if (customShader == false) {
-                g.setColor(new Color(paint.getColor(), true /*hasAlpha*/));
-            }
-
+        if (!compositeOnly) {
+            customShader = setShader(g, paint);
             // set the stroke
             g.setStroke(paint.getJavaStroke());
         }
+        // set the composite.
+        setComposite(g, paint, compositeOnly || customShader, forceMode);
 
-        // the alpha for the composite. Always opaque if the normal paint color is used since
-        // it contains the alpha
-        int alpha = (compositeOnly || customShader) ? paint.getAlpha() : 0xFF;
+        return g;
+    }
 
-        if (forceSrcMode) {
-            g.setComposite(AlphaComposite.getInstance(
-                    AlphaComposite.SRC, (float) alpha / 255.f));
-        } else {
-            boolean customXfermode = false;
-            Xfermode_Delegate xfermodeDelegate = paint.getXfermode();
-            if (xfermodeDelegate != null) {
-                if (xfermodeDelegate.isSupported()) {
-                    Composite composite = xfermodeDelegate.getComposite(alpha);
-                    assert composite != null;
-                    if (composite != null) {
-                        g.setComposite(composite);
-                        customXfermode = true;
-                    }
-                } else {
-                    Bridge.getLog().fidelityWarning(LayoutLog.TAG_XFERMODE,
-                            xfermodeDelegate.getSupportMessage(),
-                            null /*throwable*/, null /*data*/);
+    private boolean setShader(Graphics2D g, Paint_Delegate paint) {
+        Shader_Delegate shaderDelegate = paint.getShader();
+        if (shaderDelegate != null) {
+            if (shaderDelegate.isSupported()) {
+                java.awt.Paint shaderPaint = shaderDelegate.getJavaPaint();
+                assert shaderPaint != null;
+                if (shaderPaint != null) {
+                    g.setPaint(shaderPaint);
+                    return true;
                 }
-            }
-
-            // if there was no custom xfermode, but we have alpha (due to a shader and a non
-            // opaque alpha channel in the paint color), then we create an AlphaComposite anyway
-            // that will handle the alpha.
-            if (customXfermode == false && alpha != 0xFF) {
-                g.setComposite(AlphaComposite.getInstance(
-                        AlphaComposite.SRC_OVER, (float) alpha / 255.f));
+            } else {
+                Bridge.getLog().fidelityWarning(LayoutLog.TAG_SHADER,
+                        shaderDelegate.getSupportMessage(),
+                        null /*throwable*/, null /*data*/);
             }
         }
 
-        return g;
+        // if no shader, use the paint color
+        g.setColor(new Color(paint.getColor(), true /*hasAlpha*/));
+
+        return false;
+    }
+
+    private void setComposite(Graphics2D g, Paint_Delegate paint, boolean usePaintAlpha,
+            int forceMode) {
+        // the alpha for the composite. Always opaque if the normal paint color is used since
+        // it contains the alpha
+        int alpha = usePaintAlpha ? paint.getAlpha() : 0xFF;
+        if (forceMode != 0) {
+            g.setComposite(AlphaComposite.getInstance(forceMode, (float) alpha / 255.f));
+            return;
+        }
+        Xfermode_Delegate xfermodeDelegate = paint.getXfermode();
+        if (xfermodeDelegate != null) {
+            if (xfermodeDelegate.isSupported()) {
+                Composite composite = xfermodeDelegate.getComposite(alpha);
+                assert composite != null;
+                if (composite != null) {
+                    g.setComposite(composite);
+                    return;
+                }
+            } else {
+                Bridge.getLog().fidelityWarning(LayoutLog.TAG_XFERMODE,
+                        xfermodeDelegate.getSupportMessage(),
+                        null /*throwable*/, null /*data*/);
+            }
+        }
+        // if there was no custom xfermode, but we have alpha (due to a shader and a non
+        // opaque alpha channel in the paint color), then we create an AlphaComposite anyway
+        // that will handle the alpha.
+        if (alpha != 0xFF) {
+            g.setComposite(AlphaComposite.getInstance(
+                    AlphaComposite.SRC_OVER, (float) alpha / 255.f));
+        }
     }
 
     private void mapRect(AffineTransform matrix, RectF dst, RectF src) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java
new file mode 100644
index 0000000..bc53e93
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/PorterDuffUtility.java
@@ -0,0 +1,96 @@
+/*
+ * 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.
+ */
+
+package com.android.layoutlib.bridge.impl;
+
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.layoutlib.bridge.Bridge;
+
+import android.graphics.PorterDuff.Mode;
+import android.graphics.PorterDuffColorFilter_Delegate;
+import android.graphics.PorterDuffXfermode_Delegate;
+
+import java.awt.AlphaComposite;
+
+/**
+ * Provides various utility methods for {@link PorterDuffColorFilter_Delegate} and {@link
+ * PorterDuffXfermode_Delegate}.
+ */
+public final class PorterDuffUtility {
+
+    // Make the class non-instantiable.
+    private PorterDuffUtility() {
+    }
+
+    /**
+     * Convert the porterDuffMode from the framework to its corresponding enum. This defaults to
+     * {@link Mode#SRC_OVER} for invalid modes.
+     */
+    public static Mode getPorterDuffMode(int porterDuffMode) {
+        Mode[] values = Mode.values();
+        if (porterDuffMode >= 0 && porterDuffMode < values.length) {
+            return values[porterDuffMode];
+        }
+        Bridge.getLog().error(LayoutLog.TAG_BROKEN,
+                String.format("Unknown PorterDuff.Mode: %1$d", porterDuffMode), null /*data*/);
+        assert false;
+        return Mode.SRC_OVER;
+    }
+
+    /**
+     * A utility method to convert the porterDuffMode to an int to be used as a rule for {@link
+     * AlphaComposite}. If {@code AlphaComposite} doesn't support the mode, -1 is returned.
+     */
+    public static int getAlphaCompositeRule(Mode porterDuffMode) {
+        switch (porterDuffMode) {
+            case CLEAR:
+                return AlphaComposite.CLEAR;
+            case DARKEN:
+                break;
+            case DST:
+                return AlphaComposite.DST;
+            case DST_ATOP:
+                return AlphaComposite.DST_ATOP;
+            case DST_IN:
+                return AlphaComposite.DST_IN;
+            case DST_OUT:
+                return AlphaComposite.DST_OUT;
+            case DST_OVER:
+                return AlphaComposite.DST_OVER;
+            case LIGHTEN:
+                break;
+            case MULTIPLY:
+                break;
+            case SCREEN:
+                break;
+            case SRC:
+                return AlphaComposite.SRC;
+            case SRC_ATOP:
+                return AlphaComposite.SRC_ATOP;
+            case SRC_IN:
+                return AlphaComposite.SRC_IN;
+            case SRC_OUT:
+                return AlphaComposite.SRC_OUT;
+            case SRC_OVER:
+                return AlphaComposite.SRC_OVER;
+            case XOR:
+                return AlphaComposite.XOR;
+        }
+        // This is an unsupported mode.
+        return -1;
+
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index c715003..07f72c4 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -247,6 +247,7 @@
                 backgroundView = mViewRoot = mContentRoot = new FrameLayout(context);
                 mViewRoot.setLayoutDirection(layoutDirection);
             } else {
+                int simulatedPlatformVersion = params.getSimulatedPlatformVersion();
                 if (hasSoftwareButtons() && mNavigationBarOrientation == LinearLayout.VERTICAL) {
                     /*
                      * This is a special case where the navigation bar is on the right.
@@ -271,10 +272,11 @@
                     mViewRoot = topLayout;
                     topLayout.setOrientation(LinearLayout.HORIZONTAL);
 
-                    if (Config.showOnScreenNavBar(params.getSimulatedPlatformVersion())) {
+                    if (Config.showOnScreenNavBar(simulatedPlatformVersion)) {
                         try {
                             NavigationBar navigationBar = createNavigationBar(context,
-                                    hardwareConfig.getDensity(), isRtl, params.isRtlSupported());
+                                    hardwareConfig.getDensity(), isRtl, params.isRtlSupported(),
+                                    simulatedPlatformVersion);
                             topLayout.addView(navigationBar);
                         } catch (XmlPullParserException ignored) {
                         }
@@ -331,7 +333,7 @@
                     try {
                         StatusBar statusBar = createStatusBar(context, hardwareConfig.getDensity(),
                                 layoutDirection, params.isRtlSupported(),
-                                params.getSimulatedPlatformVersion());
+                                simulatedPlatformVersion);
                         topLayout.addView(statusBar);
                     } catch (XmlPullParserException ignored) {
 
@@ -357,7 +359,8 @@
                 } else if (mTitleBarSize > 0) {
                     try {
                         TitleBar titleBar = createTitleBar(context,
-                                hardwareConfig.getDensity(), params.getAppLabel());
+                                params.getAppLabel(),
+                                simulatedPlatformVersion);
                         backgroundLayout.addView(titleBar);
                     } catch (XmlPullParserException ignored) {
 
@@ -374,13 +377,14 @@
                     backgroundLayout.addView(mContentRoot);
                 }
 
-                if (Config.showOnScreenNavBar(params.getSimulatedPlatformVersion()) &&
+                if (Config.showOnScreenNavBar(simulatedPlatformVersion) &&
                         mNavigationBarOrientation == LinearLayout.HORIZONTAL &&
                         mNavigationBarSize > 0) {
                     // system bar
                     try {
                         NavigationBar navigationBar = createNavigationBar(context,
-                                hardwareConfig.getDensity(), isRtl, params.isRtlSupported());
+                                hardwareConfig.getDensity(), isRtl, params.isRtlSupported(),
+                                simulatedPlatformVersion);
                         topLayout.addView(navigationBar);
                     } catch (XmlPullParserException ignored) {
 
@@ -1592,10 +1596,11 @@
      *        is RTL aware.
      */
     private NavigationBar createNavigationBar(BridgeContext context, Density density,
-            boolean isRtl, boolean isRtlSupported) throws XmlPullParserException {
+            boolean isRtl, boolean isRtlSupported, int simulatedPlatformVersion)
+            throws XmlPullParserException {
         NavigationBar navigationBar = new NavigationBar(context,
                 density, mNavigationBarOrientation, isRtl,
-                isRtlSupported);
+                isRtlSupported, simulatedPlatformVersion);
         if (mNavigationBarOrientation == LinearLayout.VERTICAL) {
             navigationBar.setLayoutParams(new LinearLayout.LayoutParams(mNavigationBarSize,
                     LayoutParams.MATCH_PARENT));
@@ -1606,9 +1611,10 @@
         return navigationBar;
     }
 
-    private TitleBar createTitleBar(BridgeContext context, Density density, String title)
+    private TitleBar createTitleBar(BridgeContext context, String title,
+            int simulatedPlatformVersion)
             throws XmlPullParserException {
-        TitleBar titleBar = new TitleBar(context, density, title);
+        TitleBar titleBar = new TitleBar(context, title, simulatedPlatformVersion);
         titleBar.setLayoutParams(
                 new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, mTitleBarSize));
         return titleBar;