Merge "Allow I/O when installing providers." into lmp-mr1-dev
diff --git a/Android.mk b/Android.mk
index 22cc27b..b77c2ed 100644
--- a/Android.mk
+++ b/Android.mk
@@ -737,7 +737,8 @@
                  -samplegroup Sensors \
                  -samplegroup Testing \
                  -samplegroup UI \
-                 -samplegroup Views
+                 -samplegroup Views \
+                 -samplegroup Wearable
 
 ## SDK version identifiers used in the published docs
   # major[.minor] version for current SDK. (full releases only)
diff --git a/api/current.txt b/api/current.txt
index faf0b04..bfe8d7a 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -3052,9 +3052,10 @@
     method public android.graphics.Rect evaluate(float, android.graphics.Rect, android.graphics.Rect);
   }
 
-  public class StateListAnimator {
+  public class StateListAnimator implements java.lang.Cloneable {
     ctor public StateListAnimator();
     method public void addState(int[], android.animation.Animator);
+    method public android.animation.StateListAnimator clone();
     method public void jumpToCurrentState();
   }
 
@@ -4404,6 +4405,7 @@
     method public boolean inKeyguardRestrictedInputMode();
     method public boolean isKeyguardLocked();
     method public boolean isKeyguardSecure();
+    method public boolean isKeyguardInTrustedState();
     method public deprecated android.app.KeyguardManager.KeyguardLock newKeyguardLock(java.lang.String);
   }
 
@@ -16546,15 +16548,21 @@
     method public static java.lang.String[] decode(java.lang.String);
     method public static java.lang.String encode(java.lang.String...);
     field public static final java.lang.String ANIMAL_WILDLIFE = "ANIMAL_WILDLIFE";
+    field public static final java.lang.String ARTS = "ARTS";
     field public static final java.lang.String COMEDY = "COMEDY";
     field public static final java.lang.String DRAMA = "DRAMA";
     field public static final java.lang.String EDUCATION = "EDUCATION";
+    field public static final java.lang.String ENTERTAINMENT = "ENTERTAINMENT";
     field public static final java.lang.String FAMILY_KIDS = "FAMILY_KIDS";
     field public static final java.lang.String GAMING = "GAMING";
+    field public static final java.lang.String LIFE_STYLE = "LIFE_STYLE";
     field public static final java.lang.String MOVIES = "MOVIES";
+    field public static final java.lang.String MUSIC = "MUSIC";
     field public static final java.lang.String NEWS = "NEWS";
+    field public static final java.lang.String PREMIER = "PREMIER";
     field public static final java.lang.String SHOPPING = "SHOPPING";
     field public static final java.lang.String SPORTS = "SPORTS";
+    field public static final java.lang.String TECH_SCIENCE = "TECH_SCIENCE";
     field public static final java.lang.String TRAVEL = "TRAVEL";
   }
 
@@ -17034,6 +17042,7 @@
   }
 
   public class Network implements android.os.Parcelable {
+    method public void bindSocket(java.net.DatagramSocket) throws java.io.IOException;
     method public void bindSocket(java.net.Socket) throws java.io.IOException;
     method public int describeContents();
     method public java.net.InetAddress[] getAllByName(java.lang.String) throws java.net.UnknownHostException;
@@ -17153,7 +17162,7 @@
     field public static final java.lang.String PROXY_CHANGE_ACTION = "android.intent.action.PROXY_CHANGE";
   }
 
-  public class ProxyInfo implements android.os.Parcelable {
+  public deprecated class ProxyInfo implements android.os.Parcelable {
     method public static android.net.ProxyInfo buildDirectProxy(java.lang.String, int);
     method public static android.net.ProxyInfo buildDirectProxy(java.lang.String, int, java.util.List<java.lang.String>);
     method public static android.net.ProxyInfo buildPacProxy(android.net.Uri);
@@ -17200,7 +17209,7 @@
     method public static javax.net.SocketFactory getDefault(int);
     method public static javax.net.ssl.SSLSocketFactory getDefault(int, android.net.SSLSessionCache);
     method public java.lang.String[] getDefaultCipherSuites();
-    method public static org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
+    method public static deprecated org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(int, android.net.SSLSessionCache);
     method public static javax.net.ssl.SSLSocketFactory getInsecure(int, android.net.SSLSessionCache);
     method public byte[] getNpnSelectedProtocol(java.net.Socket);
     method public java.lang.String[] getSupportedCipherSuites();
@@ -17418,7 +17427,7 @@
 
 package android.net.http {
 
-  public final class AndroidHttpClient implements org.apache.http.client.HttpClient {
+  public final deprecated class AndroidHttpClient implements org.apache.http.client.HttpClient {
     method public void close();
     method public void disableCurlLogging();
     method public void enableCurlLogging(java.lang.String, int);
@@ -17436,8 +17445,8 @@
     method public org.apache.http.params.HttpParams getParams();
     method public static java.io.InputStream getUngzippedContent(org.apache.http.HttpEntity) throws java.io.IOException;
     method public static void modifyRequestToAcceptGzipResponse(org.apache.http.HttpRequest);
-    method public static android.net.http.AndroidHttpClient newInstance(java.lang.String, android.content.Context);
-    method public static android.net.http.AndroidHttpClient newInstance(java.lang.String);
+    method public static deprecated android.net.http.AndroidHttpClient newInstance(java.lang.String, android.content.Context);
+    method public static deprecated android.net.http.AndroidHttpClient newInstance(java.lang.String);
     method public static long parseDate(java.lang.String);
     field public static long DEFAULT_SYNC_MIN_GZIP_BYTES;
   }
@@ -28219,6 +28228,7 @@
     method public android.telecom.PhoneAccountHandle getAccountHandle();
     method public android.net.Uri getAddress();
     method public int getCapabilities();
+    method public int getColor();
     method public android.graphics.drawable.Drawable getIcon(android.content.Context);
     method public int getIconResId();
     method public java.lang.CharSequence getLabel();
@@ -28232,6 +28242,7 @@
     field public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 16; // 0x10
     field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
     field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int NO_COLOR = -1; // 0xffffffff
     field public static final java.lang.String SCHEME_SIP = "sip";
     field public static final java.lang.String SCHEME_TEL = "tel";
     field public static final java.lang.String SCHEME_VOICEMAIL = "voicemail";
@@ -28243,6 +28254,7 @@
     method public android.telecom.PhoneAccount build();
     method public android.telecom.PhoneAccount.Builder setAddress(android.net.Uri);
     method public android.telecom.PhoneAccount.Builder setCapabilities(int);
+    method public android.telecom.PhoneAccount.Builder setColor(int);
     method public android.telecom.PhoneAccount.Builder setIconResId(int);
     method public android.telecom.PhoneAccount.Builder setShortDescription(java.lang.CharSequence);
     method public android.telecom.PhoneAccount.Builder setSubscriptionAddress(android.net.Uri);
@@ -28821,6 +28833,9 @@
     ctor public SubInfoRecord();
     ctor public SubInfoRecord(long, java.lang.String, int, java.lang.String, int, int, java.lang.String, int, int, int[], int, int);
     method public int describeContents();
+    method public int getColor();
+    method public android.graphics.drawable.BitmapDrawable getIconDrawable();
+    method public java.lang.String getLabel();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
     field public int color;
@@ -30331,7 +30346,7 @@
     method public static java.lang.String formatShortFileSize(android.content.Context, long);
   }
 
-  public class Time {
+  public deprecated class Time {
     ctor public Time(java.lang.String);
     ctor public Time();
     ctor public Time(android.text.format.Time);
@@ -31702,7 +31717,7 @@
     field public final int mTag;
   }
 
-  public class FloatMath {
+  public deprecated class FloatMath {
     method public static float ceil(float);
     method public static float cos(float);
     method public static float exp(float);
@@ -34909,6 +34924,7 @@
     field public static final int FLAG_HARDWARE_ACCELERATED = 16777216; // 0x1000000
     field public static final int FLAG_IGNORE_CHEEK_PRESSES = 32768; // 0x8000
     field public static final int FLAG_KEEP_SCREEN_ON = 128; // 0x80
+    field public static final int FLAG_LAYOUT_ATTACHED_IN_DECOR = 1073741824; // 0x40000000
     field public static final int FLAG_LAYOUT_INSET_DECOR = 65536; // 0x10000
     field public static final int FLAG_LAYOUT_IN_OVERSCAN = 33554432; // 0x2000000
     field public static final int FLAG_LAYOUT_IN_SCREEN = 256; // 0x100
@@ -34958,6 +34974,7 @@
     field public static final int SOFT_INPUT_STATE_UNSPECIFIED = 0; // 0x0
     field public static final int SOFT_INPUT_STATE_VISIBLE = 4; // 0x4
     field public static final int TITLE_CHANGED = 64; // 0x40
+    field public static final int TYPE_ACCESSIBILITY_OVERLAY = 2032; // 0x7f0
     field public static final int TYPE_APPLICATION = 2; // 0x2
     field public static final int TYPE_APPLICATION_ATTACHED_DIALOG = 1003; // 0x3eb
     field public static final int TYPE_APPLICATION_MEDIA = 1001; // 0x3e9
@@ -35377,6 +35394,7 @@
     method public void recycle();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int TYPE_ACCESSIBILITY_OVERLAY = 4; // 0x4
     field public static final int TYPE_APPLICATION = 1; // 0x1
     field public static final int TYPE_INPUT_METHOD = 2; // 0x2
     field public static final int TYPE_SYSTEM = 3; // 0x3
@@ -35423,13 +35441,13 @@
 
 package android.view.animation {
 
-  public class AccelerateDecelerateInterpolator implements android.view.animation.Interpolator {
+  public class AccelerateDecelerateInterpolator extends android.view.animation.BaseInterpolator {
     ctor public AccelerateDecelerateInterpolator();
     ctor public AccelerateDecelerateInterpolator(android.content.Context, android.util.AttributeSet);
     method public float getInterpolation(float);
   }
 
-  public class AccelerateInterpolator implements android.view.animation.Interpolator {
+  public class AccelerateInterpolator extends android.view.animation.BaseInterpolator {
     ctor public AccelerateInterpolator();
     ctor public AccelerateInterpolator(float);
     ctor public AccelerateInterpolator(android.content.Context, android.util.AttributeSet);
@@ -35531,14 +35549,14 @@
     method public static android.view.animation.Animation makeOutAnimation(android.content.Context, boolean);
   }
 
-  public class AnticipateInterpolator implements android.view.animation.Interpolator {
+  public class AnticipateInterpolator extends android.view.animation.BaseInterpolator {
     ctor public AnticipateInterpolator();
     ctor public AnticipateInterpolator(float);
     ctor public AnticipateInterpolator(android.content.Context, android.util.AttributeSet);
     method public float getInterpolation(float);
   }
 
-  public class AnticipateOvershootInterpolator implements android.view.animation.Interpolator {
+  public class AnticipateOvershootInterpolator extends android.view.animation.BaseInterpolator {
     ctor public AnticipateOvershootInterpolator();
     ctor public AnticipateOvershootInterpolator(float);
     ctor public AnticipateOvershootInterpolator(float, float);
@@ -35546,19 +35564,23 @@
     method public float getInterpolation(float);
   }
 
-  public class BounceInterpolator implements android.view.animation.Interpolator {
+  public abstract class BaseInterpolator implements android.view.animation.Interpolator {
+    ctor public BaseInterpolator();
+  }
+
+  public class BounceInterpolator extends android.view.animation.BaseInterpolator {
     ctor public BounceInterpolator();
     ctor public BounceInterpolator(android.content.Context, android.util.AttributeSet);
     method public float getInterpolation(float);
   }
 
-  public class CycleInterpolator implements android.view.animation.Interpolator {
+  public class CycleInterpolator extends android.view.animation.BaseInterpolator {
     ctor public CycleInterpolator(float);
     ctor public CycleInterpolator(android.content.Context, android.util.AttributeSet);
     method public float getInterpolation(float);
   }
 
-  public class DecelerateInterpolator implements android.view.animation.Interpolator {
+  public class DecelerateInterpolator extends android.view.animation.BaseInterpolator {
     ctor public DecelerateInterpolator();
     ctor public DecelerateInterpolator(float);
     ctor public DecelerateInterpolator(android.content.Context, android.util.AttributeSet);
@@ -35633,20 +35655,20 @@
     field public int index;
   }
 
-  public class LinearInterpolator implements android.view.animation.Interpolator {
+  public class LinearInterpolator extends android.view.animation.BaseInterpolator {
     ctor public LinearInterpolator();
     ctor public LinearInterpolator(android.content.Context, android.util.AttributeSet);
     method public float getInterpolation(float);
   }
 
-  public class OvershootInterpolator implements android.view.animation.Interpolator {
+  public class OvershootInterpolator extends android.view.animation.BaseInterpolator {
     ctor public OvershootInterpolator();
     ctor public OvershootInterpolator(float);
     ctor public OvershootInterpolator(android.content.Context, android.util.AttributeSet);
     method public float getInterpolation(float);
   }
 
-  public class PathInterpolator implements android.view.animation.Interpolator {
+  public class PathInterpolator extends android.view.animation.BaseInterpolator {
     ctor public PathInterpolator(android.graphics.Path);
     ctor public PathInterpolator(float, float);
     ctor public PathInterpolator(float, float, float, float);
@@ -38172,6 +38194,7 @@
     method public int getSoftInputMode();
     method public int getWidth();
     method public boolean isAboveAnchor();
+    method public boolean isAttachedInDecor();
     method public boolean isClippingEnabled();
     method public boolean isFocusable();
     method public boolean isOutsideTouchable();
@@ -38179,6 +38202,7 @@
     method public boolean isSplitTouchEnabled();
     method public boolean isTouchable();
     method public void setAnimationStyle(int);
+    method public void setAttachedInDecor(boolean);
     method public void setBackgroundDrawable(android.graphics.drawable.Drawable);
     method public void setClippingEnabled(boolean);
     method public void setContentView(android.view.View);
@@ -54382,7 +54406,7 @@
 
 package org.apache.commons.logging {
 
-  public abstract interface Log {
+  public abstract deprecated interface Log {
     method public abstract void debug(java.lang.Object);
     method public abstract void debug(java.lang.Object, java.lang.Throwable);
     method public abstract void error(java.lang.Object);
@@ -54407,26 +54431,26 @@
 
 package org.apache.http {
 
-  public class ConnectionClosedException extends java.io.IOException {
+  public deprecated class ConnectionClosedException extends java.io.IOException {
     ctor public ConnectionClosedException(java.lang.String);
   }
 
-  public abstract interface ConnectionReuseStrategy {
+  public abstract deprecated interface ConnectionReuseStrategy {
     method public abstract boolean keepAlive(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
   }
 
-  public abstract interface FormattedHeader implements org.apache.http.Header {
+  public abstract deprecated interface FormattedHeader implements org.apache.http.Header {
     method public abstract org.apache.http.util.CharArrayBuffer getBuffer();
     method public abstract int getValuePos();
   }
 
-  public abstract interface Header {
+  public abstract deprecated interface Header {
     method public abstract org.apache.http.HeaderElement[] getElements() throws org.apache.http.ParseException;
     method public abstract java.lang.String getName();
     method public abstract java.lang.String getValue();
   }
 
-  public abstract interface HeaderElement {
+  public abstract deprecated interface HeaderElement {
     method public abstract java.lang.String getName();
     method public abstract org.apache.http.NameValuePair getParameter(int);
     method public abstract org.apache.http.NameValuePair getParameterByName(java.lang.String);
@@ -54435,17 +54459,17 @@
     method public abstract java.lang.String getValue();
   }
 
-  public abstract interface HeaderElementIterator implements java.util.Iterator {
+  public abstract deprecated interface HeaderElementIterator implements java.util.Iterator {
     method public abstract boolean hasNext();
     method public abstract org.apache.http.HeaderElement nextElement();
   }
 
-  public abstract interface HeaderIterator implements java.util.Iterator {
+  public abstract deprecated interface HeaderIterator implements java.util.Iterator {
     method public abstract boolean hasNext();
     method public abstract org.apache.http.Header nextHeader();
   }
 
-  public abstract interface HttpClientConnection implements org.apache.http.HttpConnection {
+  public abstract deprecated interface HttpClientConnection implements org.apache.http.HttpConnection {
     method public abstract void flush() throws java.io.IOException;
     method public abstract boolean isResponseAvailable(int) throws java.io.IOException;
     method public abstract void receiveResponseEntity(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
@@ -54454,7 +54478,7 @@
     method public abstract void sendRequestHeader(org.apache.http.HttpRequest) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public abstract interface HttpConnection {
+  public abstract deprecated interface HttpConnection {
     method public abstract void close() throws java.io.IOException;
     method public abstract org.apache.http.HttpConnectionMetrics getMetrics();
     method public abstract int getSocketTimeout();
@@ -54464,7 +54488,7 @@
     method public abstract void shutdown() throws java.io.IOException;
   }
 
-  public abstract interface HttpConnectionMetrics {
+  public abstract deprecated interface HttpConnectionMetrics {
     method public abstract java.lang.Object getMetric(java.lang.String);
     method public abstract long getReceivedBytesCount();
     method public abstract long getRequestCount();
@@ -54473,7 +54497,7 @@
     method public abstract void reset();
   }
 
-  public abstract interface HttpEntity {
+  public abstract deprecated interface HttpEntity {
     method public abstract void consumeContent() throws java.io.IOException;
     method public abstract java.io.InputStream getContent() throws java.io.IOException, java.lang.IllegalStateException;
     method public abstract org.apache.http.Header getContentEncoding();
@@ -54485,19 +54509,19 @@
     method public abstract void writeTo(java.io.OutputStream) throws java.io.IOException;
   }
 
-  public abstract interface HttpEntityEnclosingRequest implements org.apache.http.HttpRequest {
+  public abstract deprecated interface HttpEntityEnclosingRequest implements org.apache.http.HttpRequest {
     method public abstract boolean expectContinue();
     method public abstract org.apache.http.HttpEntity getEntity();
     method public abstract void setEntity(org.apache.http.HttpEntity);
   }
 
-  public class HttpException extends java.lang.Exception {
+  public deprecated class HttpException extends java.lang.Exception {
     ctor public HttpException();
     ctor public HttpException(java.lang.String);
     ctor public HttpException(java.lang.String, java.lang.Throwable);
   }
 
-  public final class HttpHost implements java.lang.Cloneable {
+  public final deprecated class HttpHost implements java.lang.Cloneable {
     ctor public HttpHost(java.lang.String, int, java.lang.String);
     ctor public HttpHost(java.lang.String, int);
     ctor public HttpHost(java.lang.String);
@@ -54515,14 +54539,14 @@
     field protected final java.lang.String schemeName;
   }
 
-  public abstract interface HttpInetConnection implements org.apache.http.HttpConnection {
+  public abstract deprecated interface HttpInetConnection implements org.apache.http.HttpConnection {
     method public abstract java.net.InetAddress getLocalAddress();
     method public abstract int getLocalPort();
     method public abstract java.net.InetAddress getRemoteAddress();
     method public abstract int getRemotePort();
   }
 
-  public abstract interface HttpMessage {
+  public abstract deprecated interface HttpMessage {
     method public abstract void addHeader(org.apache.http.Header);
     method public abstract void addHeader(java.lang.String, java.lang.String);
     method public abstract boolean containsHeader(java.lang.String);
@@ -54542,20 +54566,20 @@
     method public abstract void setParams(org.apache.http.params.HttpParams);
   }
 
-  public abstract interface HttpRequest implements org.apache.http.HttpMessage {
+  public abstract deprecated interface HttpRequest implements org.apache.http.HttpMessage {
     method public abstract org.apache.http.RequestLine getRequestLine();
   }
 
-  public abstract interface HttpRequestFactory {
+  public abstract deprecated interface HttpRequestFactory {
     method public abstract org.apache.http.HttpRequest newHttpRequest(org.apache.http.RequestLine) throws org.apache.http.MethodNotSupportedException;
     method public abstract org.apache.http.HttpRequest newHttpRequest(java.lang.String, java.lang.String) throws org.apache.http.MethodNotSupportedException;
   }
 
-  public abstract interface HttpRequestInterceptor {
+  public abstract deprecated interface HttpRequestInterceptor {
     method public abstract void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public abstract interface HttpResponse implements org.apache.http.HttpMessage {
+  public abstract deprecated interface HttpResponse implements org.apache.http.HttpMessage {
     method public abstract org.apache.http.HttpEntity getEntity();
     method public abstract java.util.Locale getLocale();
     method public abstract org.apache.http.StatusLine getStatusLine();
@@ -54568,16 +54592,16 @@
     method public abstract void setStatusLine(org.apache.http.ProtocolVersion, int, java.lang.String);
   }
 
-  public abstract interface HttpResponseFactory {
+  public abstract deprecated interface HttpResponseFactory {
     method public abstract org.apache.http.HttpResponse newHttpResponse(org.apache.http.ProtocolVersion, int, org.apache.http.protocol.HttpContext);
     method public abstract org.apache.http.HttpResponse newHttpResponse(org.apache.http.StatusLine, org.apache.http.protocol.HttpContext);
   }
 
-  public abstract interface HttpResponseInterceptor {
+  public abstract deprecated interface HttpResponseInterceptor {
     method public abstract void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public abstract interface HttpServerConnection implements org.apache.http.HttpConnection {
+  public abstract deprecated interface HttpServerConnection implements org.apache.http.HttpConnection {
     method public abstract void flush() throws java.io.IOException;
     method public abstract void receiveRequestEntity(org.apache.http.HttpEntityEnclosingRequest) throws org.apache.http.HttpException, java.io.IOException;
     method public abstract org.apache.http.HttpRequest receiveRequestHeader() throws org.apache.http.HttpException, java.io.IOException;
@@ -54585,7 +54609,7 @@
     method public abstract void sendResponseHeader(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public abstract interface HttpStatus {
+  public abstract deprecated interface HttpStatus {
     field public static final int SC_ACCEPTED = 202; // 0xca
     field public static final int SC_BAD_GATEWAY = 502; // 0x1f6
     field public static final int SC_BAD_REQUEST = 400; // 0x190
@@ -54636,7 +54660,7 @@
     field public static final int SC_USE_PROXY = 305; // 0x131
   }
 
-  public final class HttpVersion extends org.apache.http.ProtocolVersion implements java.io.Serializable {
+  public final deprecated class HttpVersion extends org.apache.http.ProtocolVersion implements java.io.Serializable {
     ctor public HttpVersion(int, int);
     field public static final java.lang.String HTTP = "HTTP";
     field public static final org.apache.http.HttpVersion HTTP_0_9;
@@ -54644,37 +54668,37 @@
     field public static final org.apache.http.HttpVersion HTTP_1_1;
   }
 
-  public class MalformedChunkCodingException extends java.io.IOException {
+  public deprecated class MalformedChunkCodingException extends java.io.IOException {
     ctor public MalformedChunkCodingException();
     ctor public MalformedChunkCodingException(java.lang.String);
   }
 
-  public class MethodNotSupportedException extends org.apache.http.HttpException {
+  public deprecated class MethodNotSupportedException extends org.apache.http.HttpException {
     ctor public MethodNotSupportedException(java.lang.String);
     ctor public MethodNotSupportedException(java.lang.String, java.lang.Throwable);
   }
 
-  public abstract interface NameValuePair {
+  public abstract deprecated interface NameValuePair {
     method public abstract java.lang.String getName();
     method public abstract java.lang.String getValue();
   }
 
-  public class NoHttpResponseException extends java.io.IOException {
+  public deprecated class NoHttpResponseException extends java.io.IOException {
     ctor public NoHttpResponseException(java.lang.String);
   }
 
-  public class ParseException extends java.lang.RuntimeException {
+  public deprecated class ParseException extends java.lang.RuntimeException {
     ctor public ParseException();
     ctor public ParseException(java.lang.String);
   }
 
-  public class ProtocolException extends org.apache.http.HttpException {
+  public deprecated class ProtocolException extends org.apache.http.HttpException {
     ctor public ProtocolException();
     ctor public ProtocolException(java.lang.String);
     ctor public ProtocolException(java.lang.String, java.lang.Throwable);
   }
 
-  public class ProtocolVersion implements java.lang.Cloneable java.io.Serializable {
+  public deprecated class ProtocolVersion implements java.lang.Cloneable java.io.Serializable {
     ctor public ProtocolVersion(java.lang.String, int, int);
     method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
     method public int compareToVersion(org.apache.http.ProtocolVersion);
@@ -54692,28 +54716,28 @@
     field protected final java.lang.String protocol;
   }
 
-  public abstract interface ReasonPhraseCatalog {
+  public abstract deprecated interface ReasonPhraseCatalog {
     method public abstract java.lang.String getReason(int, java.util.Locale);
   }
 
-  public abstract interface RequestLine {
+  public abstract deprecated interface RequestLine {
     method public abstract java.lang.String getMethod();
     method public abstract org.apache.http.ProtocolVersion getProtocolVersion();
     method public abstract java.lang.String getUri();
   }
 
-  public abstract interface StatusLine {
+  public abstract deprecated interface StatusLine {
     method public abstract org.apache.http.ProtocolVersion getProtocolVersion();
     method public abstract java.lang.String getReasonPhrase();
     method public abstract int getStatusCode();
   }
 
-  public abstract interface TokenIterator implements java.util.Iterator {
+  public abstract deprecated interface TokenIterator implements java.util.Iterator {
     method public abstract boolean hasNext();
     method public abstract java.lang.String nextToken();
   }
 
-  public class UnsupportedHttpVersionException extends org.apache.http.ProtocolException {
+  public deprecated class UnsupportedHttpVersionException extends org.apache.http.ProtocolException {
     ctor public UnsupportedHttpVersionException();
     ctor public UnsupportedHttpVersionException(java.lang.String);
   }
@@ -54722,14 +54746,14 @@
 
 package org.apache.http.auth {
 
-  public final class AUTH {
+  public final deprecated class AUTH {
     field public static final java.lang.String PROXY_AUTH = "Proxy-Authenticate";
     field public static final java.lang.String PROXY_AUTH_RESP = "Proxy-Authorization";
     field public static final java.lang.String WWW_AUTH = "WWW-Authenticate";
     field public static final java.lang.String WWW_AUTH_RESP = "Authorization";
   }
 
-  public abstract interface AuthScheme {
+  public abstract deprecated interface AuthScheme {
     method public abstract org.apache.http.Header authenticate(org.apache.http.auth.Credentials, org.apache.http.HttpRequest) throws org.apache.http.auth.AuthenticationException;
     method public abstract java.lang.String getParameter(java.lang.String);
     method public abstract java.lang.String getRealm();
@@ -54739,11 +54763,11 @@
     method public abstract void processChallenge(org.apache.http.Header) throws org.apache.http.auth.MalformedChallengeException;
   }
 
-  public abstract interface AuthSchemeFactory {
+  public abstract deprecated interface AuthSchemeFactory {
     method public abstract org.apache.http.auth.AuthScheme newInstance(org.apache.http.params.HttpParams);
   }
 
-  public final class AuthSchemeRegistry {
+  public final deprecated class AuthSchemeRegistry {
     ctor public AuthSchemeRegistry();
     method public synchronized org.apache.http.auth.AuthScheme getAuthScheme(java.lang.String, org.apache.http.params.HttpParams) throws java.lang.IllegalStateException;
     method public synchronized java.util.List<java.lang.String> getSchemeNames();
@@ -54752,7 +54776,7 @@
     method public synchronized void unregister(java.lang.String);
   }
 
-  public class AuthScope {
+  public deprecated class AuthScope {
     ctor public AuthScope(java.lang.String, int, java.lang.String, java.lang.String);
     ctor public AuthScope(java.lang.String, int, java.lang.String);
     ctor public AuthScope(java.lang.String, int);
@@ -54769,7 +54793,7 @@
     field public static final java.lang.String ANY_SCHEME;
   }
 
-  public class AuthState {
+  public deprecated class AuthState {
     ctor public AuthState();
     method public org.apache.http.auth.AuthScheme getAuthScheme();
     method public org.apache.http.auth.AuthScope getAuthScope();
@@ -54781,35 +54805,35 @@
     method public void setCredentials(org.apache.http.auth.Credentials);
   }
 
-  public class AuthenticationException extends org.apache.http.ProtocolException {
+  public deprecated class AuthenticationException extends org.apache.http.ProtocolException {
     ctor public AuthenticationException();
     ctor public AuthenticationException(java.lang.String);
     ctor public AuthenticationException(java.lang.String, java.lang.Throwable);
   }
 
-  public final class BasicUserPrincipal implements java.security.Principal {
+  public final deprecated class BasicUserPrincipal implements java.security.Principal {
     ctor public BasicUserPrincipal(java.lang.String);
     method public java.lang.String getName();
   }
 
-  public abstract interface Credentials {
+  public abstract deprecated interface Credentials {
     method public abstract java.lang.String getPassword();
     method public abstract java.security.Principal getUserPrincipal();
   }
 
-  public class InvalidCredentialsException extends org.apache.http.auth.AuthenticationException {
+  public deprecated class InvalidCredentialsException extends org.apache.http.auth.AuthenticationException {
     ctor public InvalidCredentialsException();
     ctor public InvalidCredentialsException(java.lang.String);
     ctor public InvalidCredentialsException(java.lang.String, java.lang.Throwable);
   }
 
-  public class MalformedChallengeException extends org.apache.http.ProtocolException {
+  public deprecated class MalformedChallengeException extends org.apache.http.ProtocolException {
     ctor public MalformedChallengeException();
     ctor public MalformedChallengeException(java.lang.String);
     ctor public MalformedChallengeException(java.lang.String, java.lang.Throwable);
   }
 
-  public class NTCredentials implements org.apache.http.auth.Credentials {
+  public deprecated class NTCredentials implements org.apache.http.auth.Credentials {
     ctor public NTCredentials(java.lang.String);
     ctor public NTCredentials(java.lang.String, java.lang.String, java.lang.String, java.lang.String);
     method public java.lang.String getDomain();
@@ -54819,14 +54843,14 @@
     method public java.lang.String getWorkstation();
   }
 
-  public class NTUserPrincipal implements java.security.Principal {
+  public deprecated class NTUserPrincipal implements java.security.Principal {
     ctor public NTUserPrincipal(java.lang.String, java.lang.String);
     method public java.lang.String getDomain();
     method public java.lang.String getName();
     method public java.lang.String getUsername();
   }
 
-  public class UsernamePasswordCredentials implements org.apache.http.auth.Credentials {
+  public deprecated class UsernamePasswordCredentials implements org.apache.http.auth.Credentials {
     ctor public UsernamePasswordCredentials(java.lang.String);
     ctor public UsernamePasswordCredentials(java.lang.String, java.lang.String);
     method public java.lang.String getPassword();
@@ -54838,16 +54862,16 @@
 
 package org.apache.http.auth.params {
 
-  public abstract interface AuthPNames {
+  public abstract deprecated interface AuthPNames {
     field public static final java.lang.String CREDENTIAL_CHARSET = "http.auth.credential-charset";
   }
 
-  public class AuthParamBean extends org.apache.http.params.HttpAbstractParamBean {
+  public deprecated class AuthParamBean extends org.apache.http.params.HttpAbstractParamBean {
     ctor public AuthParamBean(org.apache.http.params.HttpParams);
     method public void setCredentialCharset(java.lang.String);
   }
 
-  public final class AuthParams {
+  public final deprecated class AuthParams {
     method public static java.lang.String getCredentialCharset(org.apache.http.params.HttpParams);
     method public static void setCredentialCharset(org.apache.http.params.HttpParams, java.lang.String);
   }
@@ -54856,39 +54880,39 @@
 
 package org.apache.http.client {
 
-  public abstract interface AuthenticationHandler {
+  public abstract deprecated interface AuthenticationHandler {
     method public abstract java.util.Map<java.lang.String, org.apache.http.Header> getChallenges(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.MalformedChallengeException;
     method public abstract boolean isAuthenticationRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
     method public abstract org.apache.http.auth.AuthScheme selectScheme(java.util.Map<java.lang.String, org.apache.http.Header>, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.AuthenticationException;
   }
 
-  public class CircularRedirectException extends org.apache.http.client.RedirectException {
+  public deprecated class CircularRedirectException extends org.apache.http.client.RedirectException {
     ctor public CircularRedirectException();
     ctor public CircularRedirectException(java.lang.String);
     ctor public CircularRedirectException(java.lang.String, java.lang.Throwable);
   }
 
-  public class ClientProtocolException extends java.io.IOException {
+  public deprecated class ClientProtocolException extends java.io.IOException {
     ctor public ClientProtocolException();
     ctor public ClientProtocolException(java.lang.String);
     ctor public ClientProtocolException(java.lang.Throwable);
     ctor public ClientProtocolException(java.lang.String, java.lang.Throwable);
   }
 
-  public abstract interface CookieStore {
+  public abstract deprecated interface CookieStore {
     method public abstract void addCookie(org.apache.http.cookie.Cookie);
     method public abstract void clear();
     method public abstract boolean clearExpired(java.util.Date);
     method public abstract java.util.List<org.apache.http.cookie.Cookie> getCookies();
   }
 
-  public abstract interface CredentialsProvider {
+  public abstract deprecated interface CredentialsProvider {
     method public abstract void clear();
     method public abstract org.apache.http.auth.Credentials getCredentials(org.apache.http.auth.AuthScope);
     method public abstract void setCredentials(org.apache.http.auth.AuthScope, org.apache.http.auth.Credentials);
   }
 
-  public abstract interface HttpClient {
+  public abstract deprecated interface HttpClient {
     method public abstract org.apache.http.HttpResponse execute(org.apache.http.client.methods.HttpUriRequest) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
     method public abstract org.apache.http.HttpResponse execute(org.apache.http.client.methods.HttpUriRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
     method public abstract org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
@@ -54901,40 +54925,40 @@
     method public abstract org.apache.http.params.HttpParams getParams();
   }
 
-  public abstract interface HttpRequestRetryHandler {
+  public abstract deprecated interface HttpRequestRetryHandler {
     method public abstract boolean retryRequest(java.io.IOException, int, org.apache.http.protocol.HttpContext);
   }
 
-  public class HttpResponseException extends org.apache.http.client.ClientProtocolException {
+  public deprecated class HttpResponseException extends org.apache.http.client.ClientProtocolException {
     ctor public HttpResponseException(int, java.lang.String);
     method public int getStatusCode();
   }
 
-  public class NonRepeatableRequestException extends org.apache.http.ProtocolException {
+  public deprecated class NonRepeatableRequestException extends org.apache.http.ProtocolException {
     ctor public NonRepeatableRequestException();
     ctor public NonRepeatableRequestException(java.lang.String);
   }
 
-  public class RedirectException extends org.apache.http.ProtocolException {
+  public deprecated class RedirectException extends org.apache.http.ProtocolException {
     ctor public RedirectException();
     ctor public RedirectException(java.lang.String);
     ctor public RedirectException(java.lang.String, java.lang.Throwable);
   }
 
-  public abstract interface RedirectHandler {
+  public abstract deprecated interface RedirectHandler {
     method public abstract java.net.URI getLocationURI(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.ProtocolException;
     method public abstract boolean isRedirectRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
   }
 
-  public abstract interface RequestDirector {
+  public abstract deprecated interface RequestDirector {
     method public abstract org.apache.http.HttpResponse execute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public abstract interface ResponseHandler {
+  public abstract deprecated interface ResponseHandler {
     method public abstract T handleResponse(org.apache.http.HttpResponse) throws org.apache.http.client.ClientProtocolException, java.io.IOException;
   }
 
-  public abstract interface UserTokenHandler {
+  public abstract deprecated interface UserTokenHandler {
     method public abstract java.lang.Object getUserToken(org.apache.http.protocol.HttpContext);
   }
 
@@ -54942,7 +54966,7 @@
 
 package org.apache.http.client.entity {
 
-  public class UrlEncodedFormEntity extends org.apache.http.entity.StringEntity {
+  public deprecated class UrlEncodedFormEntity extends org.apache.http.entity.StringEntity {
     ctor public UrlEncodedFormEntity(java.util.List<? extends org.apache.http.NameValuePair>, java.lang.String) throws java.io.UnsupportedEncodingException;
     ctor public UrlEncodedFormEntity(java.util.List<? extends org.apache.http.NameValuePair>) throws java.io.UnsupportedEncodingException;
   }
@@ -54951,13 +54975,13 @@
 
 package org.apache.http.client.methods {
 
-  public abstract interface AbortableHttpRequest {
+  public abstract deprecated interface AbortableHttpRequest {
     method public abstract void abort();
     method public abstract void setConnectionRequest(org.apache.http.conn.ClientConnectionRequest) throws java.io.IOException;
     method public abstract void setReleaseTrigger(org.apache.http.conn.ConnectionReleaseTrigger) throws java.io.IOException;
   }
 
-  public class HttpDelete extends org.apache.http.client.methods.HttpRequestBase {
+  public deprecated class HttpDelete extends org.apache.http.client.methods.HttpRequestBase {
     ctor public HttpDelete();
     ctor public HttpDelete(java.net.URI);
     ctor public HttpDelete(java.lang.String);
@@ -54965,14 +54989,14 @@
     field public static final java.lang.String METHOD_NAME = "DELETE";
   }
 
-  public abstract class HttpEntityEnclosingRequestBase extends org.apache.http.client.methods.HttpRequestBase implements org.apache.http.HttpEntityEnclosingRequest {
+  public abstract deprecated class HttpEntityEnclosingRequestBase extends org.apache.http.client.methods.HttpRequestBase implements org.apache.http.HttpEntityEnclosingRequest {
     ctor public HttpEntityEnclosingRequestBase();
     method public boolean expectContinue();
     method public org.apache.http.HttpEntity getEntity();
     method public void setEntity(org.apache.http.HttpEntity);
   }
 
-  public class HttpGet extends org.apache.http.client.methods.HttpRequestBase {
+  public deprecated class HttpGet extends org.apache.http.client.methods.HttpRequestBase {
     ctor public HttpGet();
     ctor public HttpGet(java.net.URI);
     ctor public HttpGet(java.lang.String);
@@ -54980,7 +55004,7 @@
     field public static final java.lang.String METHOD_NAME = "GET";
   }
 
-  public class HttpHead extends org.apache.http.client.methods.HttpRequestBase {
+  public deprecated class HttpHead extends org.apache.http.client.methods.HttpRequestBase {
     ctor public HttpHead();
     ctor public HttpHead(java.net.URI);
     ctor public HttpHead(java.lang.String);
@@ -54988,7 +55012,7 @@
     field public static final java.lang.String METHOD_NAME = "HEAD";
   }
 
-  public class HttpOptions extends org.apache.http.client.methods.HttpRequestBase {
+  public deprecated class HttpOptions extends org.apache.http.client.methods.HttpRequestBase {
     ctor public HttpOptions();
     ctor public HttpOptions(java.net.URI);
     ctor public HttpOptions(java.lang.String);
@@ -54997,7 +55021,7 @@
     field public static final java.lang.String METHOD_NAME = "OPTIONS";
   }
 
-  public class HttpPost extends org.apache.http.client.methods.HttpEntityEnclosingRequestBase {
+  public deprecated class HttpPost extends org.apache.http.client.methods.HttpEntityEnclosingRequestBase {
     ctor public HttpPost();
     ctor public HttpPost(java.net.URI);
     ctor public HttpPost(java.lang.String);
@@ -55005,7 +55029,7 @@
     field public static final java.lang.String METHOD_NAME = "POST";
   }
 
-  public class HttpPut extends org.apache.http.client.methods.HttpEntityEnclosingRequestBase {
+  public deprecated class HttpPut extends org.apache.http.client.methods.HttpEntityEnclosingRequestBase {
     ctor public HttpPut();
     ctor public HttpPut(java.net.URI);
     ctor public HttpPut(java.lang.String);
@@ -55013,7 +55037,7 @@
     field public static final java.lang.String METHOD_NAME = "PUT";
   }
 
-  public abstract class HttpRequestBase extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.client.methods.AbortableHttpRequest java.lang.Cloneable org.apache.http.client.methods.HttpUriRequest {
+  public abstract deprecated class HttpRequestBase extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.client.methods.AbortableHttpRequest java.lang.Cloneable org.apache.http.client.methods.HttpUriRequest {
     ctor public HttpRequestBase();
     method public void abort();
     method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
@@ -55027,7 +55051,7 @@
     method public void setURI(java.net.URI);
   }
 
-  public class HttpTrace extends org.apache.http.client.methods.HttpRequestBase {
+  public deprecated class HttpTrace extends org.apache.http.client.methods.HttpRequestBase {
     ctor public HttpTrace();
     ctor public HttpTrace(java.net.URI);
     ctor public HttpTrace(java.lang.String);
@@ -55035,7 +55059,7 @@
     field public static final java.lang.String METHOD_NAME = "TRACE";
   }
 
-  public abstract interface HttpUriRequest implements org.apache.http.HttpRequest {
+  public abstract deprecated interface HttpUriRequest implements org.apache.http.HttpRequest {
     method public abstract void abort() throws java.lang.UnsupportedOperationException;
     method public abstract java.lang.String getMethod();
     method public abstract java.net.URI getURI();
@@ -55046,16 +55070,16 @@
 
 package org.apache.http.client.params {
 
-  public abstract interface AllClientPNames implements org.apache.http.auth.params.AuthPNames org.apache.http.client.params.ClientPNames org.apache.http.conn.params.ConnConnectionPNames org.apache.http.conn.params.ConnManagerPNames org.apache.http.conn.params.ConnRoutePNames org.apache.http.cookie.params.CookieSpecPNames org.apache.http.params.CoreConnectionPNames org.apache.http.params.CoreProtocolPNames {
+  public abstract deprecated interface AllClientPNames implements org.apache.http.auth.params.AuthPNames org.apache.http.client.params.ClientPNames org.apache.http.conn.params.ConnConnectionPNames org.apache.http.conn.params.ConnManagerPNames org.apache.http.conn.params.ConnRoutePNames org.apache.http.cookie.params.CookieSpecPNames org.apache.http.params.CoreConnectionPNames org.apache.http.params.CoreProtocolPNames {
   }
 
-  public final class AuthPolicy {
+  public final deprecated class AuthPolicy {
     field public static final java.lang.String BASIC = "Basic";
     field public static final java.lang.String DIGEST = "Digest";
     field public static final java.lang.String NTLM = "NTLM";
   }
 
-  public abstract interface ClientPNames {
+  public abstract deprecated interface ClientPNames {
     field public static final java.lang.String ALLOW_CIRCULAR_REDIRECTS = "http.protocol.allow-circular-redirects";
     field public static final java.lang.String CONNECTION_MANAGER_FACTORY = "http.connection-manager.factory-object";
     field public static final java.lang.String CONNECTION_MANAGER_FACTORY_CLASS_NAME = "http.connection-manager.factory-class-name";
@@ -55069,7 +55093,7 @@
     field public static final java.lang.String VIRTUAL_HOST = "http.virtual-host";
   }
 
-  public class ClientParamBean extends org.apache.http.params.HttpAbstractParamBean {
+  public deprecated class ClientParamBean extends org.apache.http.params.HttpAbstractParamBean {
     ctor public ClientParamBean(org.apache.http.params.HttpParams);
     method public void setAllowCircularRedirects(boolean);
     method public void setConnectionManagerFactory(org.apache.http.conn.ClientConnectionManagerFactory);
@@ -55084,7 +55108,7 @@
     method public void setVirtualHost(org.apache.http.HttpHost);
   }
 
-  public final class CookiePolicy {
+  public final deprecated class CookiePolicy {
     field public static final java.lang.String BEST_MATCH = "best-match";
     field public static final java.lang.String BROWSER_COMPATIBILITY = "compatibility";
     field public static final java.lang.String NETSCAPE = "netscape";
@@ -55092,7 +55116,7 @@
     field public static final java.lang.String RFC_2965 = "rfc2965";
   }
 
-  public class HttpClientParams {
+  public deprecated class HttpClientParams {
     method public static java.lang.String getCookiePolicy(org.apache.http.params.HttpParams);
     method public static boolean isAuthenticating(org.apache.http.params.HttpParams);
     method public static boolean isRedirecting(org.apache.http.params.HttpParams);
@@ -55105,7 +55129,7 @@
 
 package org.apache.http.client.protocol {
 
-  public abstract interface ClientContext {
+  public abstract deprecated interface ClientContext {
     field public static final java.lang.String AUTHSCHEME_REGISTRY = "http.authscheme-registry";
     field public static final java.lang.String AUTH_SCHEME_PREF = "http.auth.scheme-pref";
     field public static final java.lang.String COOKIESPEC_REGISTRY = "http.cookiespec-registry";
@@ -55118,7 +55142,7 @@
     field public static final java.lang.String USER_TOKEN = "http.user-token";
   }
 
-  public class ClientContextConfigurer implements org.apache.http.client.protocol.ClientContext {
+  public deprecated class ClientContextConfigurer implements org.apache.http.client.protocol.ClientContext {
     ctor public ClientContextConfigurer(org.apache.http.protocol.HttpContext);
     method public void setAuthSchemePref(java.util.List<java.lang.String>);
     method public void setAuthSchemeRegistry(org.apache.http.auth.AuthSchemeRegistry);
@@ -55127,27 +55151,27 @@
     method public void setCredentialsProvider(org.apache.http.client.CredentialsProvider);
   }
 
-  public class RequestAddCookies implements org.apache.http.HttpRequestInterceptor {
+  public deprecated class RequestAddCookies implements org.apache.http.HttpRequestInterceptor {
     ctor public RequestAddCookies();
     method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public class RequestDefaultHeaders implements org.apache.http.HttpRequestInterceptor {
+  public deprecated class RequestDefaultHeaders implements org.apache.http.HttpRequestInterceptor {
     ctor public RequestDefaultHeaders();
     method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public class RequestProxyAuthentication implements org.apache.http.HttpRequestInterceptor {
+  public deprecated class RequestProxyAuthentication implements org.apache.http.HttpRequestInterceptor {
     ctor public RequestProxyAuthentication();
     method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public class RequestTargetAuthentication implements org.apache.http.HttpRequestInterceptor {
+  public deprecated class RequestTargetAuthentication implements org.apache.http.HttpRequestInterceptor {
     ctor public RequestTargetAuthentication();
     method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public class ResponseProcessCookies implements org.apache.http.HttpResponseInterceptor {
+  public deprecated class ResponseProcessCookies implements org.apache.http.HttpResponseInterceptor {
     ctor public ResponseProcessCookies();
     method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
   }
@@ -55156,11 +55180,11 @@
 
 package org.apache.http.client.utils {
 
-  public class CloneUtils {
+  public deprecated class CloneUtils {
     method public static java.lang.Object clone(java.lang.Object) throws java.lang.CloneNotSupportedException;
   }
 
-  public class URIUtils {
+  public deprecated class URIUtils {
     method public static java.net.URI createURI(java.lang.String, java.lang.String, int, java.lang.String, java.lang.String, java.lang.String) throws java.net.URISyntaxException;
     method public static java.net.URI resolve(java.net.URI, java.lang.String);
     method public static java.net.URI resolve(java.net.URI, java.net.URI);
@@ -55168,7 +55192,7 @@
     method public static java.net.URI rewriteURI(java.net.URI, org.apache.http.HttpHost) throws java.net.URISyntaxException;
   }
 
-  public class URLEncodedUtils {
+  public deprecated class URLEncodedUtils {
     ctor public URLEncodedUtils();
     method public static java.lang.String format(java.util.List<? extends org.apache.http.NameValuePair>, java.lang.String);
     method public static boolean isEncoded(org.apache.http.HttpEntity);
@@ -55182,7 +55206,7 @@
 
 package org.apache.http.conn {
 
-  public class BasicEofSensorWatcher implements org.apache.http.conn.EofSensorWatcher {
+  public deprecated class BasicEofSensorWatcher implements org.apache.http.conn.EofSensorWatcher {
     ctor public BasicEofSensorWatcher(org.apache.http.conn.ManagedClientConnection, boolean);
     method public boolean eofDetected(java.io.InputStream) throws java.io.IOException;
     method public boolean streamAbort(java.io.InputStream) throws java.io.IOException;
@@ -55191,7 +55215,7 @@
     field protected org.apache.http.conn.ManagedClientConnection managedConn;
   }
 
-  public class BasicManagedEntity extends org.apache.http.entity.HttpEntityWrapper implements org.apache.http.conn.ConnectionReleaseTrigger org.apache.http.conn.EofSensorWatcher {
+  public deprecated class BasicManagedEntity extends org.apache.http.entity.HttpEntityWrapper implements org.apache.http.conn.ConnectionReleaseTrigger org.apache.http.conn.EofSensorWatcher {
     ctor public BasicManagedEntity(org.apache.http.HttpEntity, org.apache.http.conn.ManagedClientConnection, boolean);
     method public void abortConnection() throws java.io.IOException;
     method public boolean eofDetected(java.io.InputStream) throws java.io.IOException;
@@ -55203,7 +55227,7 @@
     field protected org.apache.http.conn.ManagedClientConnection managedConn;
   }
 
-  public abstract interface ClientConnectionManager {
+  public abstract deprecated interface ClientConnectionManager {
     method public abstract void closeExpiredConnections();
     method public abstract void closeIdleConnections(long, java.util.concurrent.TimeUnit);
     method public abstract org.apache.http.conn.scheme.SchemeRegistry getSchemeRegistry();
@@ -55212,41 +55236,41 @@
     method public abstract void shutdown();
   }
 
-  public abstract interface ClientConnectionManagerFactory {
+  public abstract deprecated interface ClientConnectionManagerFactory {
     method public abstract org.apache.http.conn.ClientConnectionManager newInstance(org.apache.http.params.HttpParams, org.apache.http.conn.scheme.SchemeRegistry);
   }
 
-  public abstract interface ClientConnectionOperator {
+  public abstract deprecated interface ClientConnectionOperator {
     method public abstract org.apache.http.conn.OperatedClientConnection createConnection();
     method public abstract void openConnection(org.apache.http.conn.OperatedClientConnection, org.apache.http.HttpHost, java.net.InetAddress, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
     method public abstract void updateSecureConnection(org.apache.http.conn.OperatedClientConnection, org.apache.http.HttpHost, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
   }
 
-  public abstract interface ClientConnectionRequest {
+  public abstract deprecated interface ClientConnectionRequest {
     method public abstract void abortRequest();
     method public abstract org.apache.http.conn.ManagedClientConnection getConnection(long, java.util.concurrent.TimeUnit) throws org.apache.http.conn.ConnectionPoolTimeoutException, java.lang.InterruptedException;
   }
 
-  public class ConnectTimeoutException extends java.io.InterruptedIOException {
+  public deprecated class ConnectTimeoutException extends java.io.InterruptedIOException {
     ctor public ConnectTimeoutException();
     ctor public ConnectTimeoutException(java.lang.String);
   }
 
-  public abstract interface ConnectionKeepAliveStrategy {
+  public abstract deprecated interface ConnectionKeepAliveStrategy {
     method public abstract long getKeepAliveDuration(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
   }
 
-  public class ConnectionPoolTimeoutException extends org.apache.http.conn.ConnectTimeoutException {
+  public deprecated class ConnectionPoolTimeoutException extends org.apache.http.conn.ConnectTimeoutException {
     ctor public ConnectionPoolTimeoutException();
     ctor public ConnectionPoolTimeoutException(java.lang.String);
   }
 
-  public abstract interface ConnectionReleaseTrigger {
+  public abstract deprecated interface ConnectionReleaseTrigger {
     method public abstract void abortConnection() throws java.io.IOException;
     method public abstract void releaseConnection() throws java.io.IOException;
   }
 
-  public class EofSensorInputStream extends java.io.InputStream implements org.apache.http.conn.ConnectionReleaseTrigger {
+  public deprecated class EofSensorInputStream extends java.io.InputStream implements org.apache.http.conn.ConnectionReleaseTrigger {
     ctor public EofSensorInputStream(java.io.InputStream, org.apache.http.conn.EofSensorWatcher);
     method public void abortConnection() throws java.io.IOException;
     method protected void checkAbort() throws java.io.IOException;
@@ -55258,18 +55282,18 @@
     field protected java.io.InputStream wrappedStream;
   }
 
-  public abstract interface EofSensorWatcher {
+  public abstract deprecated interface EofSensorWatcher {
     method public abstract boolean eofDetected(java.io.InputStream) throws java.io.IOException;
     method public abstract boolean streamAbort(java.io.InputStream) throws java.io.IOException;
     method public abstract boolean streamClosed(java.io.InputStream) throws java.io.IOException;
   }
 
-  public class HttpHostConnectException extends java.net.ConnectException {
+  public deprecated class HttpHostConnectException extends java.net.ConnectException {
     ctor public HttpHostConnectException(org.apache.http.HttpHost, java.net.ConnectException);
     method public org.apache.http.HttpHost getHost();
   }
 
-  public abstract interface ManagedClientConnection implements org.apache.http.conn.ConnectionReleaseTrigger org.apache.http.HttpClientConnection org.apache.http.HttpInetConnection {
+  public abstract deprecated interface ManagedClientConnection implements org.apache.http.conn.ConnectionReleaseTrigger org.apache.http.HttpClientConnection org.apache.http.HttpInetConnection {
     method public abstract org.apache.http.conn.routing.HttpRoute getRoute();
     method public abstract javax.net.ssl.SSLSession getSSLSession();
     method public abstract java.lang.Object getState();
@@ -55285,14 +55309,14 @@
     method public abstract void unmarkReusable();
   }
 
-  public final class MultihomePlainSocketFactory implements org.apache.http.conn.scheme.SocketFactory {
+  public final deprecated class MultihomePlainSocketFactory implements org.apache.http.conn.scheme.SocketFactory {
     method public java.net.Socket connectSocket(java.net.Socket, java.lang.String, int, java.net.InetAddress, int, org.apache.http.params.HttpParams) throws java.io.IOException;
     method public java.net.Socket createSocket();
     method public static org.apache.http.conn.MultihomePlainSocketFactory getSocketFactory();
     method public final boolean isSecure(java.net.Socket) throws java.lang.IllegalArgumentException;
   }
 
-  public abstract interface OperatedClientConnection implements org.apache.http.HttpClientConnection org.apache.http.HttpInetConnection {
+  public abstract deprecated interface OperatedClientConnection implements org.apache.http.HttpClientConnection org.apache.http.HttpInetConnection {
     method public abstract java.net.Socket getSocket();
     method public abstract org.apache.http.HttpHost getTargetHost();
     method public abstract boolean isSecure();
@@ -55305,29 +55329,29 @@
 
 package org.apache.http.conn.params {
 
-  public abstract interface ConnConnectionPNames {
+  public abstract deprecated interface ConnConnectionPNames {
     field public static final java.lang.String MAX_STATUS_LINE_GARBAGE = "http.connection.max-status-line-garbage";
   }
 
-  public class ConnConnectionParamBean extends org.apache.http.params.HttpAbstractParamBean {
+  public deprecated class ConnConnectionParamBean extends org.apache.http.params.HttpAbstractParamBean {
     ctor public ConnConnectionParamBean(org.apache.http.params.HttpParams);
     method public void setMaxStatusLineGarbage(int);
   }
 
-  public abstract interface ConnManagerPNames {
+  public abstract deprecated interface ConnManagerPNames {
     field public static final java.lang.String MAX_CONNECTIONS_PER_ROUTE = "http.conn-manager.max-per-route";
     field public static final java.lang.String MAX_TOTAL_CONNECTIONS = "http.conn-manager.max-total";
     field public static final java.lang.String TIMEOUT = "http.conn-manager.timeout";
   }
 
-  public class ConnManagerParamBean extends org.apache.http.params.HttpAbstractParamBean {
+  public deprecated class ConnManagerParamBean extends org.apache.http.params.HttpAbstractParamBean {
     ctor public ConnManagerParamBean(org.apache.http.params.HttpParams);
     method public void setConnectionsPerRoute(org.apache.http.conn.params.ConnPerRouteBean);
     method public void setMaxTotalConnections(int);
     method public void setTimeout(long);
   }
 
-  public final class ConnManagerParams implements org.apache.http.conn.params.ConnManagerPNames {
+  public final deprecated class ConnManagerParams implements org.apache.http.conn.params.ConnManagerPNames {
     ctor public ConnManagerParams();
     method public static org.apache.http.conn.params.ConnPerRoute getMaxConnectionsPerRoute(org.apache.http.params.HttpParams);
     method public static int getMaxTotalConnections(org.apache.http.params.HttpParams);
@@ -55338,11 +55362,11 @@
     field public static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 20; // 0x14
   }
 
-  public abstract interface ConnPerRoute {
+  public abstract deprecated interface ConnPerRoute {
     method public abstract int getMaxForRoute(org.apache.http.conn.routing.HttpRoute);
   }
 
-  public final class ConnPerRouteBean implements org.apache.http.conn.params.ConnPerRoute {
+  public final deprecated class ConnPerRouteBean implements org.apache.http.conn.params.ConnPerRoute {
     ctor public ConnPerRouteBean(int);
     ctor public ConnPerRouteBean();
     method public int getDefaultMax();
@@ -55353,20 +55377,20 @@
     field public static final int DEFAULT_MAX_CONNECTIONS_PER_ROUTE = 2; // 0x2
   }
 
-  public abstract interface ConnRoutePNames {
+  public abstract deprecated interface ConnRoutePNames {
     field public static final java.lang.String DEFAULT_PROXY = "http.route.default-proxy";
     field public static final java.lang.String FORCED_ROUTE = "http.route.forced-route";
     field public static final java.lang.String LOCAL_ADDRESS = "http.route.local-address";
   }
 
-  public class ConnRouteParamBean extends org.apache.http.params.HttpAbstractParamBean {
+  public deprecated class ConnRouteParamBean extends org.apache.http.params.HttpAbstractParamBean {
     ctor public ConnRouteParamBean(org.apache.http.params.HttpParams);
     method public void setDefaultProxy(org.apache.http.HttpHost);
     method public void setForcedRoute(org.apache.http.conn.routing.HttpRoute);
     method public void setLocalAddress(java.net.InetAddress);
   }
 
-  public class ConnRouteParams implements org.apache.http.conn.params.ConnRoutePNames {
+  public deprecated class ConnRouteParams implements org.apache.http.conn.params.ConnRoutePNames {
     method public static org.apache.http.HttpHost getDefaultProxy(org.apache.http.params.HttpParams);
     method public static org.apache.http.conn.routing.HttpRoute getForcedRoute(org.apache.http.params.HttpParams);
     method public static java.net.InetAddress getLocalAddress(org.apache.http.params.HttpParams);
@@ -55381,7 +55405,7 @@
 
 package org.apache.http.conn.routing {
 
-  public class BasicRouteDirector implements org.apache.http.conn.routing.HttpRouteDirector {
+  public deprecated class BasicRouteDirector implements org.apache.http.conn.routing.HttpRouteDirector {
     ctor public BasicRouteDirector();
     method protected int directStep(org.apache.http.conn.routing.RouteInfo, org.apache.http.conn.routing.RouteInfo);
     method protected int firstStep(org.apache.http.conn.routing.RouteInfo);
@@ -55389,7 +55413,7 @@
     method protected int proxiedStep(org.apache.http.conn.routing.RouteInfo, org.apache.http.conn.routing.RouteInfo);
   }
 
-  public final class HttpRoute implements java.lang.Cloneable org.apache.http.conn.routing.RouteInfo {
+  public final deprecated class HttpRoute implements java.lang.Cloneable org.apache.http.conn.routing.RouteInfo {
     ctor public HttpRoute(org.apache.http.HttpHost, java.net.InetAddress, org.apache.http.HttpHost[], boolean, org.apache.http.conn.routing.RouteInfo.TunnelType, org.apache.http.conn.routing.RouteInfo.LayerType);
     ctor public HttpRoute(org.apache.http.HttpHost, java.net.InetAddress, org.apache.http.HttpHost, boolean, org.apache.http.conn.routing.RouteInfo.TunnelType, org.apache.http.conn.routing.RouteInfo.LayerType);
     ctor public HttpRoute(org.apache.http.HttpHost, java.net.InetAddress, boolean);
@@ -55411,7 +55435,7 @@
     method public final java.lang.String toString();
   }
 
-  public abstract interface HttpRouteDirector {
+  public abstract deprecated interface HttpRouteDirector {
     method public abstract int nextStep(org.apache.http.conn.routing.RouteInfo, org.apache.http.conn.routing.RouteInfo);
     field public static final int COMPLETE = 0; // 0x0
     field public static final int CONNECT_PROXY = 2; // 0x2
@@ -55422,11 +55446,11 @@
     field public static final int UNREACHABLE = -1; // 0xffffffff
   }
 
-  public abstract interface HttpRoutePlanner {
+  public abstract deprecated interface HttpRoutePlanner {
     method public abstract org.apache.http.conn.routing.HttpRoute determineRoute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException;
   }
 
-  public abstract interface RouteInfo {
+  public abstract deprecated interface RouteInfo {
     method public abstract int getHopCount();
     method public abstract org.apache.http.HttpHost getHopTarget(int);
     method public abstract org.apache.http.conn.routing.RouteInfo.LayerType getLayerType();
@@ -55453,7 +55477,7 @@
     enum_constant public static final org.apache.http.conn.routing.RouteInfo.TunnelType TUNNELLED;
   }
 
-  public final class RouteTracker implements java.lang.Cloneable org.apache.http.conn.routing.RouteInfo {
+  public final deprecated class RouteTracker implements java.lang.Cloneable org.apache.http.conn.routing.RouteInfo {
     ctor public RouteTracker(org.apache.http.HttpHost, java.net.InetAddress);
     ctor public RouteTracker(org.apache.http.conn.routing.HttpRoute);
     method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
@@ -55483,15 +55507,15 @@
 
 package org.apache.http.conn.scheme {
 
-  public abstract interface HostNameResolver {
+  public abstract deprecated interface HostNameResolver {
     method public abstract java.net.InetAddress resolve(java.lang.String) throws java.io.IOException;
   }
 
-  public abstract interface LayeredSocketFactory implements org.apache.http.conn.scheme.SocketFactory {
+  public abstract deprecated interface LayeredSocketFactory implements org.apache.http.conn.scheme.SocketFactory {
     method public abstract java.net.Socket createSocket(java.net.Socket, java.lang.String, int, boolean) throws java.io.IOException, java.net.UnknownHostException;
   }
 
-  public final class PlainSocketFactory implements org.apache.http.conn.scheme.SocketFactory {
+  public final deprecated class PlainSocketFactory implements org.apache.http.conn.scheme.SocketFactory {
     ctor public PlainSocketFactory(org.apache.http.conn.scheme.HostNameResolver);
     ctor public PlainSocketFactory();
     method public java.net.Socket connectSocket(java.net.Socket, java.lang.String, int, java.net.InetAddress, int, org.apache.http.params.HttpParams) throws java.io.IOException;
@@ -55500,7 +55524,7 @@
     method public final boolean isSecure(java.net.Socket) throws java.lang.IllegalArgumentException;
   }
 
-  public final class Scheme {
+  public final deprecated class Scheme {
     ctor public Scheme(java.lang.String, org.apache.http.conn.scheme.SocketFactory, int);
     method public final boolean equals(java.lang.Object);
     method public final int getDefaultPort();
@@ -55511,7 +55535,7 @@
     method public final java.lang.String toString();
   }
 
-  public final class SchemeRegistry {
+  public final deprecated class SchemeRegistry {
     ctor public SchemeRegistry();
     method public final synchronized org.apache.http.conn.scheme.Scheme get(java.lang.String);
     method public final synchronized org.apache.http.conn.scheme.Scheme getScheme(java.lang.String);
@@ -55522,7 +55546,7 @@
     method public final synchronized org.apache.http.conn.scheme.Scheme unregister(java.lang.String);
   }
 
-  public abstract interface SocketFactory {
+  public abstract deprecated interface SocketFactory {
     method public abstract java.net.Socket connectSocket(java.net.Socket, java.lang.String, int, java.net.InetAddress, int, org.apache.http.params.HttpParams) throws org.apache.http.conn.ConnectTimeoutException, java.io.IOException, java.net.UnknownHostException;
     method public abstract java.net.Socket createSocket() throws java.io.IOException;
     method public abstract boolean isSecure(java.net.Socket) throws java.lang.IllegalArgumentException;
@@ -55532,7 +55556,7 @@
 
 package org.apache.http.conn.ssl {
 
-  public abstract class AbstractVerifier implements org.apache.http.conn.ssl.X509HostnameVerifier {
+  public abstract deprecated class AbstractVerifier implements org.apache.http.conn.ssl.X509HostnameVerifier {
     ctor public AbstractVerifier();
     method public static boolean acceptableCountryWildcard(java.lang.String);
     method public static int countDots(java.lang.String);
@@ -55544,19 +55568,19 @@
     method public final void verify(java.lang.String, java.lang.String[], java.lang.String[], boolean) throws javax.net.ssl.SSLException;
   }
 
-  public class AllowAllHostnameVerifier extends org.apache.http.conn.ssl.AbstractVerifier {
+  public deprecated class AllowAllHostnameVerifier extends org.apache.http.conn.ssl.AbstractVerifier {
     ctor public AllowAllHostnameVerifier();
     method public final java.lang.String toString();
     method public final void verify(java.lang.String, java.lang.String[], java.lang.String[]);
   }
 
-  public class BrowserCompatHostnameVerifier extends org.apache.http.conn.ssl.AbstractVerifier {
+  public deprecated class BrowserCompatHostnameVerifier extends org.apache.http.conn.ssl.AbstractVerifier {
     ctor public BrowserCompatHostnameVerifier();
     method public final java.lang.String toString();
     method public final void verify(java.lang.String, java.lang.String[], java.lang.String[]) throws javax.net.ssl.SSLException;
   }
 
-  public class SSLSocketFactory implements org.apache.http.conn.scheme.LayeredSocketFactory {
+  public deprecated class SSLSocketFactory implements org.apache.http.conn.scheme.LayeredSocketFactory {
     ctor public SSLSocketFactory(java.lang.String, java.security.KeyStore, java.lang.String, java.security.KeyStore, java.security.SecureRandom, org.apache.http.conn.scheme.HostNameResolver) throws java.security.KeyManagementException, java.security.KeyStoreException, java.security.NoSuchAlgorithmException, java.security.UnrecoverableKeyException;
     ctor public SSLSocketFactory(java.security.KeyStore, java.lang.String, java.security.KeyStore) throws java.security.KeyManagementException, java.security.KeyStoreException, java.security.NoSuchAlgorithmException, java.security.UnrecoverableKeyException;
     ctor public SSLSocketFactory(java.security.KeyStore, java.lang.String) throws java.security.KeyManagementException, java.security.KeyStoreException, java.security.NoSuchAlgorithmException, java.security.UnrecoverableKeyException;
@@ -55576,13 +55600,13 @@
     field public static final java.lang.String TLS = "TLS";
   }
 
-  public class StrictHostnameVerifier extends org.apache.http.conn.ssl.AbstractVerifier {
+  public deprecated class StrictHostnameVerifier extends org.apache.http.conn.ssl.AbstractVerifier {
     ctor public StrictHostnameVerifier();
     method public final java.lang.String toString();
     method public final void verify(java.lang.String, java.lang.String[], java.lang.String[]) throws javax.net.ssl.SSLException;
   }
 
-  public abstract interface X509HostnameVerifier implements javax.net.ssl.HostnameVerifier {
+  public abstract deprecated interface X509HostnameVerifier implements javax.net.ssl.HostnameVerifier {
     method public abstract boolean verify(java.lang.String, javax.net.ssl.SSLSession);
     method public abstract void verify(java.lang.String, javax.net.ssl.SSLSocket) throws java.io.IOException;
     method public abstract void verify(java.lang.String, java.security.cert.X509Certificate) throws javax.net.ssl.SSLException;
@@ -55593,7 +55617,7 @@
 
 package org.apache.http.conn.util {
 
-  public class InetAddressUtils {
+  public deprecated class InetAddressUtils {
     method public static boolean isIPv4Address(java.lang.String);
     method public static boolean isIPv6Address(java.lang.String);
     method public static boolean isIPv6HexCompressedAddress(java.lang.String);
@@ -55604,7 +55628,7 @@
 
 package org.apache.http.cookie {
 
-  public abstract interface ClientCookie implements org.apache.http.cookie.Cookie {
+  public abstract deprecated interface ClientCookie implements org.apache.http.cookie.Cookie {
     method public abstract boolean containsAttribute(java.lang.String);
     method public abstract java.lang.String getAttribute(java.lang.String);
     field public static final java.lang.String COMMENTURL_ATTR = "commenturl";
@@ -55619,7 +55643,7 @@
     field public static final java.lang.String VERSION_ATTR = "version";
   }
 
-  public abstract interface Cookie {
+  public abstract deprecated interface Cookie {
     method public abstract java.lang.String getComment();
     method public abstract java.lang.String getCommentURL();
     method public abstract java.lang.String getDomain();
@@ -55634,18 +55658,18 @@
     method public abstract boolean isSecure();
   }
 
-  public abstract interface CookieAttributeHandler {
+  public abstract deprecated interface CookieAttributeHandler {
     method public abstract boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
     method public abstract void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
     method public abstract void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
   }
 
-  public class CookieIdentityComparator implements java.util.Comparator java.io.Serializable {
+  public deprecated class CookieIdentityComparator implements java.util.Comparator java.io.Serializable {
     ctor public CookieIdentityComparator();
     method public int compare(org.apache.http.cookie.Cookie, org.apache.http.cookie.Cookie);
   }
 
-  public final class CookieOrigin {
+  public final deprecated class CookieOrigin {
     ctor public CookieOrigin(java.lang.String, int, java.lang.String, boolean);
     method public java.lang.String getHost();
     method public java.lang.String getPath();
@@ -55653,12 +55677,12 @@
     method public boolean isSecure();
   }
 
-  public class CookiePathComparator implements java.util.Comparator java.io.Serializable {
+  public deprecated class CookiePathComparator implements java.util.Comparator java.io.Serializable {
     ctor public CookiePathComparator();
     method public int compare(org.apache.http.cookie.Cookie, org.apache.http.cookie.Cookie);
   }
 
-  public abstract interface CookieSpec {
+  public abstract deprecated interface CookieSpec {
     method public abstract java.util.List<org.apache.http.Header> formatCookies(java.util.List<org.apache.http.cookie.Cookie>);
     method public abstract int getVersion();
     method public abstract org.apache.http.Header getVersionHeader();
@@ -55667,11 +55691,11 @@
     method public abstract void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
   }
 
-  public abstract interface CookieSpecFactory {
+  public abstract deprecated interface CookieSpecFactory {
     method public abstract org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
   }
 
-  public final class CookieSpecRegistry {
+  public final deprecated class CookieSpecRegistry {
     ctor public CookieSpecRegistry();
     method public synchronized org.apache.http.cookie.CookieSpec getCookieSpec(java.lang.String, org.apache.http.params.HttpParams) throws java.lang.IllegalStateException;
     method public synchronized org.apache.http.cookie.CookieSpec getCookieSpec(java.lang.String) throws java.lang.IllegalStateException;
@@ -55681,20 +55705,20 @@
     method public synchronized void unregister(java.lang.String);
   }
 
-  public class MalformedCookieException extends org.apache.http.ProtocolException {
+  public deprecated class MalformedCookieException extends org.apache.http.ProtocolException {
     ctor public MalformedCookieException();
     ctor public MalformedCookieException(java.lang.String);
     ctor public MalformedCookieException(java.lang.String, java.lang.Throwable);
   }
 
-  public abstract interface SM {
+  public abstract deprecated interface SM {
     field public static final java.lang.String COOKIE = "Cookie";
     field public static final java.lang.String COOKIE2 = "Cookie2";
     field public static final java.lang.String SET_COOKIE = "Set-Cookie";
     field public static final java.lang.String SET_COOKIE2 = "Set-Cookie2";
   }
 
-  public abstract interface SetCookie implements org.apache.http.cookie.Cookie {
+  public abstract deprecated interface SetCookie implements org.apache.http.cookie.Cookie {
     method public abstract void setComment(java.lang.String);
     method public abstract void setDomain(java.lang.String);
     method public abstract void setExpiryDate(java.util.Date);
@@ -55704,7 +55728,7 @@
     method public abstract void setVersion(int);
   }
 
-  public abstract interface SetCookie2 implements org.apache.http.cookie.SetCookie {
+  public abstract deprecated interface SetCookie2 implements org.apache.http.cookie.SetCookie {
     method public abstract void setCommentURL(java.lang.String);
     method public abstract void setDiscard(boolean);
     method public abstract void setPorts(int[]);
@@ -55714,12 +55738,12 @@
 
 package org.apache.http.cookie.params {
 
-  public abstract interface CookieSpecPNames {
+  public abstract deprecated interface CookieSpecPNames {
     field public static final java.lang.String DATE_PATTERNS = "http.protocol.cookie-datepatterns";
     field public static final java.lang.String SINGLE_COOKIE_HEADER = "http.protocol.single-cookie-header";
   }
 
-  public class CookieSpecParamBean extends org.apache.http.params.HttpAbstractParamBean {
+  public deprecated class CookieSpecParamBean extends org.apache.http.params.HttpAbstractParamBean {
     ctor public CookieSpecParamBean(org.apache.http.params.HttpParams);
     method public void setDatePatterns(java.util.Collection<java.lang.String>);
     method public void setSingleHeader(boolean);
@@ -55729,7 +55753,7 @@
 
 package org.apache.http.entity {
 
-  public abstract class AbstractHttpEntity implements org.apache.http.HttpEntity {
+  public abstract deprecated class AbstractHttpEntity implements org.apache.http.HttpEntity {
     ctor protected AbstractHttpEntity();
     method public void consumeContent() throws java.io.IOException, java.lang.UnsupportedOperationException;
     method public org.apache.http.Header getContentEncoding();
@@ -55745,7 +55769,7 @@
     field protected org.apache.http.Header contentType;
   }
 
-  public class BasicHttpEntity extends org.apache.http.entity.AbstractHttpEntity {
+  public deprecated class BasicHttpEntity extends org.apache.http.entity.AbstractHttpEntity {
     ctor public BasicHttpEntity();
     method public java.io.InputStream getContent() throws java.lang.IllegalStateException;
     method public long getContentLength();
@@ -55756,11 +55780,11 @@
     method public void writeTo(java.io.OutputStream) throws java.io.IOException;
   }
 
-  public class BufferedHttpEntity extends org.apache.http.entity.HttpEntityWrapper {
+  public deprecated class BufferedHttpEntity extends org.apache.http.entity.HttpEntityWrapper {
     ctor public BufferedHttpEntity(org.apache.http.HttpEntity) throws java.io.IOException;
   }
 
-  public class ByteArrayEntity extends org.apache.http.entity.AbstractHttpEntity implements java.lang.Cloneable {
+  public deprecated class ByteArrayEntity extends org.apache.http.entity.AbstractHttpEntity implements java.lang.Cloneable {
     ctor public ByteArrayEntity(byte[]);
     method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
     method public java.io.InputStream getContent();
@@ -55771,17 +55795,17 @@
     field protected final byte[] content;
   }
 
-  public abstract interface ContentLengthStrategy {
+  public abstract deprecated interface ContentLengthStrategy {
     method public abstract long determineLength(org.apache.http.HttpMessage) throws org.apache.http.HttpException;
     field public static final int CHUNKED = -2; // 0xfffffffe
     field public static final int IDENTITY = -1; // 0xffffffff
   }
 
-  public abstract interface ContentProducer {
+  public abstract deprecated interface ContentProducer {
     method public abstract void writeTo(java.io.OutputStream) throws java.io.IOException;
   }
 
-  public class EntityTemplate extends org.apache.http.entity.AbstractHttpEntity {
+  public deprecated class EntityTemplate extends org.apache.http.entity.AbstractHttpEntity {
     ctor public EntityTemplate(org.apache.http.entity.ContentProducer);
     method public java.io.InputStream getContent();
     method public long getContentLength();
@@ -55790,7 +55814,7 @@
     method public void writeTo(java.io.OutputStream) throws java.io.IOException;
   }
 
-  public class FileEntity extends org.apache.http.entity.AbstractHttpEntity implements java.lang.Cloneable {
+  public deprecated class FileEntity extends org.apache.http.entity.AbstractHttpEntity implements java.lang.Cloneable {
     ctor public FileEntity(java.io.File, java.lang.String);
     method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
     method public java.io.InputStream getContent() throws java.io.IOException;
@@ -55801,7 +55825,7 @@
     field protected final java.io.File file;
   }
 
-  public class HttpEntityWrapper implements org.apache.http.HttpEntity {
+  public deprecated class HttpEntityWrapper implements org.apache.http.HttpEntity {
     ctor public HttpEntityWrapper(org.apache.http.HttpEntity);
     method public void consumeContent() throws java.io.IOException;
     method public java.io.InputStream getContent() throws java.io.IOException;
@@ -55815,7 +55839,7 @@
     field protected org.apache.http.HttpEntity wrappedEntity;
   }
 
-  public class InputStreamEntity extends org.apache.http.entity.AbstractHttpEntity {
+  public deprecated class InputStreamEntity extends org.apache.http.entity.AbstractHttpEntity {
     ctor public InputStreamEntity(java.io.InputStream, long);
     method public java.io.InputStream getContent() throws java.io.IOException;
     method public long getContentLength();
@@ -55824,7 +55848,7 @@
     method public void writeTo(java.io.OutputStream) throws java.io.IOException;
   }
 
-  public class SerializableEntity extends org.apache.http.entity.AbstractHttpEntity {
+  public deprecated class SerializableEntity extends org.apache.http.entity.AbstractHttpEntity {
     ctor public SerializableEntity(java.io.Serializable, boolean) throws java.io.IOException;
     method public java.io.InputStream getContent() throws java.io.IOException, java.lang.IllegalStateException;
     method public long getContentLength();
@@ -55833,7 +55857,7 @@
     method public void writeTo(java.io.OutputStream) throws java.io.IOException;
   }
 
-  public class StringEntity extends org.apache.http.entity.AbstractHttpEntity implements java.lang.Cloneable {
+  public deprecated class StringEntity extends org.apache.http.entity.AbstractHttpEntity implements java.lang.Cloneable {
     ctor public StringEntity(java.lang.String, java.lang.String) throws java.io.UnsupportedEncodingException;
     ctor public StringEntity(java.lang.String) throws java.io.UnsupportedEncodingException;
     method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
@@ -55849,7 +55873,7 @@
 
 package org.apache.http.impl {
 
-  public abstract class AbstractHttpClientConnection implements org.apache.http.HttpClientConnection {
+  public abstract deprecated class AbstractHttpClientConnection implements org.apache.http.HttpClientConnection {
     ctor public AbstractHttpClientConnection();
     method protected abstract void assertOpen() throws java.lang.IllegalStateException;
     method protected org.apache.http.impl.entity.EntityDeserializer createEntityDeserializer();
@@ -55869,7 +55893,7 @@
     method public void sendRequestHeader(org.apache.http.HttpRequest) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public abstract class AbstractHttpServerConnection implements org.apache.http.HttpServerConnection {
+  public abstract deprecated class AbstractHttpServerConnection implements org.apache.http.HttpServerConnection {
     ctor public AbstractHttpServerConnection();
     method protected abstract void assertOpen() throws java.lang.IllegalStateException;
     method protected org.apache.http.impl.entity.EntityDeserializer createEntityDeserializer();
@@ -55888,24 +55912,24 @@
     method public void sendResponseHeader(org.apache.http.HttpResponse) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public class DefaultConnectionReuseStrategy implements org.apache.http.ConnectionReuseStrategy {
+  public deprecated class DefaultConnectionReuseStrategy implements org.apache.http.ConnectionReuseStrategy {
     ctor public DefaultConnectionReuseStrategy();
     method protected org.apache.http.TokenIterator createTokenIterator(org.apache.http.HeaderIterator);
     method public boolean keepAlive(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
   }
 
-  public class DefaultHttpClientConnection extends org.apache.http.impl.SocketHttpClientConnection {
+  public deprecated class DefaultHttpClientConnection extends org.apache.http.impl.SocketHttpClientConnection {
     ctor public DefaultHttpClientConnection();
     method public void bind(java.net.Socket, org.apache.http.params.HttpParams) throws java.io.IOException;
   }
 
-  public class DefaultHttpRequestFactory implements org.apache.http.HttpRequestFactory {
+  public deprecated class DefaultHttpRequestFactory implements org.apache.http.HttpRequestFactory {
     ctor public DefaultHttpRequestFactory();
     method public org.apache.http.HttpRequest newHttpRequest(org.apache.http.RequestLine) throws org.apache.http.MethodNotSupportedException;
     method public org.apache.http.HttpRequest newHttpRequest(java.lang.String, java.lang.String) throws org.apache.http.MethodNotSupportedException;
   }
 
-  public class DefaultHttpResponseFactory implements org.apache.http.HttpResponseFactory {
+  public deprecated class DefaultHttpResponseFactory implements org.apache.http.HttpResponseFactory {
     ctor public DefaultHttpResponseFactory(org.apache.http.ReasonPhraseCatalog);
     ctor public DefaultHttpResponseFactory();
     method protected java.util.Locale determineLocale(org.apache.http.protocol.HttpContext);
@@ -55914,18 +55938,18 @@
     field protected final org.apache.http.ReasonPhraseCatalog reasonCatalog;
   }
 
-  public class DefaultHttpServerConnection extends org.apache.http.impl.SocketHttpServerConnection {
+  public deprecated class DefaultHttpServerConnection extends org.apache.http.impl.SocketHttpServerConnection {
     ctor public DefaultHttpServerConnection();
     method public void bind(java.net.Socket, org.apache.http.params.HttpParams) throws java.io.IOException;
   }
 
-  public class EnglishReasonPhraseCatalog implements org.apache.http.ReasonPhraseCatalog {
+  public deprecated class EnglishReasonPhraseCatalog implements org.apache.http.ReasonPhraseCatalog {
     ctor protected EnglishReasonPhraseCatalog();
     method public java.lang.String getReason(int, java.util.Locale);
     field public static final org.apache.http.impl.EnglishReasonPhraseCatalog INSTANCE;
   }
 
-  public class HttpConnectionMetricsImpl implements org.apache.http.HttpConnectionMetrics {
+  public deprecated class HttpConnectionMetricsImpl implements org.apache.http.HttpConnectionMetrics {
     ctor public HttpConnectionMetricsImpl(org.apache.http.io.HttpTransportMetrics, org.apache.http.io.HttpTransportMetrics);
     method public java.lang.Object getMetric(java.lang.String);
     method public long getReceivedBytesCount();
@@ -55942,12 +55966,12 @@
     field public static final java.lang.String SENT_BYTES_COUNT = "http.sent-bytes-count";
   }
 
-  public class NoConnectionReuseStrategy implements org.apache.http.ConnectionReuseStrategy {
+  public deprecated class NoConnectionReuseStrategy implements org.apache.http.ConnectionReuseStrategy {
     ctor public NoConnectionReuseStrategy();
     method public boolean keepAlive(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
   }
 
-  public class SocketHttpClientConnection extends org.apache.http.impl.AbstractHttpClientConnection implements org.apache.http.HttpInetConnection {
+  public deprecated class SocketHttpClientConnection extends org.apache.http.impl.AbstractHttpClientConnection implements org.apache.http.HttpInetConnection {
     ctor public SocketHttpClientConnection();
     method protected void assertNotOpen();
     method protected void assertOpen();
@@ -55966,7 +55990,7 @@
     method public void shutdown() throws java.io.IOException;
   }
 
-  public class SocketHttpServerConnection extends org.apache.http.impl.AbstractHttpServerConnection implements org.apache.http.HttpInetConnection {
+  public deprecated class SocketHttpServerConnection extends org.apache.http.impl.AbstractHttpServerConnection implements org.apache.http.HttpInetConnection {
     ctor public SocketHttpServerConnection();
     method protected void assertNotOpen();
     method protected void assertOpen();
@@ -55989,14 +56013,14 @@
 
 package org.apache.http.impl.auth {
 
-  public abstract class AuthSchemeBase implements org.apache.http.auth.AuthScheme {
+  public abstract deprecated class AuthSchemeBase implements org.apache.http.auth.AuthScheme {
     ctor public AuthSchemeBase();
     method public boolean isProxy();
     method protected abstract void parseChallenge(org.apache.http.util.CharArrayBuffer, int, int) throws org.apache.http.auth.MalformedChallengeException;
     method public void processChallenge(org.apache.http.Header) throws org.apache.http.auth.MalformedChallengeException;
   }
 
-  public class BasicScheme extends org.apache.http.impl.auth.RFC2617Scheme {
+  public deprecated class BasicScheme extends org.apache.http.impl.auth.RFC2617Scheme {
     ctor public BasicScheme();
     method public org.apache.http.Header authenticate(org.apache.http.auth.Credentials, org.apache.http.HttpRequest) throws org.apache.http.auth.AuthenticationException;
     method public static org.apache.http.Header authenticate(org.apache.http.auth.Credentials, java.lang.String, boolean);
@@ -56005,12 +56029,12 @@
     method public boolean isConnectionBased();
   }
 
-  public class BasicSchemeFactory implements org.apache.http.auth.AuthSchemeFactory {
+  public deprecated class BasicSchemeFactory implements org.apache.http.auth.AuthSchemeFactory {
     ctor public BasicSchemeFactory();
     method public org.apache.http.auth.AuthScheme newInstance(org.apache.http.params.HttpParams);
   }
 
-  public class DigestScheme extends org.apache.http.impl.auth.RFC2617Scheme {
+  public deprecated class DigestScheme extends org.apache.http.impl.auth.RFC2617Scheme {
     ctor public DigestScheme();
     method public org.apache.http.Header authenticate(org.apache.http.auth.Credentials, org.apache.http.HttpRequest) throws org.apache.http.auth.AuthenticationException;
     method public static java.lang.String createCnonce();
@@ -56020,23 +56044,23 @@
     method public void overrideParamter(java.lang.String, java.lang.String);
   }
 
-  public class DigestSchemeFactory implements org.apache.http.auth.AuthSchemeFactory {
+  public deprecated class DigestSchemeFactory implements org.apache.http.auth.AuthSchemeFactory {
     ctor public DigestSchemeFactory();
     method public org.apache.http.auth.AuthScheme newInstance(org.apache.http.params.HttpParams);
   }
 
-  public abstract interface NTLMEngine {
+  public abstract deprecated interface NTLMEngine {
     method public abstract java.lang.String generateType1Msg(java.lang.String, java.lang.String) throws org.apache.http.impl.auth.NTLMEngineException;
     method public abstract java.lang.String generateType3Msg(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String) throws org.apache.http.impl.auth.NTLMEngineException;
   }
 
-  public class NTLMEngineException extends org.apache.http.auth.AuthenticationException {
+  public deprecated class NTLMEngineException extends org.apache.http.auth.AuthenticationException {
     ctor public NTLMEngineException();
     ctor public NTLMEngineException(java.lang.String);
     ctor public NTLMEngineException(java.lang.String, java.lang.Throwable);
   }
 
-  public class NTLMScheme extends org.apache.http.impl.auth.AuthSchemeBase {
+  public deprecated class NTLMScheme extends org.apache.http.impl.auth.AuthSchemeBase {
     ctor public NTLMScheme(org.apache.http.impl.auth.NTLMEngine);
     method public org.apache.http.Header authenticate(org.apache.http.auth.Credentials, org.apache.http.HttpRequest) throws org.apache.http.auth.AuthenticationException;
     method public java.lang.String getParameter(java.lang.String);
@@ -56047,7 +56071,7 @@
     method protected void parseChallenge(org.apache.http.util.CharArrayBuffer, int, int) throws org.apache.http.auth.MalformedChallengeException;
   }
 
-  public abstract class RFC2617Scheme extends org.apache.http.impl.auth.AuthSchemeBase {
+  public abstract deprecated class RFC2617Scheme extends org.apache.http.impl.auth.AuthSchemeBase {
     ctor public RFC2617Scheme();
     method public java.lang.String getParameter(java.lang.String);
     method protected java.util.Map<java.lang.String, java.lang.String> getParameters();
@@ -56055,7 +56079,7 @@
     method protected void parseChallenge(org.apache.http.util.CharArrayBuffer, int, int) throws org.apache.http.auth.MalformedChallengeException;
   }
 
-  public class UnsupportedDigestAlgorithmException extends java.lang.RuntimeException {
+  public deprecated class UnsupportedDigestAlgorithmException extends java.lang.RuntimeException {
     ctor public UnsupportedDigestAlgorithmException();
     ctor public UnsupportedDigestAlgorithmException(java.lang.String);
     ctor public UnsupportedDigestAlgorithmException(java.lang.String, java.lang.Throwable);
@@ -56065,14 +56089,14 @@
 
 package org.apache.http.impl.client {
 
-  public abstract class AbstractAuthenticationHandler implements org.apache.http.client.AuthenticationHandler {
+  public abstract deprecated class AbstractAuthenticationHandler implements org.apache.http.client.AuthenticationHandler {
     ctor public AbstractAuthenticationHandler();
     method protected java.util.List<java.lang.String> getAuthPreferences();
     method protected java.util.Map<java.lang.String, org.apache.http.Header> parseChallenges(org.apache.http.Header[]) throws org.apache.http.auth.MalformedChallengeException;
     method public org.apache.http.auth.AuthScheme selectScheme(java.util.Map<java.lang.String, org.apache.http.Header>, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.AuthenticationException;
   }
 
-  public abstract class AbstractHttpClient implements org.apache.http.client.HttpClient {
+  public abstract deprecated class AbstractHttpClient implements org.apache.http.client.HttpClient {
     ctor protected AbstractHttpClient(org.apache.http.conn.ClientConnectionManager, org.apache.http.params.HttpParams);
     method public synchronized void addRequestInterceptor(org.apache.http.HttpRequestInterceptor);
     method public synchronized void addRequestInterceptor(org.apache.http.HttpRequestInterceptor, int);
@@ -56144,7 +56168,7 @@
     method public synchronized void setUserTokenHandler(org.apache.http.client.UserTokenHandler);
   }
 
-  public class BasicCookieStore implements org.apache.http.client.CookieStore {
+  public deprecated class BasicCookieStore implements org.apache.http.client.CookieStore {
     ctor public BasicCookieStore();
     method public synchronized void addCookie(org.apache.http.cookie.Cookie);
     method public synchronized void addCookies(org.apache.http.cookie.Cookie[]);
@@ -56153,19 +56177,19 @@
     method public synchronized java.util.List<org.apache.http.cookie.Cookie> getCookies();
   }
 
-  public class BasicCredentialsProvider implements org.apache.http.client.CredentialsProvider {
+  public deprecated class BasicCredentialsProvider implements org.apache.http.client.CredentialsProvider {
     ctor public BasicCredentialsProvider();
     method public synchronized void clear();
     method public synchronized org.apache.http.auth.Credentials getCredentials(org.apache.http.auth.AuthScope);
     method public synchronized void setCredentials(org.apache.http.auth.AuthScope, org.apache.http.auth.Credentials);
   }
 
-  public class BasicResponseHandler implements org.apache.http.client.ResponseHandler {
+  public deprecated class BasicResponseHandler implements org.apache.http.client.ResponseHandler {
     ctor public BasicResponseHandler();
     method public java.lang.String handleResponse(org.apache.http.HttpResponse) throws org.apache.http.client.HttpResponseException, java.io.IOException;
   }
 
-  public class ClientParamsStack extends org.apache.http.params.AbstractHttpParams {
+  public deprecated class ClientParamsStack extends org.apache.http.params.AbstractHttpParams {
     ctor public ClientParamsStack(org.apache.http.params.HttpParams, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams);
     ctor public ClientParamsStack(org.apache.http.impl.client.ClientParamsStack);
     ctor public ClientParamsStack(org.apache.http.impl.client.ClientParamsStack, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams, org.apache.http.params.HttpParams);
@@ -56183,12 +56207,12 @@
     field protected final org.apache.http.params.HttpParams requestParams;
   }
 
-  public class DefaultConnectionKeepAliveStrategy implements org.apache.http.conn.ConnectionKeepAliveStrategy {
+  public deprecated class DefaultConnectionKeepAliveStrategy implements org.apache.http.conn.ConnectionKeepAliveStrategy {
     ctor public DefaultConnectionKeepAliveStrategy();
     method public long getKeepAliveDuration(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
   }
 
-  public class DefaultHttpClient extends org.apache.http.impl.client.AbstractHttpClient {
+  public deprecated class DefaultHttpClient extends org.apache.http.impl.client.AbstractHttpClient {
     ctor public DefaultHttpClient(org.apache.http.conn.ClientConnectionManager, org.apache.http.params.HttpParams);
     ctor public DefaultHttpClient(org.apache.http.params.HttpParams);
     ctor public DefaultHttpClient();
@@ -56211,7 +56235,7 @@
     method protected org.apache.http.client.UserTokenHandler createUserTokenHandler();
   }
 
-  public class DefaultHttpRequestRetryHandler implements org.apache.http.client.HttpRequestRetryHandler {
+  public deprecated class DefaultHttpRequestRetryHandler implements org.apache.http.client.HttpRequestRetryHandler {
     ctor public DefaultHttpRequestRetryHandler(int, boolean);
     ctor public DefaultHttpRequestRetryHandler();
     method public int getRetryCount();
@@ -56219,19 +56243,19 @@
     method public boolean retryRequest(java.io.IOException, int, org.apache.http.protocol.HttpContext);
   }
 
-  public class DefaultProxyAuthenticationHandler extends org.apache.http.impl.client.AbstractAuthenticationHandler {
+  public deprecated class DefaultProxyAuthenticationHandler extends org.apache.http.impl.client.AbstractAuthenticationHandler {
     ctor public DefaultProxyAuthenticationHandler();
     method public java.util.Map<java.lang.String, org.apache.http.Header> getChallenges(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.MalformedChallengeException;
     method public boolean isAuthenticationRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
   }
 
-  public class DefaultRedirectHandler implements org.apache.http.client.RedirectHandler {
+  public deprecated class DefaultRedirectHandler implements org.apache.http.client.RedirectHandler {
     ctor public DefaultRedirectHandler();
     method public java.net.URI getLocationURI(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.ProtocolException;
     method public boolean isRedirectRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
   }
 
-  public class DefaultRequestDirector implements org.apache.http.client.RequestDirector {
+  public deprecated class DefaultRequestDirector implements org.apache.http.client.RequestDirector {
     ctor public DefaultRequestDirector(org.apache.http.protocol.HttpRequestExecutor, org.apache.http.conn.ClientConnectionManager, org.apache.http.ConnectionReuseStrategy, org.apache.http.conn.ConnectionKeepAliveStrategy, org.apache.http.conn.routing.HttpRoutePlanner, org.apache.http.protocol.HttpProcessor, org.apache.http.client.HttpRequestRetryHandler, org.apache.http.client.RedirectHandler, org.apache.http.client.AuthenticationHandler, org.apache.http.client.AuthenticationHandler, org.apache.http.client.UserTokenHandler, org.apache.http.params.HttpParams);
     method protected org.apache.http.HttpRequest createConnectRequest(org.apache.http.conn.routing.HttpRoute, org.apache.http.protocol.HttpContext);
     method protected boolean createTunnelToProxy(org.apache.http.conn.routing.HttpRoute, int, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
@@ -56254,32 +56278,32 @@
     field protected final org.apache.http.conn.routing.HttpRoutePlanner routePlanner;
   }
 
-  public class DefaultTargetAuthenticationHandler extends org.apache.http.impl.client.AbstractAuthenticationHandler {
+  public deprecated class DefaultTargetAuthenticationHandler extends org.apache.http.impl.client.AbstractAuthenticationHandler {
     ctor public DefaultTargetAuthenticationHandler();
     method public java.util.Map<java.lang.String, org.apache.http.Header> getChallenges(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.auth.MalformedChallengeException;
     method public boolean isAuthenticationRequested(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext);
   }
 
-  public class DefaultUserTokenHandler implements org.apache.http.client.UserTokenHandler {
+  public deprecated class DefaultUserTokenHandler implements org.apache.http.client.UserTokenHandler {
     ctor public DefaultUserTokenHandler();
     method public java.lang.Object getUserToken(org.apache.http.protocol.HttpContext);
   }
 
-  public class EntityEnclosingRequestWrapper extends org.apache.http.impl.client.RequestWrapper implements org.apache.http.HttpEntityEnclosingRequest {
+  public deprecated class EntityEnclosingRequestWrapper extends org.apache.http.impl.client.RequestWrapper implements org.apache.http.HttpEntityEnclosingRequest {
     ctor public EntityEnclosingRequestWrapper(org.apache.http.HttpEntityEnclosingRequest) throws org.apache.http.ProtocolException;
     method public boolean expectContinue();
     method public org.apache.http.HttpEntity getEntity();
     method public void setEntity(org.apache.http.HttpEntity);
   }
 
-  public class RedirectLocations {
+  public deprecated class RedirectLocations {
     ctor public RedirectLocations();
     method public void add(java.net.URI);
     method public boolean contains(java.net.URI);
     method public boolean remove(java.net.URI);
   }
 
-  public class RequestWrapper extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.client.methods.HttpUriRequest {
+  public deprecated class RequestWrapper extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.client.methods.HttpUriRequest {
     ctor public RequestWrapper(org.apache.http.HttpRequest) throws org.apache.http.ProtocolException;
     method public void abort() throws java.lang.UnsupportedOperationException;
     method public int getExecCount();
@@ -56297,7 +56321,7 @@
     method public void setURI(java.net.URI);
   }
 
-  public class RoutedRequest {
+  public deprecated class RoutedRequest {
     ctor public RoutedRequest(org.apache.http.impl.client.RequestWrapper, org.apache.http.conn.routing.HttpRoute);
     method public final org.apache.http.impl.client.RequestWrapper getRequest();
     method public final org.apache.http.conn.routing.HttpRoute getRoute();
@@ -56305,7 +56329,7 @@
     field protected final org.apache.http.conn.routing.HttpRoute route;
   }
 
-  public class TunnelRefusedException extends org.apache.http.HttpException {
+  public deprecated class TunnelRefusedException extends org.apache.http.HttpException {
     ctor public TunnelRefusedException(java.lang.String, org.apache.http.HttpResponse);
     method public org.apache.http.HttpResponse getResponse();
   }
@@ -56314,7 +56338,7 @@
 
 package org.apache.http.impl.conn {
 
-  public abstract class AbstractClientConnAdapter implements org.apache.http.conn.ManagedClientConnection {
+  public abstract deprecated class AbstractClientConnAdapter implements org.apache.http.conn.ManagedClientConnection {
     ctor protected AbstractClientConnAdapter(org.apache.http.conn.ClientConnectionManager, org.apache.http.conn.OperatedClientConnection);
     method public void abortConnection();
     method protected final void assertNotAborted() throws java.io.InterruptedIOException;
@@ -56346,7 +56370,7 @@
     method public void unmarkReusable();
   }
 
-  public abstract class AbstractPoolEntry {
+  public abstract deprecated class AbstractPoolEntry {
     ctor protected AbstractPoolEntry(org.apache.http.conn.ClientConnectionOperator, org.apache.http.conn.routing.HttpRoute);
     method public java.lang.Object getState();
     method public void layerProtocol(org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
@@ -56362,7 +56386,7 @@
     field protected volatile org.apache.http.conn.routing.RouteTracker tracker;
   }
 
-  public abstract class AbstractPooledConnAdapter extends org.apache.http.impl.conn.AbstractClientConnAdapter {
+  public abstract deprecated class AbstractPooledConnAdapter extends org.apache.http.impl.conn.AbstractClientConnAdapter {
     ctor protected AbstractPooledConnAdapter(org.apache.http.conn.ClientConnectionManager, org.apache.http.impl.conn.AbstractPoolEntry);
     method protected final void assertAttached();
     method public void close() throws java.io.IOException;
@@ -56377,7 +56401,7 @@
     field protected volatile org.apache.http.impl.conn.AbstractPoolEntry poolEntry;
   }
 
-  public class DefaultClientConnection extends org.apache.http.impl.SocketHttpClientConnection implements org.apache.http.conn.OperatedClientConnection {
+  public deprecated class DefaultClientConnection extends org.apache.http.impl.SocketHttpClientConnection implements org.apache.http.conn.OperatedClientConnection {
     ctor public DefaultClientConnection();
     method public final java.net.Socket getSocket();
     method public final org.apache.http.HttpHost getTargetHost();
@@ -56387,7 +56411,7 @@
     method public void update(java.net.Socket, org.apache.http.HttpHost, boolean, org.apache.http.params.HttpParams) throws java.io.IOException;
   }
 
-  public class DefaultClientConnectionOperator implements org.apache.http.conn.ClientConnectionOperator {
+  public deprecated class DefaultClientConnectionOperator implements org.apache.http.conn.ClientConnectionOperator {
     ctor public DefaultClientConnectionOperator(org.apache.http.conn.scheme.SchemeRegistry);
     method public org.apache.http.conn.OperatedClientConnection createConnection();
     method public void openConnection(org.apache.http.conn.OperatedClientConnection, org.apache.http.HttpHost, java.net.InetAddress, org.apache.http.protocol.HttpContext, org.apache.http.params.HttpParams) throws java.io.IOException;
@@ -56396,18 +56420,18 @@
     field protected org.apache.http.conn.scheme.SchemeRegistry schemeRegistry;
   }
 
-  public class DefaultHttpRoutePlanner implements org.apache.http.conn.routing.HttpRoutePlanner {
+  public deprecated class DefaultHttpRoutePlanner implements org.apache.http.conn.routing.HttpRoutePlanner {
     ctor public DefaultHttpRoutePlanner(org.apache.http.conn.scheme.SchemeRegistry);
     method public org.apache.http.conn.routing.HttpRoute determineRoute(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException;
     field protected org.apache.http.conn.scheme.SchemeRegistry schemeRegistry;
   }
 
-  public class DefaultResponseParser extends org.apache.http.impl.io.AbstractMessageParser {
+  public deprecated class DefaultResponseParser extends org.apache.http.impl.io.AbstractMessageParser {
     ctor public DefaultResponseParser(org.apache.http.io.SessionInputBuffer, org.apache.http.message.LineParser, org.apache.http.HttpResponseFactory, org.apache.http.params.HttpParams);
     method protected org.apache.http.HttpMessage parseHead(org.apache.http.io.SessionInputBuffer) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public class IdleConnectionHandler {
+  public deprecated class IdleConnectionHandler {
     ctor public IdleConnectionHandler();
     method public void add(org.apache.http.HttpConnection, long, java.util.concurrent.TimeUnit);
     method public void closeExpiredConnections();
@@ -56416,7 +56440,7 @@
     method public void removeAll();
   }
 
-  public class LoggingSessionInputBuffer implements org.apache.http.io.SessionInputBuffer {
+  public deprecated class LoggingSessionInputBuffer implements org.apache.http.io.SessionInputBuffer {
     ctor public LoggingSessionInputBuffer(org.apache.http.io.SessionInputBuffer, org.apache.http.impl.conn.Wire);
     method public org.apache.http.io.HttpTransportMetrics getMetrics();
     method public boolean isDataAvailable(int) throws java.io.IOException;
@@ -56427,7 +56451,7 @@
     method public int readLine(org.apache.http.util.CharArrayBuffer) throws java.io.IOException;
   }
 
-  public class LoggingSessionOutputBuffer implements org.apache.http.io.SessionOutputBuffer {
+  public deprecated class LoggingSessionOutputBuffer implements org.apache.http.io.SessionOutputBuffer {
     ctor public LoggingSessionOutputBuffer(org.apache.http.io.SessionOutputBuffer, org.apache.http.impl.conn.Wire);
     method public void flush() throws java.io.IOException;
     method public org.apache.http.io.HttpTransportMetrics getMetrics();
@@ -56438,7 +56462,7 @@
     method public void writeLine(java.lang.String) throws java.io.IOException;
   }
 
-  public class ProxySelectorRoutePlanner implements org.apache.http.conn.routing.HttpRoutePlanner {
+  public deprecated class ProxySelectorRoutePlanner implements org.apache.http.conn.routing.HttpRoutePlanner {
     ctor public ProxySelectorRoutePlanner(org.apache.http.conn.scheme.SchemeRegistry, java.net.ProxySelector);
     method protected java.net.Proxy chooseProxy(java.util.List<java.net.Proxy>, org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext);
     method protected org.apache.http.HttpHost determineProxy(org.apache.http.HttpHost, org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException;
@@ -56450,7 +56474,7 @@
     field protected org.apache.http.conn.scheme.SchemeRegistry schemeRegistry;
   }
 
-  public class SingleClientConnManager implements org.apache.http.conn.ClientConnectionManager {
+  public deprecated class SingleClientConnManager implements org.apache.http.conn.ClientConnectionManager {
     ctor public SingleClientConnManager(org.apache.http.params.HttpParams, org.apache.http.conn.scheme.SchemeRegistry);
     method protected final void assertStillUp() throws java.lang.IllegalStateException;
     method public void closeExpiredConnections();
@@ -56483,7 +56507,7 @@
     method protected void shutdown() throws java.io.IOException;
   }
 
-  public class Wire {
+  public deprecated class Wire {
     ctor public Wire(org.apache.commons.logging.Log);
     method public boolean enabled();
     method public void input(java.io.InputStream) throws java.io.IOException;
@@ -56502,7 +56526,7 @@
 
 package org.apache.http.impl.conn.tsccm {
 
-  public abstract class AbstractConnPool implements org.apache.http.impl.conn.tsccm.RefQueueHandler {
+  public abstract deprecated class AbstractConnPool implements org.apache.http.impl.conn.tsccm.RefQueueHandler {
     ctor protected AbstractConnPool();
     method protected void closeConnection(org.apache.http.conn.OperatedClientConnection);
     method public void closeExpiredConnections();
@@ -56523,24 +56547,24 @@
     field protected java.lang.ref.ReferenceQueue refQueue;
   }
 
-  public class BasicPoolEntry extends org.apache.http.impl.conn.AbstractPoolEntry {
+  public deprecated class BasicPoolEntry extends org.apache.http.impl.conn.AbstractPoolEntry {
     ctor public BasicPoolEntry(org.apache.http.conn.ClientConnectionOperator, org.apache.http.conn.routing.HttpRoute, java.lang.ref.ReferenceQueue<java.lang.Object>);
     method protected final org.apache.http.conn.OperatedClientConnection getConnection();
     method protected final org.apache.http.conn.routing.HttpRoute getPlannedRoute();
     method protected final org.apache.http.impl.conn.tsccm.BasicPoolEntryRef getWeakRef();
   }
 
-  public class BasicPoolEntryRef extends java.lang.ref.WeakReference {
+  public deprecated class BasicPoolEntryRef extends java.lang.ref.WeakReference {
     ctor public BasicPoolEntryRef(org.apache.http.impl.conn.tsccm.BasicPoolEntry, java.lang.ref.ReferenceQueue<java.lang.Object>);
     method public final org.apache.http.conn.routing.HttpRoute getRoute();
   }
 
-  public class BasicPooledConnAdapter extends org.apache.http.impl.conn.AbstractPooledConnAdapter {
+  public deprecated class BasicPooledConnAdapter extends org.apache.http.impl.conn.AbstractPooledConnAdapter {
     ctor protected BasicPooledConnAdapter(org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager, org.apache.http.impl.conn.AbstractPoolEntry);
     method protected org.apache.http.impl.conn.AbstractPoolEntry getPoolEntry();
   }
 
-  public class ConnPoolByRoute extends org.apache.http.impl.conn.tsccm.AbstractConnPool {
+  public deprecated class ConnPoolByRoute extends org.apache.http.impl.conn.tsccm.AbstractConnPool {
     ctor public ConnPoolByRoute(org.apache.http.conn.ClientConnectionOperator, org.apache.http.params.HttpParams);
     method protected org.apache.http.impl.conn.tsccm.BasicPoolEntry createEntry(org.apache.http.impl.conn.tsccm.RouteSpecificPool, org.apache.http.conn.ClientConnectionOperator);
     method protected java.util.Queue<org.apache.http.impl.conn.tsccm.BasicPoolEntry> createFreeConnQueue();
@@ -56566,16 +56590,16 @@
     field protected java.util.Queue waitingThreads;
   }
 
-  public abstract interface PoolEntryRequest {
+  public abstract deprecated interface PoolEntryRequest {
     method public abstract void abortRequest();
     method public abstract org.apache.http.impl.conn.tsccm.BasicPoolEntry getPoolEntry(long, java.util.concurrent.TimeUnit) throws org.apache.http.conn.ConnectionPoolTimeoutException, java.lang.InterruptedException;
   }
 
-  public abstract interface RefQueueHandler {
+  public abstract deprecated interface RefQueueHandler {
     method public abstract void handleReference(java.lang.ref.Reference<?>);
   }
 
-  public class RefQueueWorker implements java.lang.Runnable {
+  public deprecated class RefQueueWorker implements java.lang.Runnable {
     ctor public RefQueueWorker(java.lang.ref.ReferenceQueue<?>, org.apache.http.impl.conn.tsccm.RefQueueHandler);
     method public void run();
     method public void shutdown();
@@ -56584,7 +56608,7 @@
     field protected volatile java.lang.Thread workerThread;
   }
 
-  public class RouteSpecificPool {
+  public deprecated class RouteSpecificPool {
     ctor public RouteSpecificPool(org.apache.http.conn.routing.HttpRoute, int);
     method public org.apache.http.impl.conn.tsccm.BasicPoolEntry allocEntry(java.lang.Object);
     method public void createdEntry(org.apache.http.impl.conn.tsccm.BasicPoolEntry);
@@ -56607,7 +56631,7 @@
     field protected final java.util.Queue waitingThreads;
   }
 
-  public class ThreadSafeClientConnManager implements org.apache.http.conn.ClientConnectionManager {
+  public deprecated class ThreadSafeClientConnManager implements org.apache.http.conn.ClientConnectionManager {
     ctor public ThreadSafeClientConnManager(org.apache.http.params.HttpParams, org.apache.http.conn.scheme.SchemeRegistry);
     method public void closeExpiredConnections();
     method public void closeIdleConnections(long, java.util.concurrent.TimeUnit);
@@ -56624,7 +56648,7 @@
     field protected org.apache.http.conn.scheme.SchemeRegistry schemeRegistry;
   }
 
-  public class WaitingThread {
+  public deprecated class WaitingThread {
     ctor public WaitingThread(java.util.concurrent.locks.Condition, org.apache.http.impl.conn.tsccm.RouteSpecificPool);
     method public boolean await(java.util.Date) throws java.lang.InterruptedException;
     method public final java.util.concurrent.locks.Condition getCondition();
@@ -56634,7 +56658,7 @@
     method public void wakeup();
   }
 
-  public class WaitingThreadAborter {
+  public deprecated class WaitingThreadAborter {
     ctor public WaitingThreadAborter();
     method public void abort();
     method public void setWaitingThread(org.apache.http.impl.conn.tsccm.WaitingThread);
@@ -56644,13 +56668,13 @@
 
 package org.apache.http.impl.cookie {
 
-  public abstract class AbstractCookieAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
+  public abstract deprecated class AbstractCookieAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
     ctor public AbstractCookieAttributeHandler();
     method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
     method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
   }
 
-  public abstract class AbstractCookieSpec implements org.apache.http.cookie.CookieSpec {
+  public abstract deprecated class AbstractCookieSpec implements org.apache.http.cookie.CookieSpec {
     ctor public AbstractCookieSpec();
     method protected org.apache.http.cookie.CookieAttributeHandler findAttribHandler(java.lang.String);
     method protected org.apache.http.cookie.CookieAttributeHandler getAttribHandler(java.lang.String);
@@ -56658,7 +56682,7 @@
     method public void registerAttribHandler(java.lang.String, org.apache.http.cookie.CookieAttributeHandler);
   }
 
-  public class BasicClientCookie implements org.apache.http.cookie.ClientCookie java.lang.Cloneable org.apache.http.cookie.SetCookie {
+  public deprecated class BasicClientCookie implements org.apache.http.cookie.ClientCookie java.lang.Cloneable org.apache.http.cookie.SetCookie {
     ctor public BasicClientCookie(java.lang.String, java.lang.String);
     method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
     method public boolean containsAttribute(java.lang.String);
@@ -56685,48 +56709,48 @@
     method public void setVersion(int);
   }
 
-  public class BasicClientCookie2 extends org.apache.http.impl.cookie.BasicClientCookie implements org.apache.http.cookie.SetCookie2 {
+  public deprecated class BasicClientCookie2 extends org.apache.http.impl.cookie.BasicClientCookie implements org.apache.http.cookie.SetCookie2 {
     ctor public BasicClientCookie2(java.lang.String, java.lang.String);
     method public void setCommentURL(java.lang.String);
     method public void setDiscard(boolean);
     method public void setPorts(int[]);
   }
 
-  public class BasicCommentHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
+  public deprecated class BasicCommentHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
     ctor public BasicCommentHandler();
     method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
   }
 
-  public class BasicDomainHandler implements org.apache.http.cookie.CookieAttributeHandler {
+  public deprecated class BasicDomainHandler implements org.apache.http.cookie.CookieAttributeHandler {
     ctor public BasicDomainHandler();
     method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
     method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
     method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
   }
 
-  public class BasicExpiresHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
+  public deprecated class BasicExpiresHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
     ctor public BasicExpiresHandler(java.lang.String[]);
     method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
   }
 
-  public class BasicMaxAgeHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
+  public deprecated class BasicMaxAgeHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
     ctor public BasicMaxAgeHandler();
     method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
   }
 
-  public class BasicPathHandler implements org.apache.http.cookie.CookieAttributeHandler {
+  public deprecated class BasicPathHandler implements org.apache.http.cookie.CookieAttributeHandler {
     ctor public BasicPathHandler();
     method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
     method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
     method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
   }
 
-  public class BasicSecureHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
+  public deprecated class BasicSecureHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
     ctor public BasicSecureHandler();
     method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
   }
 
-  public class BestMatchSpec implements org.apache.http.cookie.CookieSpec {
+  public deprecated class BestMatchSpec implements org.apache.http.cookie.CookieSpec {
     ctor public BestMatchSpec(java.lang.String[], boolean);
     ctor public BestMatchSpec();
     method public java.util.List<org.apache.http.Header> formatCookies(java.util.List<org.apache.http.cookie.Cookie>);
@@ -56737,12 +56761,12 @@
     method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
   }
 
-  public class BestMatchSpecFactory implements org.apache.http.cookie.CookieSpecFactory {
+  public deprecated class BestMatchSpecFactory implements org.apache.http.cookie.CookieSpecFactory {
     ctor public BestMatchSpecFactory();
     method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
   }
 
-  public class BrowserCompatSpec extends org.apache.http.impl.cookie.CookieSpecBase {
+  public deprecated class BrowserCompatSpec extends org.apache.http.impl.cookie.CookieSpecBase {
     ctor public BrowserCompatSpec(java.lang.String[]);
     ctor public BrowserCompatSpec();
     method public java.util.List<org.apache.http.Header> formatCookies(java.util.List<org.apache.http.cookie.Cookie>);
@@ -56752,12 +56776,12 @@
     field protected static final java.lang.String[] DATE_PATTERNS;
   }
 
-  public class BrowserCompatSpecFactory implements org.apache.http.cookie.CookieSpecFactory {
+  public deprecated class BrowserCompatSpecFactory implements org.apache.http.cookie.CookieSpecFactory {
     ctor public BrowserCompatSpecFactory();
     method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
   }
 
-  public abstract class CookieSpecBase extends org.apache.http.impl.cookie.AbstractCookieSpec {
+  public abstract deprecated class CookieSpecBase extends org.apache.http.impl.cookie.AbstractCookieSpec {
     ctor public CookieSpecBase();
     method protected static java.lang.String getDefaultDomain(org.apache.http.cookie.CookieOrigin);
     method protected static java.lang.String getDefaultPath(org.apache.http.cookie.CookieOrigin);
@@ -56766,12 +56790,12 @@
     method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
   }
 
-  public class DateParseException extends java.lang.Exception {
+  public deprecated class DateParseException extends java.lang.Exception {
     ctor public DateParseException();
     ctor public DateParseException(java.lang.String);
   }
 
-  public final class DateUtils {
+  public final deprecated class DateUtils {
     method public static java.lang.String formatDate(java.util.Date);
     method public static java.lang.String formatDate(java.util.Date, java.lang.String);
     method public static java.util.Date parseDate(java.lang.String) throws org.apache.http.impl.cookie.DateParseException;
@@ -56783,17 +56807,17 @@
     field public static final java.lang.String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
   }
 
-  public class NetscapeDomainHandler extends org.apache.http.impl.cookie.BasicDomainHandler {
+  public deprecated class NetscapeDomainHandler extends org.apache.http.impl.cookie.BasicDomainHandler {
     ctor public NetscapeDomainHandler();
   }
 
-  public class NetscapeDraftHeaderParser {
+  public deprecated class NetscapeDraftHeaderParser {
     ctor public NetscapeDraftHeaderParser();
     method public org.apache.http.HeaderElement parseHeader(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
     field public static final org.apache.http.impl.cookie.NetscapeDraftHeaderParser DEFAULT;
   }
 
-  public class NetscapeDraftSpec extends org.apache.http.impl.cookie.CookieSpecBase {
+  public deprecated class NetscapeDraftSpec extends org.apache.http.impl.cookie.CookieSpecBase {
     ctor public NetscapeDraftSpec(java.lang.String[]);
     ctor public NetscapeDraftSpec();
     method public java.util.List<org.apache.http.Header> formatCookies(java.util.List<org.apache.http.cookie.Cookie>);
@@ -56803,19 +56827,19 @@
     field protected static final java.lang.String EXPIRES_PATTERN = "EEE, dd-MMM-yyyy HH:mm:ss z";
   }
 
-  public class NetscapeDraftSpecFactory implements org.apache.http.cookie.CookieSpecFactory {
+  public deprecated class NetscapeDraftSpecFactory implements org.apache.http.cookie.CookieSpecFactory {
     ctor public NetscapeDraftSpecFactory();
     method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
   }
 
-  public class RFC2109DomainHandler implements org.apache.http.cookie.CookieAttributeHandler {
+  public deprecated class RFC2109DomainHandler implements org.apache.http.cookie.CookieAttributeHandler {
     ctor public RFC2109DomainHandler();
     method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
     method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
     method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
   }
 
-  public class RFC2109Spec extends org.apache.http.impl.cookie.CookieSpecBase {
+  public deprecated class RFC2109Spec extends org.apache.http.impl.cookie.CookieSpecBase {
     ctor public RFC2109Spec(java.lang.String[], boolean);
     ctor public RFC2109Spec();
     method protected void formatCookieAsVer(org.apache.http.util.CharArrayBuffer, org.apache.http.cookie.Cookie, int);
@@ -56826,31 +56850,31 @@
     method public java.util.List<org.apache.http.cookie.Cookie> parse(org.apache.http.Header, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
   }
 
-  public class RFC2109SpecFactory implements org.apache.http.cookie.CookieSpecFactory {
+  public deprecated class RFC2109SpecFactory implements org.apache.http.cookie.CookieSpecFactory {
     ctor public RFC2109SpecFactory();
     method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
   }
 
-  public class RFC2109VersionHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
+  public deprecated class RFC2109VersionHandler extends org.apache.http.impl.cookie.AbstractCookieAttributeHandler {
     ctor public RFC2109VersionHandler();
     method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
   }
 
-  public class RFC2965CommentUrlAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
+  public deprecated class RFC2965CommentUrlAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
     ctor public RFC2965CommentUrlAttributeHandler();
     method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
     method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
     method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
   }
 
-  public class RFC2965DiscardAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
+  public deprecated class RFC2965DiscardAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
     ctor public RFC2965DiscardAttributeHandler();
     method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
     method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
     method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
   }
 
-  public class RFC2965DomainAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
+  public deprecated class RFC2965DomainAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
     ctor public RFC2965DomainAttributeHandler();
     method public boolean domainMatch(java.lang.String, java.lang.String);
     method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
@@ -56858,24 +56882,24 @@
     method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
   }
 
-  public class RFC2965PortAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
+  public deprecated class RFC2965PortAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
     ctor public RFC2965PortAttributeHandler();
     method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
     method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
     method public void validate(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin) throws org.apache.http.cookie.MalformedCookieException;
   }
 
-  public class RFC2965Spec extends org.apache.http.impl.cookie.RFC2109Spec {
+  public deprecated class RFC2965Spec extends org.apache.http.impl.cookie.RFC2109Spec {
     ctor public RFC2965Spec();
     ctor public RFC2965Spec(java.lang.String[], boolean);
   }
 
-  public class RFC2965SpecFactory implements org.apache.http.cookie.CookieSpecFactory {
+  public deprecated class RFC2965SpecFactory implements org.apache.http.cookie.CookieSpecFactory {
     ctor public RFC2965SpecFactory();
     method public org.apache.http.cookie.CookieSpec newInstance(org.apache.http.params.HttpParams);
   }
 
-  public class RFC2965VersionAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
+  public deprecated class RFC2965VersionAttributeHandler implements org.apache.http.cookie.CookieAttributeHandler {
     ctor public RFC2965VersionAttributeHandler();
     method public boolean match(org.apache.http.cookie.Cookie, org.apache.http.cookie.CookieOrigin);
     method public void parse(org.apache.http.cookie.SetCookie, java.lang.String) throws org.apache.http.cookie.MalformedCookieException;
@@ -56886,24 +56910,24 @@
 
 package org.apache.http.impl.entity {
 
-  public class EntityDeserializer {
+  public deprecated class EntityDeserializer {
     ctor public EntityDeserializer(org.apache.http.entity.ContentLengthStrategy);
     method public org.apache.http.HttpEntity deserialize(org.apache.http.io.SessionInputBuffer, org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException;
     method protected org.apache.http.entity.BasicHttpEntity doDeserialize(org.apache.http.io.SessionInputBuffer, org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public class EntitySerializer {
+  public deprecated class EntitySerializer {
     ctor public EntitySerializer(org.apache.http.entity.ContentLengthStrategy);
     method protected java.io.OutputStream doSerialize(org.apache.http.io.SessionOutputBuffer, org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException;
     method public void serialize(org.apache.http.io.SessionOutputBuffer, org.apache.http.HttpMessage, org.apache.http.HttpEntity) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public class LaxContentLengthStrategy implements org.apache.http.entity.ContentLengthStrategy {
+  public deprecated class LaxContentLengthStrategy implements org.apache.http.entity.ContentLengthStrategy {
     ctor public LaxContentLengthStrategy();
     method public long determineLength(org.apache.http.HttpMessage) throws org.apache.http.HttpException;
   }
 
-  public class StrictContentLengthStrategy implements org.apache.http.entity.ContentLengthStrategy {
+  public deprecated class StrictContentLengthStrategy implements org.apache.http.entity.ContentLengthStrategy {
     ctor public StrictContentLengthStrategy();
     method public long determineLength(org.apache.http.HttpMessage) throws org.apache.http.HttpException;
   }
@@ -56912,7 +56936,7 @@
 
 package org.apache.http.impl.io {
 
-  public abstract class AbstractMessageParser implements org.apache.http.io.HttpMessageParser {
+  public abstract deprecated class AbstractMessageParser implements org.apache.http.io.HttpMessageParser {
     ctor public AbstractMessageParser(org.apache.http.io.SessionInputBuffer, org.apache.http.message.LineParser, org.apache.http.params.HttpParams);
     method public org.apache.http.HttpMessage parse() throws org.apache.http.HttpException, java.io.IOException;
     method protected abstract org.apache.http.HttpMessage parseHead(org.apache.http.io.SessionInputBuffer) throws org.apache.http.HttpException, java.io.IOException, org.apache.http.ParseException;
@@ -56920,7 +56944,7 @@
     field protected final org.apache.http.message.LineParser lineParser;
   }
 
-  public abstract class AbstractMessageWriter implements org.apache.http.io.HttpMessageWriter {
+  public abstract deprecated class AbstractMessageWriter implements org.apache.http.io.HttpMessageWriter {
     ctor public AbstractMessageWriter(org.apache.http.io.SessionOutputBuffer, org.apache.http.message.LineFormatter, org.apache.http.params.HttpParams);
     method public void write(org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException;
     method protected abstract void writeHeadLine(org.apache.http.HttpMessage) throws java.io.IOException;
@@ -56929,7 +56953,7 @@
     field protected final org.apache.http.io.SessionOutputBuffer sessionBuffer;
   }
 
-  public abstract class AbstractSessionInputBuffer implements org.apache.http.io.SessionInputBuffer {
+  public abstract deprecated class AbstractSessionInputBuffer implements org.apache.http.io.SessionInputBuffer {
     ctor public AbstractSessionInputBuffer();
     method protected int fillBuffer() throws java.io.IOException;
     method public org.apache.http.io.HttpTransportMetrics getMetrics();
@@ -56942,7 +56966,7 @@
     method public java.lang.String readLine() throws java.io.IOException;
   }
 
-  public abstract class AbstractSessionOutputBuffer implements org.apache.http.io.SessionOutputBuffer {
+  public abstract deprecated class AbstractSessionOutputBuffer implements org.apache.http.io.SessionOutputBuffer {
     ctor public AbstractSessionOutputBuffer();
     method public void flush() throws java.io.IOException;
     method protected void flushBuffer() throws java.io.IOException;
@@ -56955,13 +56979,13 @@
     method public void writeLine(org.apache.http.util.CharArrayBuffer) throws java.io.IOException;
   }
 
-  public class ChunkedInputStream extends java.io.InputStream {
+  public deprecated class ChunkedInputStream extends java.io.InputStream {
     ctor public ChunkedInputStream(org.apache.http.io.SessionInputBuffer);
     method public org.apache.http.Header[] getFooters();
     method public int read() throws java.io.IOException;
   }
 
-  public class ChunkedOutputStream extends java.io.OutputStream {
+  public deprecated class ChunkedOutputStream extends java.io.OutputStream {
     ctor public ChunkedOutputStream(org.apache.http.io.SessionOutputBuffer, int) throws java.io.IOException;
     ctor public ChunkedOutputStream(org.apache.http.io.SessionOutputBuffer) throws java.io.IOException;
     method public void finish() throws java.io.IOException;
@@ -56971,37 +56995,37 @@
     method protected void writeClosingChunk() throws java.io.IOException;
   }
 
-  public class ContentLengthInputStream extends java.io.InputStream {
+  public deprecated class ContentLengthInputStream extends java.io.InputStream {
     ctor public ContentLengthInputStream(org.apache.http.io.SessionInputBuffer, long);
     method public int read() throws java.io.IOException;
   }
 
-  public class ContentLengthOutputStream extends java.io.OutputStream {
+  public deprecated class ContentLengthOutputStream extends java.io.OutputStream {
     ctor public ContentLengthOutputStream(org.apache.http.io.SessionOutputBuffer, long);
     method public void write(int) throws java.io.IOException;
   }
 
-  public class HttpRequestParser extends org.apache.http.impl.io.AbstractMessageParser {
+  public deprecated class HttpRequestParser extends org.apache.http.impl.io.AbstractMessageParser {
     ctor public HttpRequestParser(org.apache.http.io.SessionInputBuffer, org.apache.http.message.LineParser, org.apache.http.HttpRequestFactory, org.apache.http.params.HttpParams);
     method protected org.apache.http.HttpMessage parseHead(org.apache.http.io.SessionInputBuffer) throws org.apache.http.HttpException, java.io.IOException, org.apache.http.ParseException;
   }
 
-  public class HttpRequestWriter extends org.apache.http.impl.io.AbstractMessageWriter {
+  public deprecated class HttpRequestWriter extends org.apache.http.impl.io.AbstractMessageWriter {
     ctor public HttpRequestWriter(org.apache.http.io.SessionOutputBuffer, org.apache.http.message.LineFormatter, org.apache.http.params.HttpParams);
     method protected void writeHeadLine(org.apache.http.HttpMessage) throws java.io.IOException;
   }
 
-  public class HttpResponseParser extends org.apache.http.impl.io.AbstractMessageParser {
+  public deprecated class HttpResponseParser extends org.apache.http.impl.io.AbstractMessageParser {
     ctor public HttpResponseParser(org.apache.http.io.SessionInputBuffer, org.apache.http.message.LineParser, org.apache.http.HttpResponseFactory, org.apache.http.params.HttpParams);
     method protected org.apache.http.HttpMessage parseHead(org.apache.http.io.SessionInputBuffer) throws org.apache.http.HttpException, java.io.IOException, org.apache.http.ParseException;
   }
 
-  public class HttpResponseWriter extends org.apache.http.impl.io.AbstractMessageWriter {
+  public deprecated class HttpResponseWriter extends org.apache.http.impl.io.AbstractMessageWriter {
     ctor public HttpResponseWriter(org.apache.http.io.SessionOutputBuffer, org.apache.http.message.LineFormatter, org.apache.http.params.HttpParams);
     method protected void writeHeadLine(org.apache.http.HttpMessage) throws java.io.IOException;
   }
 
-  public class HttpTransportMetricsImpl implements org.apache.http.io.HttpTransportMetrics {
+  public deprecated class HttpTransportMetricsImpl implements org.apache.http.io.HttpTransportMetrics {
     ctor public HttpTransportMetricsImpl();
     method public long getBytesTransferred();
     method public void incrementBytesTransferred(long);
@@ -57009,22 +57033,22 @@
     method public void setBytesTransferred(long);
   }
 
-  public class IdentityInputStream extends java.io.InputStream {
+  public deprecated class IdentityInputStream extends java.io.InputStream {
     ctor public IdentityInputStream(org.apache.http.io.SessionInputBuffer);
     method public int read() throws java.io.IOException;
   }
 
-  public class IdentityOutputStream extends java.io.OutputStream {
+  public deprecated class IdentityOutputStream extends java.io.OutputStream {
     ctor public IdentityOutputStream(org.apache.http.io.SessionOutputBuffer);
     method public void write(int) throws java.io.IOException;
   }
 
-  public class SocketInputBuffer extends org.apache.http.impl.io.AbstractSessionInputBuffer {
+  public deprecated class SocketInputBuffer extends org.apache.http.impl.io.AbstractSessionInputBuffer {
     ctor public SocketInputBuffer(java.net.Socket, int, org.apache.http.params.HttpParams) throws java.io.IOException;
     method public boolean isDataAvailable(int) throws java.io.IOException;
   }
 
-  public class SocketOutputBuffer extends org.apache.http.impl.io.AbstractSessionOutputBuffer {
+  public deprecated class SocketOutputBuffer extends org.apache.http.impl.io.AbstractSessionOutputBuffer {
     ctor public SocketOutputBuffer(java.net.Socket, int, org.apache.http.params.HttpParams) throws java.io.IOException;
   }
 
@@ -57032,20 +57056,20 @@
 
 package org.apache.http.io {
 
-  public abstract interface HttpMessageParser {
+  public abstract deprecated interface HttpMessageParser {
     method public abstract org.apache.http.HttpMessage parse() throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public abstract interface HttpMessageWriter {
+  public abstract deprecated interface HttpMessageWriter {
     method public abstract void write(org.apache.http.HttpMessage) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public abstract interface HttpTransportMetrics {
+  public abstract deprecated interface HttpTransportMetrics {
     method public abstract long getBytesTransferred();
     method public abstract void reset();
   }
 
-  public abstract interface SessionInputBuffer {
+  public abstract deprecated interface SessionInputBuffer {
     method public abstract org.apache.http.io.HttpTransportMetrics getMetrics();
     method public abstract boolean isDataAvailable(int) throws java.io.IOException;
     method public abstract int read(byte[], int, int) throws java.io.IOException;
@@ -57055,7 +57079,7 @@
     method public abstract java.lang.String readLine() throws java.io.IOException;
   }
 
-  public abstract interface SessionOutputBuffer {
+  public abstract deprecated interface SessionOutputBuffer {
     method public abstract void flush() throws java.io.IOException;
     method public abstract org.apache.http.io.HttpTransportMetrics getMetrics();
     method public abstract void write(byte[], int, int) throws java.io.IOException;
@@ -57069,7 +57093,7 @@
 
 package org.apache.http.message {
 
-  public abstract class AbstractHttpMessage implements org.apache.http.HttpMessage {
+  public abstract deprecated class AbstractHttpMessage implements org.apache.http.HttpMessage {
     ctor protected AbstractHttpMessage(org.apache.http.params.HttpParams);
     ctor protected AbstractHttpMessage();
     method public void addHeader(org.apache.http.Header);
@@ -57092,7 +57116,7 @@
     field protected org.apache.http.params.HttpParams params;
   }
 
-  public class BasicHeader implements java.lang.Cloneable org.apache.http.Header {
+  public deprecated class BasicHeader implements java.lang.Cloneable org.apache.http.Header {
     ctor public BasicHeader(java.lang.String, java.lang.String);
     method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
     method public org.apache.http.HeaderElement[] getElements() throws org.apache.http.ParseException;
@@ -57100,7 +57124,7 @@
     method public java.lang.String getValue();
   }
 
-  public class BasicHeaderElement implements java.lang.Cloneable org.apache.http.HeaderElement {
+  public deprecated class BasicHeaderElement implements java.lang.Cloneable org.apache.http.HeaderElement {
     ctor public BasicHeaderElement(java.lang.String, java.lang.String, org.apache.http.NameValuePair[]);
     ctor public BasicHeaderElement(java.lang.String, java.lang.String);
     method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
@@ -57112,7 +57136,7 @@
     method public java.lang.String getValue();
   }
 
-  public class BasicHeaderElementIterator implements org.apache.http.HeaderElementIterator {
+  public deprecated class BasicHeaderElementIterator implements org.apache.http.HeaderElementIterator {
     ctor public BasicHeaderElementIterator(org.apache.http.HeaderIterator, org.apache.http.message.HeaderValueParser);
     ctor public BasicHeaderElementIterator(org.apache.http.HeaderIterator);
     method public boolean hasNext();
@@ -57121,7 +57145,7 @@
     method public void remove() throws java.lang.UnsupportedOperationException;
   }
 
-  public class BasicHeaderIterator implements org.apache.http.HeaderIterator {
+  public deprecated class BasicHeaderIterator implements org.apache.http.HeaderIterator {
     ctor public BasicHeaderIterator(org.apache.http.Header[], java.lang.String);
     method protected boolean filterHeader(int);
     method protected int findNext(int);
@@ -57134,7 +57158,7 @@
     field protected java.lang.String headerName;
   }
 
-  public class BasicHeaderValueFormatter implements org.apache.http.message.HeaderValueFormatter {
+  public deprecated class BasicHeaderValueFormatter implements org.apache.http.message.HeaderValueFormatter {
     ctor public BasicHeaderValueFormatter();
     method protected void doFormatValue(org.apache.http.util.CharArrayBuffer, java.lang.String, boolean);
     method protected int estimateElementsLen(org.apache.http.HeaderElement[]);
@@ -57156,7 +57180,7 @@
     field public static final java.lang.String UNSAFE_CHARS = "\"\\";
   }
 
-  public class BasicHeaderValueParser implements org.apache.http.message.HeaderValueParser {
+  public deprecated class BasicHeaderValueParser implements org.apache.http.message.HeaderValueParser {
     ctor public BasicHeaderValueParser();
     method protected org.apache.http.HeaderElement createHeaderElement(java.lang.String, java.lang.String, org.apache.http.NameValuePair[]);
     method protected org.apache.http.NameValuePair createNameValuePair(java.lang.String, java.lang.String);
@@ -57172,7 +57196,7 @@
     field public static final org.apache.http.message.BasicHeaderValueParser DEFAULT;
   }
 
-  public class BasicHttpEntityEnclosingRequest extends org.apache.http.message.BasicHttpRequest implements org.apache.http.HttpEntityEnclosingRequest {
+  public deprecated class BasicHttpEntityEnclosingRequest extends org.apache.http.message.BasicHttpRequest implements org.apache.http.HttpEntityEnclosingRequest {
     ctor public BasicHttpEntityEnclosingRequest(java.lang.String, java.lang.String);
     ctor public BasicHttpEntityEnclosingRequest(java.lang.String, java.lang.String, org.apache.http.ProtocolVersion);
     ctor public BasicHttpEntityEnclosingRequest(org.apache.http.RequestLine);
@@ -57181,7 +57205,7 @@
     method public void setEntity(org.apache.http.HttpEntity);
   }
 
-  public class BasicHttpRequest extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.HttpRequest {
+  public deprecated class BasicHttpRequest extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.HttpRequest {
     ctor public BasicHttpRequest(java.lang.String, java.lang.String);
     ctor public BasicHttpRequest(java.lang.String, java.lang.String, org.apache.http.ProtocolVersion);
     ctor public BasicHttpRequest(org.apache.http.RequestLine);
@@ -57189,7 +57213,7 @@
     method public org.apache.http.RequestLine getRequestLine();
   }
 
-  public class BasicHttpResponse extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.HttpResponse {
+  public deprecated class BasicHttpResponse extends org.apache.http.message.AbstractHttpMessage implements org.apache.http.HttpResponse {
     ctor public BasicHttpResponse(org.apache.http.StatusLine, org.apache.http.ReasonPhraseCatalog, java.util.Locale);
     ctor public BasicHttpResponse(org.apache.http.StatusLine);
     ctor public BasicHttpResponse(org.apache.http.ProtocolVersion, int, java.lang.String);
@@ -57207,7 +57231,7 @@
     method public void setStatusLine(org.apache.http.ProtocolVersion, int, java.lang.String);
   }
 
-  public class BasicLineFormatter implements org.apache.http.message.LineFormatter {
+  public deprecated class BasicLineFormatter implements org.apache.http.message.LineFormatter {
     ctor public BasicLineFormatter();
     method public org.apache.http.util.CharArrayBuffer appendProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.ProtocolVersion);
     method protected void doFormatHeader(org.apache.http.util.CharArrayBuffer, org.apache.http.Header);
@@ -57225,7 +57249,7 @@
     field public static final org.apache.http.message.BasicLineFormatter DEFAULT;
   }
 
-  public class BasicLineParser implements org.apache.http.message.LineParser {
+  public deprecated class BasicLineParser implements org.apache.http.message.LineParser {
     ctor public BasicLineParser(org.apache.http.ProtocolVersion);
     ctor public BasicLineParser();
     method protected org.apache.http.ProtocolVersion createProtocolVersion(int, int);
@@ -57245,7 +57269,7 @@
     field protected final org.apache.http.ProtocolVersion protocol;
   }
 
-  public class BasicListHeaderIterator implements org.apache.http.HeaderIterator {
+  public deprecated class BasicListHeaderIterator implements org.apache.http.HeaderIterator {
     ctor public BasicListHeaderIterator(java.util.List, java.lang.String);
     method protected boolean filterHeader(int);
     method protected int findNext(int);
@@ -57259,14 +57283,14 @@
     field protected int lastIndex;
   }
 
-  public class BasicNameValuePair implements java.lang.Cloneable org.apache.http.NameValuePair {
+  public deprecated class BasicNameValuePair implements java.lang.Cloneable org.apache.http.NameValuePair {
     ctor public BasicNameValuePair(java.lang.String, java.lang.String);
     method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
     method public java.lang.String getName();
     method public java.lang.String getValue();
   }
 
-  public class BasicRequestLine implements java.lang.Cloneable org.apache.http.RequestLine {
+  public deprecated class BasicRequestLine implements java.lang.Cloneable org.apache.http.RequestLine {
     ctor public BasicRequestLine(java.lang.String, java.lang.String, org.apache.http.ProtocolVersion);
     method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
     method public java.lang.String getMethod();
@@ -57274,7 +57298,7 @@
     method public java.lang.String getUri();
   }
 
-  public class BasicStatusLine implements java.lang.Cloneable org.apache.http.StatusLine {
+  public deprecated class BasicStatusLine implements java.lang.Cloneable org.apache.http.StatusLine {
     ctor public BasicStatusLine(org.apache.http.ProtocolVersion, int, java.lang.String);
     method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
     method public org.apache.http.ProtocolVersion getProtocolVersion();
@@ -57282,7 +57306,7 @@
     method public int getStatusCode();
   }
 
-  public class BasicTokenIterator implements org.apache.http.TokenIterator {
+  public deprecated class BasicTokenIterator implements org.apache.http.TokenIterator {
     ctor public BasicTokenIterator(org.apache.http.HeaderIterator);
     method protected java.lang.String createToken(java.lang.String, int, int);
     method protected int findNext(int) throws org.apache.http.ParseException;
@@ -57304,7 +57328,7 @@
     field protected int searchPos;
   }
 
-  public class BufferedHeader implements java.lang.Cloneable org.apache.http.FormattedHeader {
+  public deprecated class BufferedHeader implements java.lang.Cloneable org.apache.http.FormattedHeader {
     ctor public BufferedHeader(org.apache.http.util.CharArrayBuffer) throws org.apache.http.ParseException;
     method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
     method public org.apache.http.util.CharArrayBuffer getBuffer();
@@ -57314,7 +57338,7 @@
     method public int getValuePos();
   }
 
-  public class HeaderGroup implements java.lang.Cloneable {
+  public deprecated class HeaderGroup implements java.lang.Cloneable {
     ctor public HeaderGroup();
     method public void addHeader(org.apache.http.Header);
     method public void clear();
@@ -57333,28 +57357,28 @@
     method public void updateHeader(org.apache.http.Header);
   }
 
-  public abstract interface HeaderValueFormatter {
+  public abstract deprecated interface HeaderValueFormatter {
     method public abstract org.apache.http.util.CharArrayBuffer formatElements(org.apache.http.util.CharArrayBuffer, org.apache.http.HeaderElement[], boolean);
     method public abstract org.apache.http.util.CharArrayBuffer formatHeaderElement(org.apache.http.util.CharArrayBuffer, org.apache.http.HeaderElement, boolean);
     method public abstract org.apache.http.util.CharArrayBuffer formatNameValuePair(org.apache.http.util.CharArrayBuffer, org.apache.http.NameValuePair, boolean);
     method public abstract org.apache.http.util.CharArrayBuffer formatParameters(org.apache.http.util.CharArrayBuffer, org.apache.http.NameValuePair[], boolean);
   }
 
-  public abstract interface HeaderValueParser {
+  public abstract deprecated interface HeaderValueParser {
     method public abstract org.apache.http.HeaderElement[] parseElements(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
     method public abstract org.apache.http.HeaderElement parseHeaderElement(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
     method public abstract org.apache.http.NameValuePair parseNameValuePair(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
     method public abstract org.apache.http.NameValuePair[] parseParameters(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
   }
 
-  public abstract interface LineFormatter {
+  public abstract deprecated interface LineFormatter {
     method public abstract org.apache.http.util.CharArrayBuffer appendProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.ProtocolVersion);
     method public abstract org.apache.http.util.CharArrayBuffer formatHeader(org.apache.http.util.CharArrayBuffer, org.apache.http.Header);
     method public abstract org.apache.http.util.CharArrayBuffer formatRequestLine(org.apache.http.util.CharArrayBuffer, org.apache.http.RequestLine);
     method public abstract org.apache.http.util.CharArrayBuffer formatStatusLine(org.apache.http.util.CharArrayBuffer, org.apache.http.StatusLine);
   }
 
-  public abstract interface LineParser {
+  public abstract deprecated interface LineParser {
     method public abstract boolean hasProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor);
     method public abstract org.apache.http.Header parseHeader(org.apache.http.util.CharArrayBuffer) throws org.apache.http.ParseException;
     method public abstract org.apache.http.ProtocolVersion parseProtocolVersion(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
@@ -57362,7 +57386,7 @@
     method public abstract org.apache.http.StatusLine parseStatusLine(org.apache.http.util.CharArrayBuffer, org.apache.http.message.ParserCursor) throws org.apache.http.ParseException;
   }
 
-  public class ParserCursor {
+  public deprecated class ParserCursor {
     ctor public ParserCursor(int, int);
     method public boolean atEnd();
     method public int getLowerBound();
@@ -57375,7 +57399,7 @@
 
 package org.apache.http.params {
 
-  public abstract class AbstractHttpParams implements org.apache.http.params.HttpParams {
+  public abstract deprecated class AbstractHttpParams implements org.apache.http.params.HttpParams {
     ctor protected AbstractHttpParams();
     method public boolean getBooleanParameter(java.lang.String, boolean);
     method public double getDoubleParameter(java.lang.String, double);
@@ -57389,7 +57413,7 @@
     method public org.apache.http.params.HttpParams setLongParameter(java.lang.String, long);
   }
 
-  public final class BasicHttpParams extends org.apache.http.params.AbstractHttpParams implements java.lang.Cloneable java.io.Serializable {
+  public final deprecated class BasicHttpParams extends org.apache.http.params.AbstractHttpParams implements java.lang.Cloneable java.io.Serializable {
     ctor public BasicHttpParams();
     method public void clear();
     method public java.lang.Object clone() throws java.lang.CloneNotSupportedException;
@@ -57403,7 +57427,7 @@
     method public void setParameters(java.lang.String[], java.lang.Object);
   }
 
-  public abstract interface CoreConnectionPNames {
+  public abstract deprecated interface CoreConnectionPNames {
     field public static final java.lang.String CONNECTION_TIMEOUT = "http.connection.timeout";
     field public static final java.lang.String MAX_HEADER_COUNT = "http.connection.max-header-count";
     field public static final java.lang.String MAX_LINE_LENGTH = "http.connection.max-line-length";
@@ -57414,7 +57438,7 @@
     field public static final java.lang.String TCP_NODELAY = "http.tcp.nodelay";
   }
 
-  public abstract interface CoreProtocolPNames {
+  public abstract deprecated interface CoreProtocolPNames {
     field public static final java.lang.String HTTP_CONTENT_CHARSET = "http.protocol.content-charset";
     field public static final java.lang.String HTTP_ELEMENT_CHARSET = "http.protocol.element-charset";
     field public static final java.lang.String ORIGIN_SERVER = "http.origin-server";
@@ -57425,7 +57449,7 @@
     field public static final java.lang.String WAIT_FOR_CONTINUE = "http.protocol.wait-for-continue";
   }
 
-  public final class DefaultedHttpParams extends org.apache.http.params.AbstractHttpParams {
+  public final deprecated class DefaultedHttpParams extends org.apache.http.params.AbstractHttpParams {
     ctor public DefaultedHttpParams(org.apache.http.params.HttpParams, org.apache.http.params.HttpParams);
     method public org.apache.http.params.HttpParams copy();
     method public org.apache.http.params.HttpParams getDefaults();
@@ -57434,12 +57458,12 @@
     method public org.apache.http.params.HttpParams setParameter(java.lang.String, java.lang.Object);
   }
 
-  public abstract class HttpAbstractParamBean {
+  public abstract deprecated class HttpAbstractParamBean {
     ctor public HttpAbstractParamBean(org.apache.http.params.HttpParams);
     field protected final org.apache.http.params.HttpParams params;
   }
 
-  public class HttpConnectionParamBean extends org.apache.http.params.HttpAbstractParamBean {
+  public deprecated class HttpConnectionParamBean extends org.apache.http.params.HttpAbstractParamBean {
     ctor public HttpConnectionParamBean(org.apache.http.params.HttpParams);
     method public void setConnectionTimeout(int);
     method public void setLinger(int);
@@ -57449,7 +57473,7 @@
     method public void setTcpNoDelay(boolean);
   }
 
-  public final class HttpConnectionParams implements org.apache.http.params.CoreConnectionPNames {
+  public final deprecated class HttpConnectionParams implements org.apache.http.params.CoreConnectionPNames {
     method public static int getConnectionTimeout(org.apache.http.params.HttpParams);
     method public static int getLinger(org.apache.http.params.HttpParams);
     method public static int getSoTimeout(org.apache.http.params.HttpParams);
@@ -57464,7 +57488,7 @@
     method public static void setTcpNoDelay(org.apache.http.params.HttpParams, boolean);
   }
 
-  public abstract interface HttpParams {
+  public abstract deprecated interface HttpParams {
     method public abstract org.apache.http.params.HttpParams copy();
     method public abstract boolean getBooleanParameter(java.lang.String, boolean);
     method public abstract double getDoubleParameter(java.lang.String, double);
@@ -57481,7 +57505,7 @@
     method public abstract org.apache.http.params.HttpParams setParameter(java.lang.String, java.lang.Object);
   }
 
-  public class HttpProtocolParamBean extends org.apache.http.params.HttpAbstractParamBean {
+  public deprecated class HttpProtocolParamBean extends org.apache.http.params.HttpAbstractParamBean {
     ctor public HttpProtocolParamBean(org.apache.http.params.HttpParams);
     method public void setContentCharset(java.lang.String);
     method public void setHttpElementCharset(java.lang.String);
@@ -57490,7 +57514,7 @@
     method public void setVersion(org.apache.http.HttpVersion);
   }
 
-  public final class HttpProtocolParams implements org.apache.http.params.CoreProtocolPNames {
+  public final deprecated class HttpProtocolParams implements org.apache.http.params.CoreProtocolPNames {
     method public static java.lang.String getContentCharset(org.apache.http.params.HttpParams);
     method public static java.lang.String getHttpElementCharset(org.apache.http.params.HttpParams);
     method public static java.lang.String getUserAgent(org.apache.http.params.HttpParams);
@@ -57507,7 +57531,7 @@
 
 package org.apache.http.protocol {
 
-  public class BasicHttpContext implements org.apache.http.protocol.HttpContext {
+  public deprecated class BasicHttpContext implements org.apache.http.protocol.HttpContext {
     ctor public BasicHttpContext();
     ctor public BasicHttpContext(org.apache.http.protocol.HttpContext);
     method public java.lang.Object getAttribute(java.lang.String);
@@ -57515,7 +57539,7 @@
     method public void setAttribute(java.lang.String, java.lang.Object);
   }
 
-  public final class BasicHttpProcessor implements java.lang.Cloneable org.apache.http.protocol.HttpProcessor org.apache.http.protocol.HttpRequestInterceptorList org.apache.http.protocol.HttpResponseInterceptorList {
+  public final deprecated class BasicHttpProcessor implements java.lang.Cloneable org.apache.http.protocol.HttpProcessor org.apache.http.protocol.HttpRequestInterceptorList org.apache.http.protocol.HttpResponseInterceptorList {
     ctor public BasicHttpProcessor();
     method public final void addInterceptor(org.apache.http.HttpRequestInterceptor);
     method public final void addInterceptor(org.apache.http.HttpRequestInterceptor, int);
@@ -57544,7 +57568,7 @@
     field protected java.util.List responseInterceptors;
   }
 
-  public final class DefaultedHttpContext implements org.apache.http.protocol.HttpContext {
+  public final deprecated class DefaultedHttpContext implements org.apache.http.protocol.HttpContext {
     ctor public DefaultedHttpContext(org.apache.http.protocol.HttpContext, org.apache.http.protocol.HttpContext);
     method public java.lang.Object getAttribute(java.lang.String);
     method public org.apache.http.protocol.HttpContext getDefaults();
@@ -57552,7 +57576,7 @@
     method public void setAttribute(java.lang.String, java.lang.Object);
   }
 
-  public abstract interface ExecutionContext {
+  public abstract deprecated interface ExecutionContext {
     field public static final java.lang.String HTTP_CONNECTION = "http.connection";
     field public static final java.lang.String HTTP_PROXY_HOST = "http.proxy_host";
     field public static final java.lang.String HTTP_REQUEST = "http.request";
@@ -57561,7 +57585,7 @@
     field public static final java.lang.String HTTP_TARGET_HOST = "http.target_host";
   }
 
-  public final class HTTP {
+  public final deprecated class HTTP {
     method public static boolean isWhitespace(char);
     field public static final java.lang.String ASCII = "ASCII";
     field public static final java.lang.String CHARSET_PARAM = "; charset=";
@@ -57595,28 +57619,28 @@
     field public static final java.lang.String UTF_8 = "UTF-8";
   }
 
-  public abstract interface HttpContext {
+  public abstract deprecated interface HttpContext {
     method public abstract java.lang.Object getAttribute(java.lang.String);
     method public abstract java.lang.Object removeAttribute(java.lang.String);
     method public abstract void setAttribute(java.lang.String, java.lang.Object);
     field public static final java.lang.String RESERVED_PREFIX = "http.";
   }
 
-  public class HttpDateGenerator {
+  public deprecated class HttpDateGenerator {
     ctor public HttpDateGenerator();
     method public synchronized java.lang.String getCurrentDate();
     field public static final java.util.TimeZone GMT;
     field public static final java.lang.String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
   }
 
-  public abstract interface HttpExpectationVerifier {
+  public abstract deprecated interface HttpExpectationVerifier {
     method public abstract void verify(org.apache.http.HttpRequest, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException;
   }
 
-  public abstract interface HttpProcessor implements org.apache.http.HttpRequestInterceptor org.apache.http.HttpResponseInterceptor {
+  public abstract deprecated interface HttpProcessor implements org.apache.http.HttpRequestInterceptor org.apache.http.HttpResponseInterceptor {
   }
 
-  public class HttpRequestExecutor {
+  public deprecated class HttpRequestExecutor {
     ctor public HttpRequestExecutor();
     method protected boolean canResponseHaveBody(org.apache.http.HttpRequest, org.apache.http.HttpResponse);
     method protected org.apache.http.HttpResponse doReceiveResponse(org.apache.http.HttpRequest, org.apache.http.HttpClientConnection, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
@@ -57626,11 +57650,11 @@
     method public void preProcess(org.apache.http.HttpRequest, org.apache.http.protocol.HttpProcessor, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public abstract interface HttpRequestHandler {
+  public abstract deprecated interface HttpRequestHandler {
     method public abstract void handle(org.apache.http.HttpRequest, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public class HttpRequestHandlerRegistry implements org.apache.http.protocol.HttpRequestHandlerResolver {
+  public deprecated class HttpRequestHandlerRegistry implements org.apache.http.protocol.HttpRequestHandlerResolver {
     ctor public HttpRequestHandlerRegistry();
     method public org.apache.http.protocol.HttpRequestHandler lookup(java.lang.String);
     method protected deprecated boolean matchUriRequestPattern(java.lang.String, java.lang.String);
@@ -57639,11 +57663,11 @@
     method public void unregister(java.lang.String);
   }
 
-  public abstract interface HttpRequestHandlerResolver {
+  public abstract deprecated interface HttpRequestHandlerResolver {
     method public abstract org.apache.http.protocol.HttpRequestHandler lookup(java.lang.String);
   }
 
-  public abstract interface HttpRequestInterceptorList {
+  public abstract deprecated interface HttpRequestInterceptorList {
     method public abstract void addRequestInterceptor(org.apache.http.HttpRequestInterceptor);
     method public abstract void addRequestInterceptor(org.apache.http.HttpRequestInterceptor, int);
     method public abstract void clearRequestInterceptors();
@@ -57653,7 +57677,7 @@
     method public abstract void setInterceptors(java.util.List);
   }
 
-  public abstract interface HttpResponseInterceptorList {
+  public abstract deprecated interface HttpResponseInterceptorList {
     method public abstract void addResponseInterceptor(org.apache.http.HttpResponseInterceptor);
     method public abstract void addResponseInterceptor(org.apache.http.HttpResponseInterceptor, int);
     method public abstract void clearResponseInterceptors();
@@ -57663,7 +57687,7 @@
     method public abstract void setInterceptors(java.util.List);
   }
 
-  public class HttpService {
+  public deprecated class HttpService {
     ctor public HttpService(org.apache.http.protocol.HttpProcessor, org.apache.http.ConnectionReuseStrategy, org.apache.http.HttpResponseFactory);
     method protected void doService(org.apache.http.HttpRequest, org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
     method public org.apache.http.params.HttpParams getParams();
@@ -57677,61 +57701,61 @@
     method public void setResponseFactory(org.apache.http.HttpResponseFactory);
   }
 
-  public class RequestConnControl implements org.apache.http.HttpRequestInterceptor {
+  public deprecated class RequestConnControl implements org.apache.http.HttpRequestInterceptor {
     ctor public RequestConnControl();
     method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public class RequestContent implements org.apache.http.HttpRequestInterceptor {
+  public deprecated class RequestContent implements org.apache.http.HttpRequestInterceptor {
     ctor public RequestContent();
     method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public class RequestDate implements org.apache.http.HttpRequestInterceptor {
+  public deprecated class RequestDate implements org.apache.http.HttpRequestInterceptor {
     ctor public RequestDate();
     method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public class RequestExpectContinue implements org.apache.http.HttpRequestInterceptor {
+  public deprecated class RequestExpectContinue implements org.apache.http.HttpRequestInterceptor {
     ctor public RequestExpectContinue();
     method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public class RequestTargetHost implements org.apache.http.HttpRequestInterceptor {
+  public deprecated class RequestTargetHost implements org.apache.http.HttpRequestInterceptor {
     ctor public RequestTargetHost();
     method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public class RequestUserAgent implements org.apache.http.HttpRequestInterceptor {
+  public deprecated class RequestUserAgent implements org.apache.http.HttpRequestInterceptor {
     ctor public RequestUserAgent();
     method public void process(org.apache.http.HttpRequest, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public class ResponseConnControl implements org.apache.http.HttpResponseInterceptor {
+  public deprecated class ResponseConnControl implements org.apache.http.HttpResponseInterceptor {
     ctor public ResponseConnControl();
     method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public class ResponseContent implements org.apache.http.HttpResponseInterceptor {
+  public deprecated class ResponseContent implements org.apache.http.HttpResponseInterceptor {
     ctor public ResponseContent();
     method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public class ResponseDate implements org.apache.http.HttpResponseInterceptor {
+  public deprecated class ResponseDate implements org.apache.http.HttpResponseInterceptor {
     ctor public ResponseDate();
     method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public class ResponseServer implements org.apache.http.HttpResponseInterceptor {
+  public deprecated class ResponseServer implements org.apache.http.HttpResponseInterceptor {
     ctor public ResponseServer();
     method public void process(org.apache.http.HttpResponse, org.apache.http.protocol.HttpContext) throws org.apache.http.HttpException, java.io.IOException;
   }
 
-  public class SyncBasicHttpContext extends org.apache.http.protocol.BasicHttpContext {
+  public deprecated class SyncBasicHttpContext extends org.apache.http.protocol.BasicHttpContext {
     ctor public SyncBasicHttpContext(org.apache.http.protocol.HttpContext);
   }
 
-  public class UriPatternMatcher {
+  public deprecated class UriPatternMatcher {
     ctor public UriPatternMatcher();
     method public java.lang.Object lookup(java.lang.String);
     method protected boolean matchUriRequestPattern(java.lang.String, java.lang.String);
@@ -57744,7 +57768,7 @@
 
 package org.apache.http.util {
 
-  public final class ByteArrayBuffer {
+  public final deprecated class ByteArrayBuffer {
     ctor public ByteArrayBuffer(int);
     method public void append(byte[], int, int);
     method public void append(int);
@@ -57761,7 +57785,7 @@
     method public byte[] toByteArray();
   }
 
-  public final class CharArrayBuffer {
+  public final deprecated class CharArrayBuffer {
     ctor public CharArrayBuffer(int);
     method public void append(char[], int, int);
     method public void append(java.lang.String);
@@ -57787,7 +57811,7 @@
     method public char[] toCharArray();
   }
 
-  public final class EncodingUtils {
+  public final deprecated class EncodingUtils {
     method public static byte[] getAsciiBytes(java.lang.String);
     method public static java.lang.String getAsciiString(byte[], int, int);
     method public static java.lang.String getAsciiString(byte[]);
@@ -57796,18 +57820,18 @@
     method public static java.lang.String getString(byte[], java.lang.String);
   }
 
-  public final class EntityUtils {
+  public final deprecated class EntityUtils {
     method public static java.lang.String getContentCharSet(org.apache.http.HttpEntity) throws org.apache.http.ParseException;
     method public static byte[] toByteArray(org.apache.http.HttpEntity) throws java.io.IOException;
     method public static java.lang.String toString(org.apache.http.HttpEntity, java.lang.String) throws java.io.IOException, org.apache.http.ParseException;
     method public static java.lang.String toString(org.apache.http.HttpEntity) throws java.io.IOException, org.apache.http.ParseException;
   }
 
-  public final class ExceptionUtils {
+  public final deprecated class ExceptionUtils {
     method public static void initCause(java.lang.Throwable, java.lang.Throwable);
   }
 
-  public final class LangUtils {
+  public final deprecated class LangUtils {
     method public static boolean equals(java.lang.Object, java.lang.Object);
     method public static boolean equals(java.lang.Object[], java.lang.Object[]);
     method public static int hashCode(int, int);
@@ -57817,7 +57841,7 @@
     field public static final int HASH_SEED = 17; // 0x11
   }
 
-  public class VersionInfo {
+  public deprecated class VersionInfo {
     ctor protected VersionInfo(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String);
     method protected static final org.apache.http.util.VersionInfo fromMap(java.lang.String, java.util.Map, java.lang.ClassLoader);
     method public final java.lang.String getClassloader();
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 13ceb4a..1e1b33f 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -24,13 +24,18 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.util.Log;
+import android.view.Display;
 import android.view.KeyEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityInteractionClient;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityWindowInfo;
 
 import com.android.internal.os.HandlerCaller;
+import com.android.internal.os.SomeArgs;
 
 import java.util.List;
 
@@ -366,7 +371,7 @@
         public void onAccessibilityEvent(AccessibilityEvent event);
         public void onInterrupt();
         public void onServiceConnected();
-        public void onSetConnectionId(int connectionId);
+        public void init(int connectionId, IBinder windowToken);
         public boolean onGesture(int gestureId);
         public boolean onKeyEvent(KeyEvent event);
     }
@@ -375,6 +380,10 @@
 
     private AccessibilityServiceInfo mInfo;
 
+    private IBinder mWindowToken;
+
+    private WindowManager mWindowManager;
+
     /**
      * Callback for {@link android.view.accessibility.AccessibilityEvent}s.
      *
@@ -611,6 +620,18 @@
         }
     }
 
+    @Override
+    public Object getSystemService(String name) {
+        if (Context.WINDOW_SERVICE.equals(name)) {
+            if (mWindowManager == null) {
+                WindowManager wrapped = (WindowManager) super.getSystemService(name);
+                mWindowManager = new LocalWindowManager(wrapped);
+            }
+            return mWindowManager;
+        }
+        return super.getSystemService(name);
+    }
+
     /**
      * Implement to return the implementation of the internal accessibility
      * service interface.
@@ -634,8 +655,9 @@
             }
 
             @Override
-            public void onSetConnectionId( int connectionId) {
+            public void init(int connectionId, IBinder windowToken) {
                 mConnectionId = connectionId;
+                mWindowToken = windowToken;
             }
 
             @Override
@@ -658,7 +680,7 @@
      */
     public static class IAccessibilityServiceClientWrapper extends IAccessibilityServiceClient.Stub
             implements HandlerCaller.Callback {
-        private static final int DO_SET_SET_CONNECTION = 1;
+        private static final int DO_INIT = 1;
         private static final int DO_ON_INTERRUPT = 2;
         private static final int DO_ON_ACCESSIBILITY_EVENT = 3;
         private static final int DO_ON_GESTURE = 4;
@@ -677,9 +699,10 @@
             mCaller = new HandlerCaller(context, looper, this, true /*asyncHandler*/);
         }
 
-        public void setConnection(IAccessibilityServiceConnection connection, int connectionId) {
-            Message message = mCaller.obtainMessageIO(DO_SET_SET_CONNECTION, connectionId,
-                    connection);
+        public void init(IAccessibilityServiceConnection connection, int connectionId,
+                IBinder windowToken) {
+            Message message = mCaller.obtainMessageIOO(DO_INIT, connectionId,
+                    connection, windowToken);
             mCaller.sendMessage(message);
         }
 
@@ -730,20 +753,24 @@
                     mCallback.onInterrupt();
                 } return;
 
-                case DO_SET_SET_CONNECTION: {
+                case DO_INIT: {
                     mConnectionId = message.arg1;
+                    SomeArgs args = (SomeArgs) message.obj;
                     IAccessibilityServiceConnection connection =
-                        (IAccessibilityServiceConnection) message.obj;
+                            (IAccessibilityServiceConnection) args.arg1;
+                    IBinder windowToken = (IBinder) args.arg2;
+                    args.recycle();
                     if (connection != null) {
                         AccessibilityInteractionClient.getInstance().addConnection(mConnectionId,
                                 connection);
-                        mCallback.onSetConnectionId(mConnectionId);
+                        mCallback.init(mConnectionId, windowToken);
                         mCallback.onServiceConnected();
                     } else {
                         AccessibilityInteractionClient.getInstance().removeConnection(
                                 mConnectionId);
+                        mConnectionId = AccessibilityInteractionClient.NO_ID;
                         AccessibilityInteractionClient.getInstance().clearCache();
-                        mCallback.onSetConnectionId(AccessibilityInteractionClient.NO_ID);
+                        mCallback.init(AccessibilityInteractionClient.NO_ID, null);
                     }
                 } return;
 
@@ -785,4 +812,53 @@
             }
         }
     }
+
+    private class LocalWindowManager implements WindowManager {
+        private final WindowManager mImpl;
+
+        private LocalWindowManager(WindowManager impl) {
+            mImpl = impl;
+        }
+
+        @Override
+        public Display getDefaultDisplay() {
+            return mImpl.getDefaultDisplay();
+        }
+
+        @Override
+        public void addView(View view, ViewGroup.LayoutParams params) {
+            if (!(params instanceof WindowManager.LayoutParams)) {
+                throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
+            }
+            WindowManager.LayoutParams windowParams = (WindowManager.LayoutParams) params;
+            if (windowParams.type == LayoutParams.TYPE_ACCESSIBILITY_OVERLAY
+                    && windowParams.token == null) {
+                windowParams.token = mWindowToken;
+            }
+            mImpl.addView(view, params);
+        }
+
+        @Override
+        public void updateViewLayout(View view, ViewGroup.LayoutParams params) {
+            if (!(params instanceof WindowManager.LayoutParams)) {
+                throw new IllegalArgumentException("Params must be WindowManager.LayoutParams");
+            }
+            WindowManager.LayoutParams windowParams = (WindowManager.LayoutParams) params;
+            if (windowParams.type == LayoutParams.TYPE_ACCESSIBILITY_OVERLAY
+                    && windowParams.token == null) {
+                windowParams.token = mWindowToken;
+            }
+            mImpl.updateViewLayout(view, params);
+        }
+
+        @Override
+        public void removeViewImmediate(View view) {
+            mImpl.removeViewImmediate(view);
+        }
+
+        @Override
+        public void removeView(View view) {
+            mImpl.removeView(view);
+        }
+    }
 }
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
index 6ce0219..8b503dd 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl
@@ -28,7 +28,7 @@
  */
  oneway interface IAccessibilityServiceClient {
 
-    void setConnection(in IAccessibilityServiceConnection connection, int connectionId);
+    void init(in IAccessibilityServiceConnection connection, int connectionId, IBinder windowToken);
 
     void onAccessibilityEvent(in AccessibilityEvent event);
 
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index 3720c81..da48709 100644
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -16,6 +16,8 @@
 
 package android.animation;
 
+import android.content.res.ConstantState;
+
 import java.util.ArrayList;
 
 /**
@@ -41,6 +43,18 @@
     boolean mPaused = false;
 
     /**
+     * A set of flags which identify the type of configuration changes that can affect this
+     * Animator. Used by the Animator cache.
+     */
+    int mChangingConfigurations = 0;
+
+    /**
+     * If this animator is inflated from a constant state, keep a reference to it so that
+     * ConstantState will not be garbage collected until this animator is collected
+     */
+    private AnimatorConstantState mConstantState;
+
+    /**
      * Starts this animation. If the animation has a nonzero startDelay, the animation will start
      * running after that delay elapses. A non-delayed animation will have its initial
      * value(s) set immediately, followed by calls to
@@ -295,25 +309,71 @@
         }
     }
 
+    /**
+     * Return a mask of the configuration parameters for which this animator may change, requiring
+     * that it should be re-created from Resources. The default implementation returns whatever
+     * value was provided through setChangingConfigurations(int) or 0 by default.
+     *
+     * @return Returns a mask of the changing configuration parameters, as defined by
+     * {@link android.content.pm.ActivityInfo}.
+     * @see android.content.pm.ActivityInfo
+     * @hide
+     */
+    public int getChangingConfigurations() {
+        return mChangingConfigurations;
+    }
+
+    /**
+     * Set a mask of the configuration parameters for which this animator may change, requiring
+     * that it be re-created from resource.
+     *
+     * @param configs A mask of the changing configuration parameters, as
+     * defined by {@link android.content.pm.ActivityInfo}.
+     *
+     * @see android.content.pm.ActivityInfo
+     * @hide
+     */
+    public void setChangingConfigurations(int configs) {
+        mChangingConfigurations = configs;
+    }
+
+    /**
+     * Sets the changing configurations value to the union of the current changing configurations
+     * and the provided configs.
+     * This method is called while loading the animator.
+     * @hide
+     */
+    public void appendChangingConfigurations(int configs) {
+        mChangingConfigurations |= configs;
+    }
+
+    /**
+     * Return a {@link android.content.res.ConstantState} instance that holds the shared state of
+     * this Animator.
+     * <p>
+     * This constant state is used to create new instances of this animator when needed, instead
+     * of re-loading it from resources. Default implementation creates a new
+     * {@link AnimatorConstantState}. You can override this method to provide your custom logic or
+     * return null if you don't want this animator to be cached.
+     *
+     * @return The ConfigurationBoundResourceCache.BaseConstantState associated to this Animator.
+     * @see android.content.res.ConstantState
+     * @see #clone()
+     * @hide
+     */
+    public ConstantState<Animator> createConstantState() {
+        return new AnimatorConstantState(this);
+    }
+
     @Override
     public Animator clone() {
         try {
             final Animator anim = (Animator) super.clone();
             if (mListeners != null) {
-                ArrayList<AnimatorListener> oldListeners = mListeners;
-                anim.mListeners = new ArrayList<AnimatorListener>();
-                int numListeners = oldListeners.size();
-                for (int i = 0; i < numListeners; ++i) {
-                    anim.mListeners.add(oldListeners.get(i));
-                }
+                anim.mListeners = new ArrayList<AnimatorListener>(mListeners);
             }
             if (mPauseListeners != null) {
-                ArrayList<AnimatorPauseListener> oldListeners = mPauseListeners;
-                anim.mPauseListeners = new ArrayList<AnimatorPauseListener>();
-                int numListeners = oldListeners.size();
-                for (int i = 0; i < numListeners; ++i) {
-                    anim.mPauseListeners.add(oldListeners.get(i));
-                }
+                anim.mPauseListeners = new ArrayList<AnimatorPauseListener>(mPauseListeners);
             }
             return anim;
         } catch (CloneNotSupportedException e) {
@@ -469,4 +529,35 @@
     public void setAllowRunningAsynchronously(boolean mayRunAsync) {
         // It is up to subclasses to support this, if they can.
     }
+
+    /**
+     * Creates a {@link ConstantState} which holds changing configurations information associated
+     * with the given Animator.
+     * <p>
+     * When {@link #newInstance()} is called, default implementation clones the Animator.
+     */
+    private static class AnimatorConstantState extends ConstantState<Animator> {
+
+        final Animator mAnimator;
+        int mChangingConf;
+
+        public AnimatorConstantState(Animator animator) {
+            mAnimator = animator;
+            // ensure a reference back to here so that constante state is not gc'ed.
+            mAnimator.mConstantState = this;
+            mChangingConf = mAnimator.getChangingConfigurations();
+        }
+
+        @Override
+        public int getChangingConfigurations() {
+            return mChangingConf;
+        }
+
+        @Override
+        public Animator newInstance() {
+            final Animator clone = mAnimator.clone();
+            clone.mConstantState = this;
+            return clone;
+        }
+    }
 }
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java
index 25417ed..688d7e4 100644
--- a/core/java/android/animation/AnimatorInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -16,6 +16,8 @@
 package android.animation;
 
 import android.content.Context;
+import android.content.res.ConfigurationBoundResourceCache;
+import android.content.res.ConstantState;
 import android.content.res.Resources;
 import android.content.res.Resources.NotFoundException;
 import android.content.res.Resources.Theme;
@@ -30,6 +32,8 @@
 import android.util.Xml;
 import android.view.InflateException;
 import android.view.animation.AnimationUtils;
+import android.view.animation.BaseInterpolator;
+import android.view.animation.Interpolator;
 
 import com.android.internal.R;
 
@@ -67,6 +71,9 @@
 
     private static final boolean DBG_ANIMATOR_INFLATER = false;
 
+    // used to calculate changing configs for resource references
+    private static final TypedValue sTmpTypedValue = new TypedValue();
+
     /**
      * Loads an {@link Animator} object from a resource
      *
@@ -98,11 +105,34 @@
     /** @hide */
     public static Animator loadAnimator(Resources resources, Theme theme, int id,
             float pathErrorScale) throws NotFoundException {
-
+        final ConfigurationBoundResourceCache<Animator> animatorCache = resources
+                .getAnimatorCache();
+        Animator animator = animatorCache.get(id, theme);
+        if (animator != null) {
+            if (DBG_ANIMATOR_INFLATER) {
+                Log.d(TAG, "loaded animator from cache, " + resources.getResourceName(id));
+            }
+            return animator;
+        } else if (DBG_ANIMATOR_INFLATER) {
+            Log.d(TAG, "cache miss for animator " + resources.getResourceName(id));
+        }
         XmlResourceParser parser = null;
         try {
             parser = resources.getAnimation(id);
-            return createAnimatorFromXml(resources, theme, parser, pathErrorScale);
+            animator = createAnimatorFromXml(resources, theme, parser, pathErrorScale);
+            if (animator != null) {
+                animator.appendChangingConfigurations(getChangingConfigs(resources, id));
+                final ConstantState<Animator> constantState = animator.createConstantState();
+                if (constantState != null) {
+                    if (DBG_ANIMATOR_INFLATER) {
+                        Log.d(TAG, "caching animator for res " + resources.getResourceName(id));
+                    }
+                    animatorCache.put(id, theme, constantState);
+                    // create a new animator so that cached version is never used by the user
+                    animator = constantState.newInstance(resources, theme);
+                }
+            }
+            return animator;
         } catch (XmlPullParserException ex) {
             Resources.NotFoundException rnf =
                     new Resources.NotFoundException("Can't load animation resource ID #0x" +
@@ -122,10 +152,29 @@
 
     public static StateListAnimator loadStateListAnimator(Context context, int id)
             throws NotFoundException {
+        final Resources resources = context.getResources();
+        final ConfigurationBoundResourceCache<StateListAnimator> cache = resources
+                .getStateListAnimatorCache();
+        final Theme theme = context.getTheme();
+        StateListAnimator animator = cache.get(id, theme);
+        if (animator != null) {
+            return animator;
+        }
         XmlResourceParser parser = null;
         try {
-            parser = context.getResources().getAnimation(id);
-            return createStateListAnimatorFromXml(context, parser, Xml.asAttributeSet(parser));
+            parser = resources.getAnimation(id);
+            animator = createStateListAnimatorFromXml(context, parser, Xml.asAttributeSet(parser));
+            if (animator != null) {
+                animator.appendChangingConfigurations(getChangingConfigs(resources, id));
+                final ConstantState<StateListAnimator> constantState = animator
+                        .createConstantState();
+                if (constantState != null) {
+                    cache.put(id, theme, constantState);
+                    // return a clone so that the animator in constant state is never used.
+                    animator = constantState.newInstance(resources, theme);
+                }
+            }
+            return animator;
         } catch (XmlPullParserException ex) {
             Resources.NotFoundException rnf =
                     new Resources.NotFoundException(
@@ -172,14 +221,13 @@
                         for (int i = 0; i < attributeCount; i++) {
                             int attrName = attributeSet.getAttributeNameResource(i);
                             if (attrName == R.attr.animation) {
-                                animator = loadAnimator(context,
-                                        attributeSet.getAttributeResourceValue(i, 0));
+                                final int animId = attributeSet.getAttributeResourceValue(i, 0);
+                                animator = loadAnimator(context, animId);
                             } else {
                                 states[stateIndex++] =
                                         attributeSet.getAttributeBooleanValue(i, false) ?
                                                 attrName : -attrName;
                             }
-
                         }
                         if (animator == null) {
                             animator = createAnimatorFromXml(context.getResources(),
@@ -192,7 +240,6 @@
                         }
                         stateListAnimator
                                 .addState(StateSet.trimStateSet(states, stateIndex), animator);
-
                     }
                     break;
             }
@@ -508,7 +555,6 @@
     private static Animator createAnimatorFromXml(Resources res, Theme theme, XmlPullParser parser,
             AttributeSet attrs, AnimatorSet parent, int sequenceOrdering, float pixelSize)
             throws XmlPullParserException, IOException {
-
         Animator anim = null;
         ArrayList<Animator> childAnims = null;
 
@@ -537,8 +583,8 @@
                 } else {
                     a = res.obtainAttributes(attrs, R.styleable.AnimatorSet);
                 }
-                int ordering = a.getInt(R.styleable.AnimatorSet_ordering,
-                        TOGETHER);
+                anim.appendChangingConfigurations(a.getChangingConfigurations());
+                int ordering = a.getInt(R.styleable.AnimatorSet_ordering, TOGETHER);
                 createAnimatorFromXml(res, theme, parser, attrs, (AnimatorSet) anim, ordering,
                         pixelSize);
                 a.recycle();
@@ -565,7 +611,6 @@
                 parent.playSequentially(animsArray);
             }
         }
-
         return anim;
 
     }
@@ -591,7 +636,6 @@
     private static ValueAnimator loadAnimator(Resources res, Theme theme,
             AttributeSet attrs, ValueAnimator anim, float pathErrorScale)
             throws NotFoundException {
-
         TypedArray arrayAnimator = null;
         TypedArray arrayObjectAnimator = null;
 
@@ -609,25 +653,37 @@
             } else {
                 arrayObjectAnimator = res.obtainAttributes(attrs, R.styleable.PropertyAnimator);
             }
+            anim.appendChangingConfigurations(arrayObjectAnimator.getChangingConfigurations());
         }
 
         if (anim == null) {
             anim = new ValueAnimator();
         }
+        anim.appendChangingConfigurations(arrayAnimator.getChangingConfigurations());
 
         parseAnimatorFromTypeArray(anim, arrayAnimator, arrayObjectAnimator, pathErrorScale);
 
-        final int resID =
-                arrayAnimator.getResourceId(R.styleable.Animator_interpolator, 0);
+        final int resID = arrayAnimator.getResourceId(R.styleable.Animator_interpolator, 0);
         if (resID > 0) {
-            anim.setInterpolator(AnimationUtils.loadInterpolator(res, theme, resID));
+            final Interpolator interpolator = AnimationUtils.loadInterpolator(res, theme, resID);
+            if (interpolator instanceof BaseInterpolator) {
+                anim.appendChangingConfigurations(
+                        ((BaseInterpolator) interpolator).getChangingConfiguration());
+            }
+            anim.setInterpolator(interpolator);
         }
 
         arrayAnimator.recycle();
         if (arrayObjectAnimator != null) {
             arrayObjectAnimator.recycle();
         }
-
         return anim;
     }
+
+    private static int getChangingConfigs(Resources resources, int id) {
+        synchronized (sTmpTypedValue) {
+            resources.getValue(id, sTmpTypedValue, true);
+            return sTmpTypedValue.changingConfigurations;
+        }
+    }
 }
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 0aa8fdd..92762c3 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -241,6 +241,19 @@
     }
 
     /**
+     * @hide
+     */
+    @Override
+    public int getChangingConfigurations() {
+        int conf = super.getChangingConfigurations();
+        final int nodeCount = mNodes.size();
+        for (int i = 0; i < nodeCount; i ++) {
+            conf |= mNodes.get(i).animation.getChangingConfigurations();
+        }
+        return conf;
+    }
+
+    /**
      * Sets the TimeInterpolator for all current {@link #getChildAnimations() child animations}
      * of this AnimatorSet. The default value is null, which means that no interpolator
      * is set on this AnimatorSet. Setting the interpolator to any non-null value
@@ -628,23 +641,25 @@
          * manually, as we clone each Node (and its animation). The clone will then be sorted,
          * and will populate any appropriate lists, when it is started.
          */
+        final int nodeCount = mNodes.size();
         anim.mNeedsSort = true;
         anim.mTerminated = false;
         anim.mStarted = false;
         anim.mPlayingSet = new ArrayList<Animator>();
         anim.mNodeMap = new HashMap<Animator, Node>();
-        anim.mNodes = new ArrayList<Node>();
-        anim.mSortedNodes = new ArrayList<Node>();
+        anim.mNodes = new ArrayList<Node>(nodeCount);
+        anim.mSortedNodes = new ArrayList<Node>(nodeCount);
         anim.mReversible = mReversible;
         anim.mSetListener = null;
 
         // Walk through the old nodes list, cloning each node and adding it to the new nodemap.
         // One problem is that the old node dependencies point to nodes in the old AnimatorSet.
         // We need to track the old/new nodes in order to reconstruct the dependencies in the clone.
-        HashMap<Node, Node> nodeCloneMap = new HashMap<Node, Node>(); // <old, new>
-        for (Node node : mNodes) {
+
+        for (int n = 0; n < nodeCount; n++) {
+            final Node node = mNodes.get(n);
             Node nodeClone = node.clone();
-            nodeCloneMap.put(node, nodeClone);
+            node.mTmpClone = nodeClone;
             anim.mNodes.add(nodeClone);
             anim.mNodeMap.put(nodeClone.animation, nodeClone);
             // Clear out the dependencies in the clone; we'll set these up manually later
@@ -652,40 +667,50 @@
             nodeClone.tmpDependencies = null;
             nodeClone.nodeDependents = null;
             nodeClone.nodeDependencies = null;
+
             // clear out any listeners that were set up by the AnimatorSet; these will
             // be set up when the clone's nodes are sorted
-            ArrayList<AnimatorListener> cloneListeners = nodeClone.animation.getListeners();
+            final ArrayList<AnimatorListener> cloneListeners = nodeClone.animation.getListeners();
             if (cloneListeners != null) {
-                ArrayList<AnimatorListener> listenersToRemove = null;
-                for (AnimatorListener listener : cloneListeners) {
+                for (int i = cloneListeners.size() - 1; i >= 0; i--) {
+                    final AnimatorListener listener = cloneListeners.get(i);
                     if (listener instanceof AnimatorSetListener) {
-                        if (listenersToRemove == null) {
-                            listenersToRemove = new ArrayList<AnimatorListener>();
-                        }
-                        listenersToRemove.add(listener);
-                    }
-                }
-                if (listenersToRemove != null) {
-                    for (AnimatorListener listener : listenersToRemove) {
-                        cloneListeners.remove(listener);
+                        cloneListeners.remove(i);
                     }
                 }
             }
         }
         // Now that we've cloned all of the nodes, we're ready to walk through their
         // dependencies, mapping the old dependencies to the new nodes
-        for (Node node : mNodes) {
-            Node nodeClone = nodeCloneMap.get(node);
+        for (int n = 0; n < nodeCount; n++) {
+            final Node node = mNodes.get(n);
+            final Node clone = node.mTmpClone;
             if (node.dependencies != null) {
-                for (Dependency dependency : node.dependencies) {
-                    Node clonedDependencyNode = nodeCloneMap.get(dependency.node);
-                    Dependency cloneDependency = new Dependency(clonedDependencyNode,
+                clone.dependencies = new ArrayList<Dependency>(node.dependencies.size());
+                final int depSize = node.dependencies.size();
+                for (int i = 0; i < depSize; i ++) {
+                    final Dependency dependency = node.dependencies.get(i);
+                    Dependency cloneDependency = new Dependency(dependency.node.mTmpClone,
                             dependency.rule);
-                    nodeClone.addDependency(cloneDependency);
+                    clone.dependencies.add(cloneDependency);
+                }
+            }
+            if (node.nodeDependents != null) {
+                clone.nodeDependents = new ArrayList<Node>(node.nodeDependents.size());
+                for (Node dep : node.nodeDependents) {
+                    clone.nodeDependents.add(dep.mTmpClone);
+                }
+            }
+            if (node.nodeDependencies != null) {
+                clone.nodeDependencies = new ArrayList<Node>(node.nodeDependencies.size());
+                for (Node dep : node.nodeDependencies) {
+                    clone.nodeDependencies.add(dep.mTmpClone);
                 }
             }
         }
-
+        for (int n = 0; n < nodeCount; n++) {
+            mNodes.get(n).mTmpClone = null;
+        }
         return anim;
     }
 
@@ -1017,6 +1042,11 @@
         public boolean done = false;
 
         /**
+         * Temporary field to hold the clone in AnimatorSet#clone. Cleaned after clone is complete
+         */
+        private Node mTmpClone = null;
+
+        /**
          * Constructs the Node with the animation that it encapsulates. A Node has no
          * dependencies by default; dependencies are added via the addDependency()
          * method.
diff --git a/core/java/android/animation/FloatKeyframeSet.java b/core/java/android/animation/FloatKeyframeSet.java
index 12e5862..abac246 100644
--- a/core/java/android/animation/FloatKeyframeSet.java
+++ b/core/java/android/animation/FloatKeyframeSet.java
@@ -19,6 +19,7 @@
 import android.animation.Keyframe.FloatKeyframe;
 
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * This class holds a collection of FloatKeyframe objects and is called by ValueAnimator to calculate
@@ -47,8 +48,8 @@
 
     @Override
     public FloatKeyframeSet clone() {
-        ArrayList<Keyframe> keyframes = mKeyframes;
-        int numKeyframes = mKeyframes.size();
+        final List<Keyframe> keyframes = mKeyframes;
+        final int numKeyframes = mKeyframes.size();
         FloatKeyframe[] newKeyframes = new FloatKeyframe[numKeyframes];
         for (int i = 0; i < numKeyframes; ++i) {
             newKeyframes[i] = (FloatKeyframe) keyframes.get(i).clone();
diff --git a/core/java/android/animation/IntKeyframeSet.java b/core/java/android/animation/IntKeyframeSet.java
index 7a5b0ec..0ec5138 100644
--- a/core/java/android/animation/IntKeyframeSet.java
+++ b/core/java/android/animation/IntKeyframeSet.java
@@ -19,6 +19,7 @@
 import android.animation.Keyframe.IntKeyframe;
 
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * This class holds a collection of IntKeyframe objects and is called by ValueAnimator to calculate
@@ -47,7 +48,7 @@
 
     @Override
     public IntKeyframeSet clone() {
-        ArrayList<Keyframe> keyframes = mKeyframes;
+        List<Keyframe> keyframes = mKeyframes;
         int numKeyframes = mKeyframes.size();
         IntKeyframe[] newKeyframes = new IntKeyframe[numKeyframes];
         for (int i = 0; i < numKeyframes; ++i) {
diff --git a/core/java/android/animation/KeyframeSet.java b/core/java/android/animation/KeyframeSet.java
index 8d15db2..0e99bff 100644
--- a/core/java/android/animation/KeyframeSet.java
+++ b/core/java/android/animation/KeyframeSet.java
@@ -18,6 +18,8 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.List;
+
 import android.animation.Keyframe.IntKeyframe;
 import android.animation.Keyframe.FloatKeyframe;
 import android.animation.Keyframe.ObjectKeyframe;
@@ -36,16 +38,16 @@
     Keyframe mFirstKeyframe;
     Keyframe mLastKeyframe;
     TimeInterpolator mInterpolator; // only used in the 2-keyframe case
-    ArrayList<Keyframe> mKeyframes; // only used when there are not 2 keyframes
+    List<Keyframe> mKeyframes; // only used when there are not 2 keyframes
     TypeEvaluator mEvaluator;
 
 
     public KeyframeSet(Keyframe... keyframes) {
         mNumKeyframes = keyframes.length;
-        mKeyframes = new ArrayList<Keyframe>();
-        mKeyframes.addAll(Arrays.asList(keyframes));
-        mFirstKeyframe = mKeyframes.get(0);
-        mLastKeyframe = mKeyframes.get(mNumKeyframes - 1);
+        // immutable list
+        mKeyframes = Arrays.asList(keyframes);
+        mFirstKeyframe = keyframes[0];
+        mLastKeyframe = keyframes[mNumKeyframes - 1];
         mInterpolator = mLastKeyframe.getInterpolator();
     }
 
@@ -57,7 +59,7 @@
     public void invalidateCache() {
     }
 
-    public ArrayList<Keyframe> getKeyframes() {
+    public List<Keyframe> getKeyframes() {
         return mKeyframes;
     }
 
@@ -177,9 +179,9 @@
 
     @Override
     public KeyframeSet clone() {
-        ArrayList<Keyframe> keyframes = mKeyframes;
+        List<Keyframe> keyframes = mKeyframes;
         int numKeyframes = mKeyframes.size();
-        Keyframe[] newKeyframes = new Keyframe[numKeyframes];
+        final Keyframe[] newKeyframes = new Keyframe[numKeyframes];
         for (int i = 0; i < numKeyframes; ++i) {
             newKeyframes[i] = keyframes.get(i).clone();
         }
diff --git a/core/java/android/animation/Keyframes.java b/core/java/android/animation/Keyframes.java
index 6611c6c..c921466 100644
--- a/core/java/android/animation/Keyframes.java
+++ b/core/java/android/animation/Keyframes.java
@@ -16,6 +16,7 @@
 package android.animation;
 
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * This interface abstracts a collection of Keyframe objects and is called by
@@ -62,7 +63,7 @@
      * @return A list of all Keyframes contained by this. This may return null if this is
      * not made up of Keyframes.
      */
-    ArrayList<Keyframe> getKeyframes();
+    List<Keyframe> getKeyframes();
 
     Keyframes clone();
 
diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java
index d372933..97426c3 100644
--- a/core/java/android/animation/PropertyValuesHolder.java
+++ b/core/java/android/animation/PropertyValuesHolder.java
@@ -27,6 +27,7 @@
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 /**
@@ -791,7 +792,7 @@
             // check to make sure that mProperty is on the class of target
             try {
                 Object testValue = null;
-                ArrayList<Keyframe> keyframes = mKeyframes.getKeyframes();
+                List<Keyframe> keyframes = mKeyframes.getKeyframes();
                 int keyframeCount = keyframes == null ? 0 : keyframes.size();
                 for (int i = 0; i < keyframeCount; i++) {
                     Keyframe kf = keyframes.get(i);
@@ -814,7 +815,7 @@
         if (mSetter == null) {
             setupSetter(targetClass);
         }
-        ArrayList<Keyframe> keyframes = mKeyframes.getKeyframes();
+        List<Keyframe> keyframes = mKeyframes.getKeyframes();
         int keyframeCount = keyframes == null ? 0 : keyframes.size();
         for (int i = 0; i < keyframeCount; i++) {
             Keyframe kf = keyframes.get(i);
@@ -890,7 +891,7 @@
      * @param target The object which holds the start values that should be set.
      */
     void setupStartValue(Object target) {
-        ArrayList<Keyframe> keyframes = mKeyframes.getKeyframes();
+        List<Keyframe> keyframes = mKeyframes.getKeyframes();
         if (!keyframes.isEmpty()) {
             setupValue(target, keyframes.get(0));
         }
@@ -905,7 +906,7 @@
      * @param target The object which holds the start values that should be set.
      */
     void setupEndValue(Object target) {
-        ArrayList<Keyframe> keyframes = mKeyframes.getKeyframes();
+        List<Keyframe> keyframes = mKeyframes.getKeyframes();
         if (!keyframes.isEmpty()) {
             setupValue(target, keyframes.get(keyframes.size() - 1));
         }
diff --git a/core/java/android/animation/StateListAnimator.java b/core/java/android/animation/StateListAnimator.java
index 7256a06..d49e914 100644
--- a/core/java/android/animation/StateListAnimator.java
+++ b/core/java/android/animation/StateListAnimator.java
@@ -16,6 +16,7 @@
 
 package android.animation;
 
+import android.content.res.ConstantState;
 import android.util.StateSet;
 import android.view.View;
 
@@ -44,25 +45,31 @@
  * @attr ref android.R.styleable#DrawableStates_state_pressed
  * @attr ref android.R.styleable#StateListAnimatorItem_animation
  */
-public class StateListAnimator {
+public class StateListAnimator implements Cloneable {
 
-    private final ArrayList<Tuple> mTuples = new ArrayList<Tuple>();
-
+    private ArrayList<Tuple> mTuples = new ArrayList<Tuple>();
     private Tuple mLastMatch = null;
-
     private Animator mRunningAnimator = null;
-
     private WeakReference<View> mViewRef;
+    private StateListAnimatorConstantState mConstantState;
+    private AnimatorListenerAdapter mAnimatorListener;
+    private int mChangingConfigurations;
 
-    private AnimatorListenerAdapter mAnimatorListener = new AnimatorListenerAdapter() {
-        @Override
-        public void onAnimationEnd(Animator animation) {
-            animation.setTarget(null);
-            if (mRunningAnimator == animation) {
-                mRunningAnimator = null;
+    public StateListAnimator() {
+        initAnimatorListener();
+    }
+
+    private void initAnimatorListener() {
+        mAnimatorListener = new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                animation.setTarget(null);
+                if (mRunningAnimator == animation) {
+                    mRunningAnimator = null;
+                }
             }
-        }
-    };
+        };
+    }
 
     /**
      * Associates the given animator with the provided drawable state specs so that it will be run
@@ -75,6 +82,7 @@
         Tuple tuple = new Tuple(specs, animator);
         tuple.mAnimator.addListener(mAnimatorListener);
         mTuples.add(tuple);
+        mChangingConfigurations |= animator.getChangingConfigurations();
     }
 
     /**
@@ -118,12 +126,35 @@
         for (int i = 0; i < size; i++) {
             mTuples.get(i).mAnimator.setTarget(null);
         }
-
         mViewRef = null;
         mLastMatch = null;
         mRunningAnimator = null;
     }
 
+    @Override
+    public StateListAnimator clone() {
+        try {
+            StateListAnimator clone = (StateListAnimator) super.clone();
+            clone.mTuples = new ArrayList<Tuple>(mTuples.size());
+            clone.mLastMatch = null;
+            clone.mRunningAnimator = null;
+            clone.mViewRef = null;
+            clone.mAnimatorListener = null;
+            clone.initAnimatorListener();
+            final int tupleSize = mTuples.size();
+            for (int i = 0; i < tupleSize; i++) {
+                final Tuple tuple = mTuples.get(i);
+                final Animator animatorClone = tuple.mAnimator.clone();
+                animatorClone.removeListener(mAnimatorListener);
+                clone.addState(tuple.mSpecs, animatorClone);
+            }
+            clone.setChangingConfigurations(getChangingConfigurations());
+            return clone;
+        } catch (CloneNotSupportedException e) {
+            throw new AssertionError("cannot clone state list animator", e);
+        }
+    }
+
     /**
      * Called by View
      * @hide
@@ -182,6 +213,63 @@
     }
 
     /**
+     * Return a mask of the configuration parameters for which this animator may change, requiring
+     * that it be re-created.  The default implementation returns whatever was provided through
+     * {@link #setChangingConfigurations(int)} or 0 by default.
+     *
+     * @return Returns a mask of the changing configuration parameters, as defined by
+     * {@link android.content.pm.ActivityInfo}.
+     *
+     * @see android.content.pm.ActivityInfo
+     * @hide
+     */
+    public int getChangingConfigurations() {
+        return mChangingConfigurations;
+    }
+
+    /**
+     * Set a mask of the configuration parameters for which this animator may change, requiring
+     * that it should be recreated from resources instead of being cloned.
+     *
+     * @param configs A mask of the changing configuration parameters, as
+     * defined by {@link android.content.pm.ActivityInfo}.
+     *
+     * @see android.content.pm.ActivityInfo
+     * @hide
+     */
+    public void setChangingConfigurations(int configs) {
+        mChangingConfigurations = configs;
+    }
+
+    /**
+     * Sets the changing configurations value to the union of the current changing configurations
+     * and the provided configs.
+     * This method is called while loading the animator.
+     * @hide
+     */
+    public void appendChangingConfigurations(int configs) {
+        mChangingConfigurations |= configs;
+    }
+
+    /**
+     * Return a {@link android.content.res.ConstantState} instance that holds the shared state of
+     * this Animator.
+     * <p>
+     * This constant state is used to create new instances of this animator when needed. Default
+     * implementation creates a new {@link StateListAnimatorConstantState}. You can override this
+     * method to provide your custom logic or return null if you don't want this animator to be
+     * cached.
+     *
+     * @return The {@link android.content.res.ConstantState} associated to this Animator.
+     * @see android.content.res.ConstantState
+     * @see #clone()
+     * @hide
+     */
+    public ConstantState<StateListAnimator> createConstantState() {
+        return new StateListAnimatorConstantState(this);
+    }
+
+    /**
      * @hide
      */
     public static class Tuple {
@@ -209,4 +297,36 @@
             return mAnimator;
         }
     }
+
+    /**
+     * Creates a constant state which holds changing configurations information associated with the
+     * given Animator.
+     * <p>
+     * When new instance is called, default implementation clones the Animator.
+     */
+    private static class StateListAnimatorConstantState
+            extends ConstantState<StateListAnimator> {
+
+        final StateListAnimator mAnimator;
+
+        int mChangingConf;
+
+        public StateListAnimatorConstantState(StateListAnimator animator) {
+            mAnimator = animator;
+            mAnimator.mConstantState = this;
+            mChangingConf = mAnimator.getChangingConfigurations();
+        }
+
+        @Override
+        public int getChangingConfigurations() {
+            return mChangingConf;
+        }
+
+        @Override
+        public StateListAnimator newInstance() {
+            final StateListAnimator clone = mAnimator.clone();
+            clone.mConstantState = this;
+            return clone;
+        }
+    }
 }
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 0d17d67..07f79b8 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -16,6 +16,7 @@
 
 package android.animation;
 
+import android.content.res.ConfigurationBoundResourceCache;
 import android.os.Looper;
 import android.os.Trace;
 import android.util.AndroidRuntimeException;
@@ -1289,12 +1290,7 @@
     public ValueAnimator clone() {
         final ValueAnimator anim = (ValueAnimator) super.clone();
         if (mUpdateListeners != null) {
-            ArrayList<AnimatorUpdateListener> oldListeners = mUpdateListeners;
-            anim.mUpdateListeners = new ArrayList<AnimatorUpdateListener>();
-            int numListeners = oldListeners.size();
-            for (int i = 0; i < numListeners; ++i) {
-                anim.mUpdateListeners.add(oldListeners.get(i));
-            }
+            anim.mUpdateListeners = new ArrayList<AnimatorUpdateListener>(mUpdateListeners);
         }
         anim.mSeekTime = -1;
         anim.mPlayingBackwards = false;
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index cc9aed8..5038df9 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -16,10 +16,14 @@
 
 package android.app;
 
+import android.app.trust.ITrustManager;
+import android.content.Context;
 import android.content.Intent;
 import android.os.Binder;
 import android.os.RemoteException;
 import android.os.IBinder;
+import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.view.IWindowManager;
 import android.view.IOnKeyguardExitResult;
 import android.view.WindowManagerGlobal;
@@ -33,6 +37,7 @@
  */
 public class KeyguardManager {
     private IWindowManager mWM;
+    private ITrustManager mTrustManager;
 
     /**
      * Intent used to prompt user for device credentials.
@@ -151,6 +156,8 @@
 
     KeyguardManager() {
         mWM = WindowManagerGlobal.getWindowManagerService();
+        mTrustManager = ITrustManager.Stub.asInterface(
+                ServiceManager.getService(Context.TRUST_SERVICE));
     }
 
     /**
@@ -218,6 +225,34 @@
     }
 
     /**
+     * Return whether unlocking the device is currently not requiring a password
+     * because of a trust agent.
+     *
+     * @return true if the keyguard can currently be unlocked without entering credentials
+     *         because the device is in a trusted environment.
+     */
+    public boolean isKeyguardInTrustedState() {
+        return isKeyguardInTrustedState(UserHandle.getCallingUserId());
+    }
+
+    /**
+     * Return whether unlocking the device is currently not requiring a password
+     * because of a trust agent.
+     *
+     * @param userId the user for which the trusted state should be reported.
+     * @return true if the keyguard can currently be unlocked without entering credentials
+     *         because the device is in a trusted environment.
+     * @hide
+     */
+    public boolean isKeyguardInTrustedState(int userId) {
+        try {
+            return mTrustManager.isTrusted(userId);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
      * @deprecated Use {@link android.view.WindowManager.LayoutParams#FLAG_DISMISS_KEYGUARD}
      * and/or {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED}
      * instead; this allows you to seamlessly hide the keyguard as your application
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 4aec9e0..b0dd70f 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -25,6 +25,7 @@
 import android.graphics.Canvas;
 import android.graphics.Point;
 import android.hardware.display.DisplayManagerGlobal;
+import android.os.IBinder;
 import android.os.Looper;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
@@ -919,7 +920,7 @@
         public IAccessibilityServiceClientImpl(Looper looper) {
             super(null, looper, new Callbacks() {
                 @Override
-                public void onSetConnectionId(int connectionId) {
+                public void init(int connectionId, IBinder windowToken) {
                     synchronized (mLock) {
                         mConnectionId = connectionId;
                         mLock.notifyAll();
diff --git a/core/java/android/app/trust/ITrustManager.aidl b/core/java/android/app/trust/ITrustManager.aidl
index 6fbf87d..0193711 100644
--- a/core/java/android/app/trust/ITrustManager.aidl
+++ b/core/java/android/app/trust/ITrustManager.aidl
@@ -29,4 +29,5 @@
     void reportRequireCredentialEntry(int userId);
     void registerTrustListener(in ITrustListener trustListener);
     void unregisterTrustListener(in ITrustListener trustListener);
+    boolean isTrusted(int userId);
 }
diff --git a/core/java/android/content/res/ConfigurationBoundResourceCache.java b/core/java/android/content/res/ConfigurationBoundResourceCache.java
new file mode 100644
index 0000000..cde7e84
--- /dev/null
+++ b/core/java/android/content/res/ConfigurationBoundResourceCache.java
@@ -0,0 +1,138 @@
+/*
+* 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.content.res;
+
+import android.util.ArrayMap;
+import android.util.LongSparseArray;
+import java.lang.ref.WeakReference;
+
+/**
+ * A Cache class which can be used to cache resource objects that are easy to clone but more
+ * expensive to inflate.
+ * @hide
+ */
+public class ConfigurationBoundResourceCache<T> {
+
+    private final ArrayMap<String, LongSparseArray<WeakReference<ConstantState<T>>>> mCache =
+            new ArrayMap<String, LongSparseArray<WeakReference<ConstantState<T>>>>();
+
+    final Resources mResources;
+
+    /**
+     * Creates a Resource cache for the given Resources instance.
+     *
+     * @param resources The Resource which can be used when creating new instances.
+     */
+    public ConfigurationBoundResourceCache(Resources resources) {
+        mResources = resources;
+    }
+
+    /**
+     * Adds a new item to the cache.
+     *
+     * @param key A custom key that uniquely identifies the resource.
+     * @param theme The Theme instance where this resource was loaded.
+     * @param constantState The constant state that can create new instances of the resource.
+     *
+     */
+    public void put(long key, Resources.Theme theme, ConstantState<T> constantState) {
+        if (constantState == null) {
+            return;
+        }
+        final String themeKey = theme == null ? "" : theme.getKey();
+        LongSparseArray<WeakReference<ConstantState<T>>> themedCache;
+        synchronized (this) {
+            themedCache = mCache.get(themeKey);
+            if (themedCache == null) {
+                themedCache = new LongSparseArray<WeakReference<ConstantState<T>>>(1);
+                mCache.put(themeKey, themedCache);
+            }
+            themedCache.put(key, new WeakReference<ConstantState<T>>(constantState));
+        }
+    }
+
+    /**
+     * If the resource is cached, creates a new instance of it and returns.
+     *
+     * @param key The long key which can be used to uniquely identify the resource.
+     * @param theme The The Theme instance where we want to load this resource.
+     *
+     * @return If this resources was loaded before, returns a new instance of it. Otherwise, returns
+     *         null.
+     */
+    public T get(long key, Resources.Theme theme) {
+        final String themeKey = theme != null ? theme.getKey() : "";
+        final LongSparseArray<WeakReference<ConstantState<T>>> themedCache;
+        final WeakReference<ConstantState<T>> wr;
+        synchronized (this) {
+            themedCache = mCache.get(themeKey);
+            if (themedCache == null) {
+                return null;
+            }
+            wr = themedCache.get(key);
+        }
+        if (wr == null) {
+            return null;
+        }
+        final ConstantState entry = wr.get();
+        if (entry != null) {
+            return  (T) entry.newInstance(mResources, theme);
+        } else {  // our entry has been purged
+            synchronized (this) {
+                // there is a potential race condition here where this entry may be put in
+                // another thread. But we prefer it to minimize lock duration
+                themedCache.delete(key);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Users of ConfigurationBoundResourceCache must call this method whenever a configuration
+     * change happens. On this callback, the cache invalidates all resources that are not valid
+     * anymore.
+     *
+     * @param configChanges The configuration changes
+     */
+    public void onConfigurationChange(final int configChanges) {
+        synchronized (this) {
+            final int size = mCache.size();
+            for (int i = size - 1; i >= 0; i--) {
+                final LongSparseArray<WeakReference<ConstantState<T>>>
+                        themeCache = mCache.valueAt(i);
+                onConfigurationChangeInt(themeCache, configChanges);
+                if (themeCache.size() == 0) {
+                    mCache.removeAt(i);
+                }
+            }
+        }
+    }
+
+    private void onConfigurationChangeInt(
+            final LongSparseArray<WeakReference<ConstantState<T>>> themeCache,
+            final int configChanges) {
+        final int size = themeCache.size();
+        for (int i = size - 1; i >= 0; i--) {
+            final WeakReference<ConstantState<T>> wr = themeCache.valueAt(i);
+            final ConstantState<T> constantState = wr.get();
+            if (constantState == null || Configuration.needNewResources(
+                    configChanges, constantState.getChangingConfigurations())) {
+                themeCache.removeAt(i);
+            }
+        }
+    }
+
+}
diff --git a/core/java/android/content/res/ConstantState.java b/core/java/android/content/res/ConstantState.java
new file mode 100644
index 0000000..ee609df
--- /dev/null
+++ b/core/java/android/content/res/ConstantState.java
@@ -0,0 +1,61 @@
+/*
+* 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.content.res;
+
+/**
+ * A cache class that can provide new instances of a particular resource which may change
+ * depending on the current {@link Resources.Theme} or {@link Configuration}.
+ * <p>
+ * A constant state should be able to return a bitmask of changing configurations, which
+ * identifies the type of configuration changes that may invalidate this resource. These
+ * configuration changes can be obtained from {@link android.util.TypedValue}. Entities such as
+ * {@link android.animation.Animator} also provide a changing configuration method to include
+ * their dependencies (e.g. An AnimatorSet's changing configuration is the union of the
+ * changing configurations of each Animator in the set)
+ * @hide
+ */
+abstract public class ConstantState<T> {
+
+    /**
+     * Return a bit mask of configuration changes that will impact
+     * this resource (and thus require completely reloading it).
+     */
+    abstract public int getChangingConfigurations();
+
+    /**
+     * Create a new instance without supplying resources the caller
+     * is running in.
+     */
+    public abstract T newInstance();
+
+    /**
+     * Create a new instance from its constant state.  This
+     * must be implemented for resources that change based on the target
+     * density of their caller (that is depending on whether it is
+     * in compatibility mode).
+     */
+    public T newInstance(Resources res) {
+        return newInstance();
+    }
+
+    /**
+     * Create a new instance from its constant state.  This must be
+     * implemented for resources that can have a theme applied.
+     */
+    public T newInstance(Resources res, Resources.Theme theme) {
+        return newInstance(res);
+    }
+}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index e34ce3e..6e9efe1 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -16,6 +16,8 @@
 
 package android.content.res;
 
+import android.animation.Animator;
+import android.animation.StateListAnimator;
 import android.util.Pools.SynchronizedPool;
 import android.view.ViewDebug;
 import com.android.internal.util.XmlUtils;
@@ -115,6 +117,10 @@
             new ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>>();
     private final LongSparseArray<WeakReference<ColorStateList>> mColorStateListCache =
             new LongSparseArray<WeakReference<ColorStateList>>();
+    private final ConfigurationBoundResourceCache<Animator> mAnimatorCache =
+            new ConfigurationBoundResourceCache<Animator>(this);
+    private final ConfigurationBoundResourceCache<StateListAnimator> mStateListAnimatorCache =
+            new ConfigurationBoundResourceCache<StateListAnimator>(this);
 
     private TypedValue mTmpValue = new TypedValue();
     private boolean mPreloading;
@@ -183,6 +189,24 @@
     }
 
     /**
+     * Used by AnimatorInflater.
+     *
+     * @hide
+     */
+    public ConfigurationBoundResourceCache<Animator> getAnimatorCache() {
+        return mAnimatorCache;
+    }
+
+    /**
+     * Used by AnimatorInflater.
+     *
+     * @hide
+     */
+    public ConfigurationBoundResourceCache<StateListAnimator> getStateListAnimatorCache() {
+        return mStateListAnimatorCache;
+    }
+
+    /**
      * This exception is thrown by the resource APIs when a requested resource
      * can not be found.
      */
@@ -1761,23 +1785,7 @@
             // the framework.
             mCompatibilityInfo.applyToDisplayMetrics(mMetrics);
 
-            int configChanges = 0xfffffff;
-            if (config != null) {
-                mTmpConfig.setTo(config);
-                int density = config.densityDpi;
-                if (density == Configuration.DENSITY_DPI_UNDEFINED) {
-                    density = mMetrics.noncompatDensityDpi;
-                }
-
-                mCompatibilityInfo.applyToConfiguration(density, mTmpConfig);
-
-                if (mTmpConfig.locale == null) {
-                    mTmpConfig.locale = Locale.getDefault();
-                    mTmpConfig.setLayoutDirection(mTmpConfig.locale);
-                }
-                configChanges = mConfiguration.updateFrom(mTmpConfig);
-                configChanges = ActivityInfo.activityInfoConfigToNative(configChanges);
-            }
+            int configChanges = calcConfigChanges(config);
             if (mConfiguration.locale == null) {
                 mConfiguration.locale = Locale.getDefault();
                 mConfiguration.setLayoutDirection(mConfiguration.locale);
@@ -1825,6 +1833,8 @@
 
             clearDrawableCachesLocked(mDrawableCache, configChanges);
             clearDrawableCachesLocked(mColorDrawableCache, configChanges);
+            mAnimatorCache.onConfigurationChange(configChanges);
+            mStateListAnimatorCache.onConfigurationChange(configChanges);
 
             mColorStateListCache.clear();
 
@@ -1837,6 +1847,30 @@
         }
     }
 
+    /**
+     * Called by ConfigurationBoundResourceCacheTest via reflection.
+     */
+    private int calcConfigChanges(Configuration config) {
+        int configChanges = 0xfffffff;
+        if (config != null) {
+            mTmpConfig.setTo(config);
+            int density = config.densityDpi;
+            if (density == Configuration.DENSITY_DPI_UNDEFINED) {
+                density = mMetrics.noncompatDensityDpi;
+            }
+
+            mCompatibilityInfo.applyToConfiguration(density, mTmpConfig);
+
+            if (mTmpConfig.locale == null) {
+                mTmpConfig.locale = Locale.getDefault();
+                mTmpConfig.setLayoutDirection(mTmpConfig.locale);
+            }
+            configChanges = mConfiguration.updateFrom(mTmpConfig);
+            configChanges = ActivityInfo.activityInfoConfigToNative(configChanges);
+        }
+        return configChanges;
+    }
+
     private void clearDrawableCachesLocked(
             ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> caches,
             int configChanges) {
diff --git a/core/java/android/hardware/hdmi/HdmiClient.java b/core/java/android/hardware/hdmi/HdmiClient.java
index c2b9846..45a79e1 100644
--- a/core/java/android/hardware/hdmi/HdmiClient.java
+++ b/core/java/android/hardware/hdmi/HdmiClient.java
@@ -8,7 +8,7 @@
 
 /**
  * Parent for classes of various HDMI-CEC device type used to access
- * {@link HdmiControlService}. Contains methods and data used in common.
+ * the HDMI control system service. Contains methods and data used in common.
  *
  * @hide
  */
@@ -16,11 +16,13 @@
 public abstract class HdmiClient {
     private static final String TAG = "HdmiClient";
 
-    protected final IHdmiControlService mService;
+    /* package */ final IHdmiControlService mService;
 
-    protected abstract int getDeviceType();
+    private IHdmiVendorCommandListener mIHdmiVendorCommandListener;
 
-    public HdmiClient(IHdmiControlService service) {
+    /* package */ abstract int getDeviceType();
+
+    /* package */ HdmiClient(IHdmiControlService service) {
         mService = service;
     }
 
@@ -40,7 +42,7 @@
     }
 
     /**
-     * Send a key event to other logical device.
+     * Sends a key event to other logical device.
      *
      * @param keyCode key code to send. Defined in {@link android.view.KeyEvent}.
      * @param isPressed true if this is key press event
@@ -54,7 +56,7 @@
     }
 
     /**
-     * Send vendor-specific command.
+     * Sends vendor-specific command.
      *
      * @param targetAddress address of the target device
      * @param params vendor-specific parameter. For &lt;Vendor Command With ID&gt; do not
@@ -71,18 +73,23 @@
     }
 
     /**
-     * Add a listener used to receive incoming vendor-specific command.
+     * Sets a listener used to receive incoming vendor-specific command.
      *
      * @param listener listener object
      */
-    public void addVendorCommandListener(@NonNull VendorCommandListener listener) {
+    public void setVendorCommandListener(@NonNull VendorCommandListener listener) {
         if (listener == null) {
             throw new IllegalArgumentException("listener cannot be null");
         }
+        if (mIHdmiVendorCommandListener != null) {
+            throw new IllegalStateException("listener was already set");
+        }
         try {
-            mService.addVendorCommandListener(getListenerWrapper(listener), getDeviceType());
+            IHdmiVendorCommandListener wrappedListener = getListenerWrapper(listener);
+            mService.addVendorCommandListener(wrappedListener, getDeviceType());
+            mIHdmiVendorCommandListener = wrappedListener;
         } catch (RemoteException e) {
-            Log.e(TAG, "failed to add vendor command listener: ", e);
+            Log.e(TAG, "failed to set vendor command listener: ", e);
         }
     }
 
diff --git a/core/java/android/hardware/hdmi/HdmiControlManager.java b/core/java/android/hardware/hdmi/HdmiControlManager.java
index ff2ba1e..308a219 100644
--- a/core/java/android/hardware/hdmi/HdmiControlManager.java
+++ b/core/java/android/hardware/hdmi/HdmiControlManager.java
@@ -21,6 +21,8 @@
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
 import android.os.RemoteException;
+import android.util.ArrayMap;
+import android.util.Log;
 
 /**
  * The {@link HdmiControlManager} class is used to send HDMI control messages
@@ -36,6 +38,8 @@
  */
 @SystemApi
 public final class HdmiControlManager {
+    private static final String TAG = "HdmiControlManager";
+
     @Nullable private final IHdmiControlService mService;
 
     /**
@@ -56,7 +60,7 @@
 
     /**
      * Message used by TV to receive volume status from Audio Receiver. It should check volume value
-     * that is retrieved from extra value with the key {@link #EXTRA_MESSAGE_EXTRAM_PARAM1}. If the
+     * that is retrieved from extra value with the key {@link #EXTRA_MESSAGE_EXTRA_PARAM1}. If the
      * value is in range of [0,100], it is current volume of Audio Receiver. And there is another
      * value, {@link #AVR_VOLUME_MUTED}, which is used to inform volume mute.
      */
@@ -71,7 +75,7 @@
      * Used as an extra field in the intent {@link #ACTION_OSD_MESSAGE}. Contains the extra value
      * of the message.
      */
-    public static final String EXTRA_MESSAGE_EXTRAM_PARAM1 =
+    public static final String EXTRA_MESSAGE_EXTRA_PARAM1 =
             "android.hardware.hdmi.extra.MESSAGE_EXTRA_PARAM1";
 
     /**
@@ -251,10 +255,9 @@
     private final boolean mHasTvDevice;
 
     /**
-     * @hide - hide this constructor because it has a parameter of type
-     * IHdmiControlService, which is a system private class. The right way
-     * to create an instance of this class is using the factory
-     * Context.getSystemService.
+     * {@hide} - hide this constructor because it has a parameter of type IHdmiControlService,
+     * which is a system private class. The right way to create an instance of this class is
+     * using the factory Context.getSystemService.
      */
     public HdmiControlManager(IHdmiControlService service) {
         mService = service;
@@ -340,6 +343,9 @@
         void onReceived(HdmiHotplugEvent event);
     }
 
+    private final ArrayMap<HotplugEventListener, IHdmiHotplugEventListener>
+            mHotplugEventListeners = new ArrayMap<>();
+
     /**
      * Listener used to get vendor-specific commands.
      */
@@ -384,12 +390,19 @@
      */
     public void addHotplugEventListener(HotplugEventListener listener) {
         if (mService == null) {
+            Log.e(TAG, "HdmiControlService is not available");
             return;
         }
+        if (mHotplugEventListeners.containsKey(listener)) {
+            Log.e(TAG, "listener is already registered");
+            return;
+        }
+        IHdmiHotplugEventListener wrappedListener = getHotplugEventListenerWrapper(listener);
+        mHotplugEventListeners.put(listener, wrappedListener);
         try {
-            mService.addHotplugEventListener(getHotplugEventListenerWrapper(listener));
+            mService.addHotplugEventListener(wrappedListener);
         } catch (RemoteException e) {
-            // Do nothing.
+            Log.e(TAG, "failed to add hotplug event listener: ", e);
         }
     }
 
@@ -400,12 +413,18 @@
      */
     public void removeHotplugEventListener(HotplugEventListener listener) {
         if (mService == null) {
+            Log.e(TAG, "HdmiControlService is not available");
+            return;
+        }
+        IHdmiHotplugEventListener wrappedListener = mHotplugEventListeners.remove(listener);
+        if (wrappedListener == null) {
+            Log.e(TAG, "tried to remove not-registered listener");
             return;
         }
         try {
-            mService.removeHotplugEventListener(getHotplugEventListenerWrapper(listener));
+            mService.removeHotplugEventListener(wrappedListener);
         } catch (RemoteException e) {
-            // Do nothing.
+            Log.e(TAG, "failed to remove hotplug event listener: ", e);
         }
     }
 
diff --git a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
index 7abea36..fe414e6 100644
--- a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
+++ b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
@@ -237,14 +237,14 @@
     }
 
     /**
-     * Return the id of the device.
+     * Returns the id of the device.
      */
     public int getId() {
         return mId;
     }
 
     /**
-     * Return the id to be used for CEC device.
+     * Returns the id to be used for CEC device.
      *
      * @param address logical address of CEC device
      * @return id for CEC device
@@ -255,7 +255,7 @@
     }
 
     /**
-     * Return the id to be used for MHL device.
+     * Returns the id to be used for MHL device.
      *
      * @param portId port which the MHL device is connected to
      * @return id for MHL device
@@ -266,7 +266,7 @@
     }
 
     /**
-     * Return the id to be used for hardware port.
+     * Returns the id to be used for hardware port.
      *
      * @param portId port id
      * @return id for hardware port
@@ -276,28 +276,28 @@
     }
 
     /**
-     * Return the CEC logical address of the device.
+     * Returns the CEC logical address of the device.
      */
     public int getLogicalAddress() {
         return mLogicalAddress;
     }
 
     /**
-     * Return the physical address of the device.
+     * Returns the physical address of the device.
      */
     public int getPhysicalAddress() {
         return mPhysicalAddress;
     }
 
     /**
-     * Return the port ID.
+     * Returns the port ID.
      */
     public int getPortId() {
         return mPortId;
     }
 
     /**
-     * Return CEC type of the device. For more details, refer constants between {@link #DEVICE_TV}
+     * Returns CEC type of the device. For more details, refer constants between {@link #DEVICE_TV}
      * and {@link #DEVICE_INACTIVE}.
      */
     public int getDeviceType() {
@@ -305,7 +305,7 @@
     }
 
     /**
-     * Return device's power status. It should be one of the following values.
+     * Returns device's power status. It should be one of the following values.
      * <ul>
      * <li>{@link HdmiControlManager#POWER_STATUS_ON}
      * <li>{@link HdmiControlManager#POWER_STATUS_STANDBY}
@@ -319,21 +319,21 @@
     }
 
     /**
-     * Return MHL device id. Return -1 for non-MHL device.
+     * Returns MHL device id. Return -1 for non-MHL device.
      */
     public int getDeviceId() {
         return mDeviceId;
     }
 
     /**
-     * Return MHL adopter id. Return -1 for non-MHL device.
+     * Returns MHL adopter id. Return -1 for non-MHL device.
      */
     public int getAdopterId() {
         return mAdopterId;
     }
 
     /**
-     * Return {@code true} if the device is of a type that can be an input source.
+     * Returns {@code true} if the device is of a type that can be an input source.
      */
     public boolean isSourceType() {
         return mDeviceType == DEVICE_PLAYBACK
@@ -342,7 +342,7 @@
     }
 
     /**
-     * Return {@code true} if the device represents an HDMI-CEC device. {@code false} if the device
+     * Returns {@code true} if the device represents an HDMI-CEC device. {@code false} if the device
      * is either MHL or other device.
      */
     public boolean isCecDevice() {
@@ -350,7 +350,7 @@
     }
 
     /**
-     * Return {@code true} if the device represents an MHL device. {@code false} if the device is
+     * Returns {@code true} if the device represents an MHL device. {@code false} if the device is
      * either CEC or other device.
      */
     public boolean isMhlDevice() {
@@ -358,14 +358,14 @@
     }
 
     /**
-     * Return display (OSD) name of the device.
+     * Returns display (OSD) name of the device.
      */
     public String getDisplayName() {
         return mDisplayName;
     }
 
     /**
-     * Return vendor id of the device. Vendor id is used to distinguish devices built by other
+     * Returns vendor id of the device. Vendor id is used to distinguish devices built by other
      * manufactures. This is required for vendor-specific command on CEC standard.
      */
     public int getVendorId() {
@@ -373,7 +373,7 @@
     }
 
     /**
-     * Describe the kinds of special objects contained in this Parcelable's marshalled
+     * Describes the kinds of special objects contained in this Parcelable's marshalled
      * representation.
      */
     @Override
@@ -382,7 +382,7 @@
     }
 
     /**
-     * Serialize this object into a {@link Parcel}.
+     * Serializes this object into a {@link Parcel}.
      *
      * @param dest The Parcel in which the object should be written.
      * @param flags Additional flags about how the object should be written. May be 0 or
diff --git a/core/java/android/hardware/hdmi/HdmiHotplugEvent.java b/core/java/android/hardware/hdmi/HdmiHotplugEvent.java
index 7be4bc5..9476742 100644
--- a/core/java/android/hardware/hdmi/HdmiHotplugEvent.java
+++ b/core/java/android/hardware/hdmi/HdmiHotplugEvent.java
@@ -44,7 +44,7 @@
     }
 
     /**
-     * Return the port number for which the event occurred.
+     * Returns the port number for which the event occurred.
      *
      * @return port number
      */
@@ -53,7 +53,7 @@
     }
 
     /**
-     * Return the connection status associated with this event
+     * Returns the connection status associated with this event
      *
      * @return true if the device gets connected; otherwise false
      */
@@ -62,7 +62,7 @@
     }
 
     /**
-     * Describe the kinds of special objects contained in this Parcelable's
+     * Describes the kinds of special objects contained in this Parcelable's
      * marshalled representation.
      */
     @Override
@@ -71,7 +71,7 @@
     }
 
     /**
-     * Flatten this object in to a Parcel.
+     * Flattens this object in to a Parcel.
      *
      * @param dest The Parcel in which the object should be written.
      * @param flags Additional flags about how the object should be written.
@@ -86,17 +86,19 @@
     public static final Parcelable.Creator<HdmiHotplugEvent> CREATOR
             = new Parcelable.Creator<HdmiHotplugEvent>() {
         /**
-         * Rebuild a {@link HdmiHotplugEvent} previously stored with
+         * Rebuilds a {@link HdmiHotplugEvent} previously stored with
          * {@link Parcelable#writeToParcel(Parcel, int)}.
          *
          * @param p {@link HdmiHotplugEvent} object to read the Rating from
          * @return a new {@link HdmiHotplugEvent} created from the data in the parcel
          */
+        @Override
         public HdmiHotplugEvent createFromParcel(Parcel p) {
             int port = p.readInt();
             boolean connected = p.readByte() == 1;
             return new HdmiHotplugEvent(port, connected);
         }
+        @Override
         public HdmiHotplugEvent[] newArray(int size) {
             return new HdmiHotplugEvent[size];
         }
diff --git a/core/java/android/hardware/hdmi/HdmiPlaybackClient.java b/core/java/android/hardware/hdmi/HdmiPlaybackClient.java
index 85ccb74..263d6b1 100644
--- a/core/java/android/hardware/hdmi/HdmiPlaybackClient.java
+++ b/core/java/android/hardware/hdmi/HdmiPlaybackClient.java
@@ -64,12 +64,12 @@
         public void onComplete(int status);
     }
 
-    HdmiPlaybackClient(IHdmiControlService service) {
+    /* package */ HdmiPlaybackClient(IHdmiControlService service) {
         super(service);
     }
 
     /**
-     * Perform the feature 'one touch play' from playback device to turn on display
+     * Performs the feature 'one touch play' from playback device to turn on display
      * and switch the input.
      *
      * @param callback {@link OneTouchPlayCallback} object to get informed
@@ -90,7 +90,7 @@
     }
 
     /**
-     * Get the status of display device connected through HDMI bus.
+     * Gets the status of display device connected through HDMI bus.
      *
      * @param callback {@link DisplayStatusCallback} object to get informed
      *         of the result
diff --git a/core/java/android/hardware/hdmi/HdmiPortInfo.java b/core/java/android/hardware/hdmi/HdmiPortInfo.java
index 2ec6126..e52baed 100644
--- a/core/java/android/hardware/hdmi/HdmiPortInfo.java
+++ b/core/java/android/hardware/hdmi/HdmiPortInfo.java
@@ -114,7 +114,7 @@
     }
 
     /**
-     * Describe the kinds of special objects contained in this Parcelable's
+     * Describes the kinds of special objects contained in this Parcelable's
      * marshalled representation.
      */
     @Override
@@ -146,7 +146,7 @@
             };
 
     /**
-     * Serialize this object into a {@link Parcel}.
+     * Serializes this object into a {@link Parcel}.
      *
      * @param dest The Parcel in which the object should be written.
      * @param flags Additional flags about how the object should be written.
diff --git a/core/java/android/hardware/hdmi/HdmiRecordListener.java b/core/java/android/hardware/hdmi/HdmiRecordListener.java
index f6a348a..29f6cfc 100644
--- a/core/java/android/hardware/hdmi/HdmiRecordListener.java
+++ b/core/java/android/hardware/hdmi/HdmiRecordListener.java
@@ -25,7 +25,7 @@
  */
 @SystemApi
 public abstract class HdmiRecordListener {
-    protected HdmiRecordListener() {}
+    public HdmiRecordListener() {}
 
     /**
      * Called when TV received one touch record request from record device. The client of this
@@ -34,7 +34,7 @@
      * @param recorderAddress
      * @return record source to be used for recording. Null if no device is available.
      */
-    public abstract RecordSource getOneTouchRecordSource(int recorderAddress);
+    public abstract RecordSource onOneTouchRecordSourceRequested(int recorderAddress);
 
     /**
      * Called when one touch record is started or failed during initialization.
diff --git a/core/java/android/hardware/hdmi/HdmiRecordSources.java b/core/java/android/hardware/hdmi/HdmiRecordSources.java
index c294f72..922b8e7 100644
--- a/core/java/android/hardware/hdmi/HdmiRecordSources.java
+++ b/core/java/android/hardware/hdmi/HdmiRecordSources.java
@@ -59,21 +59,21 @@
      */
     @SystemApi
     public static abstract class RecordSource {
-        protected final int mSourceType;
-        protected final int mExtraDataSize;
+        /* package */ final int mSourceType;
+        /* package */ final int mExtraDataSize;
 
-        protected RecordSource(int sourceType, int extraDataSize) {
+        /* package */ RecordSource(int sourceType, int extraDataSize) {
             mSourceType = sourceType;
             mExtraDataSize = extraDataSize;
         }
 
-        abstract int extraParamToByteArray(byte[] data, int index);
+        /* package */ abstract int extraParamToByteArray(byte[] data, int index);
 
-        final int getDataSize(boolean includeType)  {
+        /* package */ final int getDataSize(boolean includeType)  {
             return includeType ? mExtraDataSize + 1 : mExtraDataSize;
         }
 
-        final int toByteArray(boolean includeType, byte[] data, int index) {
+        /* package */ final int toByteArray(boolean includeType, byte[] data, int index) {
             if (includeType) {
                 // 1 to 8 bytes (depends on source).
                 // {[Record Source Type]} |
@@ -94,7 +94,7 @@
     // ---- Own source -----------------------------------------------------------------------------
     // ---------------------------------------------------------------------------------------------
     /**
-     * Create {@link OwnSource} of own source.
+     * Creates {@link OwnSource} of own source.
      */
     public static OwnSource ofOwnSource() {
         return new OwnSource();
@@ -311,7 +311,7 @@
      */
     public static final class DigitalChannelData implements DigitalServiceIdentification {
         /** Identifies the logical or virtual channel number of a service. */
-        private ChannelIdentifier mChannelIdentifier;
+        private final ChannelIdentifier mChannelIdentifier;
 
         public static DigitalChannelData ofTwoNumbers(int majorNumber, int minorNumber) {
             return new DigitalChannelData(
@@ -338,7 +338,7 @@
     }
 
     /**
-     * Create {@link DigitalServiceSource} with channel type.
+     * Creates {@link DigitalServiceSource} with channel type.
      *
      * @param broadcastSystem digital broadcast system. It should be one of
      *            <ul>
@@ -389,7 +389,7 @@
     }
 
     /**
-     * Create {@link DigitalServiceSource} of ARIB type.
+     * Creates {@link DigitalServiceSource} of ARIB type.
      *
      * @param aribType ARIB type. It should be one of
      *            <ul>
@@ -420,7 +420,7 @@
     }
 
     /**
-     * Create {@link DigitalServiceSource} of ATSC type.
+     * Creates {@link DigitalServiceSource} of ATSC type.
      *
      * @param atscType ATSC type. It should be one of
      *            <ul>
@@ -451,7 +451,7 @@
     }
 
     /**
-     * Create {@link DigitalServiceSource} of ATSC type.
+     * Creates {@link DigitalServiceSource} of ATSC type.
      *
      * @param dvbType DVB type. It should be one of
      *            <ul>
@@ -572,7 +572,7 @@
     public static final int BROADCAST_SYSTEM_PAL_OTHER_SYSTEM = 31;
 
     /**
-     * Create {@link AnalogueServiceSource} of analogue service.
+     * Creates {@link AnalogueServiceSource} of analogue service.
      *
      * @param broadcastType
      * @param frequency
@@ -615,7 +615,7 @@
      */
     @SystemApi
     public static final class AnalogueServiceSource extends RecordSource {
-        static final int EXTRA_DATA_SIZE = 4;
+        /* package */ static final int EXTRA_DATA_SIZE = 4;
 
         /** Indicates the Analogue broadcast type. */
         private final int mBroadcastType;
@@ -635,7 +635,7 @@
         }
 
         @Override
-        protected int extraParamToByteArray(byte[] data, int index) {
+        /* package */ int extraParamToByteArray(byte[] data, int index) {
             // [Analogue Broadcast Type] - 1 byte
             data[index] = (byte) mBroadcastType;
             // [Analogue Frequency] - 2 bytes
@@ -651,7 +651,7 @@
     // ---- External plug data ---------------------------------------------------------------------
     // ---------------------------------------------------------------------------------------------
     /**
-     * Create {@link ExternalPlugData} of external plug type.
+     * Creates {@link ExternalPlugData} of external plug type.
      *
      * @param plugNumber plug number. It should be in range of [1, 255]
      * @hide
@@ -695,7 +695,7 @@
     // ---- External physical address --------------------------------------------------------------
     // ---------------------------------------------------------------------------------------------
     /**
-     * Create {@link ExternalPhysicalAddress} of external physical address.
+     * Creates {@link ExternalPhysicalAddress} of external physical address.
      *
      * @param physicalAddress
      * @hide
@@ -754,7 +754,7 @@
     }
 
     /**
-     * Check the byte array of record source.
+     * Checks the byte array of record source.
      * @hide
      */
     @SystemApi
diff --git a/core/java/android/hardware/hdmi/HdmiTimerRecordSources.java b/core/java/android/hardware/hdmi/HdmiTimerRecordSources.java
index 1780707..bf97375 100644
--- a/core/java/android/hardware/hdmi/HdmiTimerRecordSources.java
+++ b/core/java/android/hardware/hdmi/HdmiTimerRecordSources.java
@@ -67,7 +67,7 @@
     private HdmiTimerRecordSources() {}
 
     /**
-     * Create {@link TimerRecordSource} for digital source which is used for &lt;Set Digital
+     * Creates {@link TimerRecordSource} for digital source which is used for &lt;Set Digital
      * Timer&gt;.
      *
      * @param timerInfo timer info used for timer recording
@@ -82,7 +82,7 @@
     }
 
     /**
-     * Create {@link TimerRecordSource} for analogue source which is used for &lt;Set Analogue
+     * Creates {@link TimerRecordSource} for analogue source which is used for &lt;Set Analogue
      * Timer&gt;.
      *
      * @param timerInfo timer info used for timer recording
@@ -97,7 +97,7 @@
     }
 
     /**
-     * Create {@link TimerRecordSource} for external plug which is used for &lt;Set External
+     * Creates {@link TimerRecordSource} for external plug which is used for &lt;Set External
      * Timer&gt;.
      *
      * @param timerInfo timer info used for timer recording
@@ -112,7 +112,7 @@
     }
 
     /**
-     * Create {@link TimerRecordSource} for external physical address which is used for &lt;Set
+     * Creates {@link TimerRecordSource} for external physical address which is used for &lt;Set
      * External Timer&gt;.
      *
      * @param timerInfo timer info used for timer recording
@@ -140,7 +140,7 @@
     }
 
     /**
-     * Create {@link Duration} for time value.
+     * Creates {@link Duration} for time value.
      *
      * @param hour hour in range of [0, 23]
      * @param minute minute in range of [0, 60]
@@ -162,7 +162,7 @@
     }
 
     /**
-     * Create {@link Duration} for duration value.
+     * Creates {@link Duration} for duration value.
      *
      * @param hour hour in range of [0, 99]
      * @param minute minute in range of [0, 59]
@@ -184,21 +184,21 @@
     }
 
     private static class TimeUnit {
-        protected final int mHour;
-        protected final int mMinute;
+        /* package */ final int mHour;
+        /* package */ final int mMinute;
 
-        protected TimeUnit(int hour, int minute) {
+        /* package */ TimeUnit(int hour, int minute) {
             mHour = hour;
             mMinute = minute;
         }
 
-        protected int toByteArray(byte[] data, int index) {
+        /* package */ int toByteArray(byte[] data, int index) {
             data[index] = toBcdByte(mHour);
             data[index + 1] = toBcdByte(mMinute);
             return 2;
         }
 
-        protected static byte toBcdByte(int value) {
+        /* package */ static byte toBcdByte(int value) {
             int digitOfTen = (value / 10) % 10;
             int digitOfOne = value % 10;
             return (byte) ((digitOfTen << 4) | digitOfOne);
@@ -247,7 +247,7 @@
             RECORDING_SEQUENCE_REPEAT_SATUREDAY);
 
     /**
-     * Create {@link TimerInfo} with the given information.
+     * Creates {@link TimerInfo} with the given information.
      *
      * @param dayOfMonth day of month
      * @param monthOfYear month of year
@@ -426,7 +426,7 @@
     }
 
     /**
-     * Check the byte array of timer record source.
+     * Checks the byte array of timer record source.
      * @param sourcetype
      * @param recordSource
      * @hide
diff --git a/core/java/android/hardware/hdmi/HdmiTvClient.java b/core/java/android/hardware/hdmi/HdmiTvClient.java
index 683d04b..dbfb4ef 100644
--- a/core/java/android/hardware/hdmi/HdmiTvClient.java
+++ b/core/java/android/hardware/hdmi/HdmiTvClient.java
@@ -22,11 +22,11 @@
 import android.os.RemoteException;
 import android.util.Log;
 
+import libcore.util.EmptyArray;
+
 import java.util.Collections;
 import java.util.List;
 
-import libcore.util.EmptyArray;
-
 /**
  * HdmiTvClient represents HDMI-CEC logical device of type TV in the Android system
  * which acts as TV/Display. It provides with methods that manage, interact with other
@@ -43,13 +43,13 @@
      */
     public static final int VENDOR_DATA_SIZE = 16;
 
-    HdmiTvClient(IHdmiControlService service) {
+    /* package */ HdmiTvClient(IHdmiControlService service) {
         super(service);
     }
 
     // Factory method for HdmiTvClient.
     // Declared package-private. Accessed by HdmiControlManager only.
-    static HdmiTvClient create(IHdmiControlService service) {
+    /* package */ static HdmiTvClient create(IHdmiControlService service) {
         return new HdmiTvClient(service);
     }
 
@@ -71,7 +71,7 @@
     }
 
     /**
-     * Select a CEC logical device to be a new active source.
+     * Selects a CEC logical device to be a new active source.
      *
      * @param logicalAddress logical address of the device to select
      * @param callback callback to get the result with
@@ -98,7 +98,7 @@
     }
 
     /**
-     * Select a HDMI port to be a new route path.
+     * Selects a HDMI port to be a new route path.
      *
      * @param portId HDMI port to select
      * @param callback callback to get the result with
@@ -128,7 +128,7 @@
     }
 
     /**
-     * Set the listener used to get informed of the input change event.
+     * Sets the listener used to get informed of the input change event.
      *
      * @param listener listener object
      */
@@ -168,7 +168,7 @@
     }
 
     /**
-     * Set system audio volume
+     * Sets system audio volume
      *
      * @param oldIndex current volume index
      * @param newIndex volume index to be set
@@ -183,7 +183,7 @@
     }
 
     /**
-     * Set system audio mute status
+     * Sets system audio mute status
      *
      * @param mute {@code true} if muted; otherwise, {@code false}
      */
@@ -196,7 +196,7 @@
     }
 
     /**
-     * Set record listener
+     * Sets record listener
      *
      * @param listener
      */
@@ -216,7 +216,7 @@
             @Override
             public byte[] getOneTouchRecordSource(int recorderAddress) {
                 HdmiRecordSources.RecordSource source =
-                        callback.getOneTouchRecordSource(recorderAddress);
+                        callback.onOneTouchRecordSourceRequested(recorderAddress);
                 if (source == null) {
                     return EmptyArray.BYTE;
                 }
@@ -244,13 +244,13 @@
     }
 
     /**
-     * Start one touch recording with the given recorder address and recorder source.
+     * Starts one touch recording with the given recorder address and recorder source.
      * <p>
      * Usage
      * <pre>
      * HdmiTvClient tvClient = ....;
      * // for own source.
-     * OwnSource ownSource = ownHdmiRecordSources.ownSource();
+     * OwnSource ownSource = HdmiRecordSources.ofOwnSource();
      * tvClient.startOneTouchRecord(recorderAddress, ownSource);
      * </pre>
      */
@@ -269,7 +269,7 @@
     }
 
     /**
-     * Stop one touch record.
+     * Stops one touch record.
      *
      * @param recorderAddress recorder address where recoding will be stopped
      */
@@ -282,7 +282,7 @@
     }
 
     /**
-     * Start timer recording with the given recoder address and recorder source.
+     * Starts timer recording with the given recoder address and recorder source.
      * <p>
      * Usage
      * <pre>
@@ -331,7 +331,7 @@
     }
 
     /**
-     * Clear timer recording with the given recorder address and recording source.
+     * Clears timer recording with the given recorder address and recording source.
      * For more details, please refer {@link #startTimerRecording(int, int, TimerRecordSource)}.
      */
     public void clearTimerRecording(int recorderAddress, int sourceType, TimerRecordSource source) {
@@ -357,7 +357,7 @@
     }
 
     /**
-     * Set {@link HdmiMhlVendorCommandListener} to get incoming MHL vendor command.
+     * Sets {@link HdmiMhlVendorCommandListener} to get incoming MHL vendor command.
      *
      * @param listener to receive incoming MHL vendor command
      */
@@ -383,7 +383,7 @@
     }
 
     /**
-     * Send MHL vendor command to the device connected to a port of the given portId.
+     * Sends MHL vendor command to the device connected to a port of the given portId.
      *
      * @param portId id of port to send MHL vendor command
      * @param offset offset in the in given data
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index 58f0fc0..4fa0593 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -21,7 +21,9 @@
 import android.os.Parcel;
 import android.system.ErrnoException;
 
+import java.io.FileDescriptor;
 import java.io.IOException;
+import java.net.DatagramSocket;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.MalformedURLException;
@@ -264,18 +266,40 @@
     }
 
     /**
+     * Binds the specified {@link DatagramSocket} to this {@code Network}. All data traffic on the
+     * socket will be sent on this {@code Network}, irrespective of any process-wide network binding
+     * set by {@link ConnectivityManager#setProcessDefaultNetwork}. The socket must not be
+     * connected.
+     */
+    public void bindSocket(DatagramSocket socket) throws IOException {
+        // Apparently, the kernel doesn't update a connected UDP socket's routing upon mark changes.
+        if (socket.isConnected()) {
+            throw new SocketException("Socket is connected");
+        }
+        // Query a property of the underlying socket to ensure that the socket's file descriptor
+        // exists, is available to bind to a network and is not closed.
+        socket.getReuseAddress();
+        bindSocketFd(socket.getFileDescriptor$());
+    }
+
+    /**
      * Binds the specified {@link Socket} to this {@code Network}. All data traffic on the socket
      * will be sent on this {@code Network}, irrespective of any process-wide network binding set by
      * {@link ConnectivityManager#setProcessDefaultNetwork}. The socket must not be connected.
      */
     public void bindSocket(Socket socket) throws IOException {
+        // Apparently, the kernel doesn't update a connected TCP socket's routing upon mark changes.
         if (socket.isConnected()) {
             throw new SocketException("Socket is connected");
         }
-        // Query a property of the underlying socket to ensure the underlying
-        // socket exists so a file descriptor is available to bind to a network.
+        // Query a property of the underlying socket to ensure that the socket's file descriptor
+        // exists, is available to bind to a network and is not closed.
         socket.getReuseAddress();
-        int err = NetworkUtils.bindSocketToNetwork(socket.getFileDescriptor$().getInt$(), netId);
+        bindSocketFd(socket.getFileDescriptor$());
+    }
+
+    private void bindSocketFd(FileDescriptor fd) throws IOException {
+        int err = NetworkUtils.bindSocketToNetwork(fd.getInt$(), netId);
         if (err != 0) {
             // bindSocketToNetwork returns negative errno.
             throw new ErrnoException("Binding socket to network " + netId, -err)
diff --git a/core/java/android/net/Proxy.java b/core/java/android/net/Proxy.java
index 6a78c29..3477b02 100644
--- a/core/java/android/net/Proxy.java
+++ b/core/java/android/net/Proxy.java
@@ -19,17 +19,10 @@
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.Context;
-import android.net.ProxyInfo;
 import android.text.TextUtils;
 import android.util.Log;
 
-
 import org.apache.http.HttpHost;
-import org.apache.http.HttpRequest;
-import org.apache.http.conn.routing.HttpRoute;
-import org.apache.http.conn.routing.HttpRoutePlanner;
-import org.apache.http.conn.scheme.SchemeRegistry;
-import org.apache.http.protocol.HttpContext;
 
 import java.net.InetSocketAddress;
 import java.net.ProxySelector;
@@ -212,6 +205,7 @@
      * is no proxy.
      * {@hide}
      */
+    // TODO: Get rid of this method. It's used only in tests.
     public static final HttpHost getPreferredHttpHost(Context context,
             String url) {
         java.net.Proxy prefProxy = getProxy(context, url);
diff --git a/core/java/android/net/ProxyInfo.java b/core/java/android/net/ProxyInfo.java
index 1534e2c..7694420 100644
--- a/core/java/android/net/ProxyInfo.java
+++ b/core/java/android/net/ProxyInfo.java
@@ -36,7 +36,13 @@
  *
  * Other HTTP stacks will need to obtain the proxy info from
  * {@link Proxy#PROXY_CHANGE_ACTION} broadcast as the extra {@link Proxy#EXTRA_PROXY_INFO}.
+ *
+ * @deprecated Please use {@link java.net.URL#openConnection}, {@link java.net.Proxy} and
+ *     friends. The Apache HTTP client is no longer maintained and may be removed in a future
+ *     release. Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
+ *     for further details.
  */
+@Deprecated
 public class ProxyInfo implements Parcelable {
 
     private String mHost;
diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java
index b0278d3..c15e6e5 100644
--- a/core/java/android/net/SSLCertificateSocketFactory.java
+++ b/core/java/android/net/SSLCertificateSocketFactory.java
@@ -154,7 +154,13 @@
      *         for none.  The socket timeout is reset to 0 after the handshake.
      * @param cache The {@link SSLSessionCache} to use, or null for no cache.
      * @return a new SocketFactory with the specified parameters
+     *
+     * @deprecated Use {@link #getDefault()} along with a {@link javax.net.ssl.HttpsURLConnection}
+     *     instead. The Apache HTTP client is no longer maintained and may be removed in a future
+     *     release. Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
+     *     for further details.
      */
+    @Deprecated
     public static org.apache.http.conn.ssl.SSLSocketFactory getHttpSocketFactory(
             int handshakeTimeoutMillis, SSLSessionCache cache) {
         return new org.apache.http.conn.ssl.SSLSocketFactory(
diff --git a/core/java/android/net/http/AndroidHttpClient.java b/core/java/android/net/http/AndroidHttpClient.java
index 04f3974..a262076 100644
--- a/core/java/android/net/http/AndroidHttpClient.java
+++ b/core/java/android/net/http/AndroidHttpClient.java
@@ -74,7 +74,13 @@
  * To retain cookies, simply add a cookie store to the HttpContext:</p>
  *
  * <pre>context.setAttribute(ClientContext.COOKIE_STORE, cookieStore);</pre>
+ *
+ * @deprecated Please use {@link java.net.URLConnection} and friends instead.
+ *     The Apache HTTP client is no longer maintained and may be removed in a future
+ *     release. Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
+ *     for further details.
  */
+@Deprecated
 public final class AndroidHttpClient implements HttpClient {
 
     // Gzip of data shorter than this probably won't be worthwhile
@@ -108,7 +114,13 @@
      * @param userAgent to report in your HTTP requests
      * @param context to use for caching SSL sessions (may be null for no caching)
      * @return AndroidHttpClient for you to use for all your requests.
+     *
+     * @deprecated Please use {@link java.net.URLConnection} and friends instead. See
+     *     {@link android.net.SSLCertificateSocketFactory} for SSL cache support. If you'd
+     *     like to set a custom useragent, please use {@link java.net.URLConnection#setRequestProperty(String, String)}
+     *     with {@code field} set to {@code User-Agent}.
      */
+    @Deprecated
     public static AndroidHttpClient newInstance(String userAgent, Context context) {
         HttpParams params = new BasicHttpParams();
 
@@ -148,7 +160,13 @@
      * Create a new HttpClient with reasonable defaults (which you can update).
      * @param userAgent to report in your HTTP requests.
      * @return AndroidHttpClient for you to use for all your requests.
+     *
+     * @deprecated Please use {@link java.net.URLConnection} and friends instead. See
+     *     {@link android.net.SSLCertificateSocketFactory} for SSL cache support. If you'd
+     *     like to set a custom useragent, please use {@link java.net.URLConnection#setRequestProperty(String, String)}
+     *     with {@code field} set to {@code User-Agent}.
      */
+    @Deprecated
     public static AndroidHttpClient newInstance(String userAgent) {
         return newInstance(userAgent, null /* session cache */);
     }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 75c435ea..98a1f05 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5095,6 +5095,12 @@
         public static final String AIRPLANE_MODE_ON = "airplane_mode_on";
 
         /**
+         * Whether Theater Mode is on.
+         * {@hide}
+         */
+        public static final String THEATER_MODE_ON = "theater_mode_on";
+
+        /**
          * Constant for use in AIRPLANE_MODE_RADIOS to specify Bluetooth radio.
          */
         public static final String RADIO_BLUETOOTH = "bluetooth";
@@ -6593,7 +6599,7 @@
          * Type: int (0 for false, 1 for true)
          * @hide
          */
-        public static final String VOLTE_VT_ENABLED = "volte_vt_enabled";
+        public static final String ENHANCED_4G_MODE_ENABLED = "volte_vt_enabled";
 
         /**
          * Settings to backup. This is here so that it's in the same place as the settings
diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java
index aa6ad20..1e04eb4 100644
--- a/core/java/android/text/format/Time.java
+++ b/core/java/android/text/format/Time.java
@@ -48,7 +48,10 @@
  *     <li>Much of the formatting / parsing assumes ASCII text and is therefore not suitable for
  *     use with non-ASCII scripts.</li>
  * </ul>
+ *
+ * @deprecated Use {@link java.util.GregorianCalendar} instead.
  */
+@Deprecated
 public class Time {
     private static final String Y_M_D_T_H_M_S_000 = "%Y-%m-%dT%H:%M:%S.000";
     private static final String Y_M_D_T_H_M_S_000_Z = "%Y-%m-%dT%H:%M:%S.000Z";
diff --git a/core/java/android/transition/ChangeBounds.java b/core/java/android/transition/ChangeBounds.java
index 0da5fb6..2c55141 100644
--- a/core/java/android/transition/ChangeBounds.java
+++ b/core/java/android/transition/ChangeBounds.java
@@ -16,6 +16,7 @@
 
 package android.transition;
 
+import android.animation.AnimatorSet;
 import android.content.Context;
 import android.graphics.PointF;
 
@@ -31,7 +32,6 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
-import android.util.IntProperty;
 import android.util.Property;
 import android.view.View;
 import android.view.ViewGroup;
@@ -77,6 +77,32 @@
                 }
     };
 
+    private static final Property<ViewBounds, PointF> TOP_LEFT_PROPERTY =
+            new Property<ViewBounds, PointF>(PointF.class, "topLeft") {
+                @Override
+                public void set(ViewBounds viewBounds, PointF topLeft) {
+                    viewBounds.setTopLeft(topLeft);
+                }
+
+                @Override
+                public PointF get(ViewBounds viewBounds) {
+                    return null;
+                }
+            };
+
+    private static final Property<ViewBounds, PointF> BOTTOM_RIGHT_PROPERTY =
+            new Property<ViewBounds, PointF>(PointF.class, "bottomRight") {
+                @Override
+                public void set(ViewBounds viewBounds, PointF bottomRight) {
+                    viewBounds.setBottomRight(bottomRight);
+                }
+
+                @Override
+                public PointF get(ViewBounds viewBounds) {
+                    return null;
+                }
+            };
+
     int[] tempLocation = new int[2];
     boolean mResizeClip = false;
     boolean mReparent = false;
@@ -189,36 +215,20 @@
             }
             if (numChanges > 0) {
                 if (!mResizeClip) {
-                    Animator anim;
-                    if (startWidth == endWidth && startHeight == endHeight) {
-                        view.offsetLeftAndRight(startLeft - view.getLeft());
-                        view.offsetTopAndBottom(startTop - view.getTop());
-                        Path positionPath = getPathMotion().getPath(0, 0, endLeft - startLeft,
-                                endTop - startTop);
-                        anim = ObjectAnimator.ofInt(view, new HorizontalOffsetProperty(),
-                                new VerticalOffsetProperty(), positionPath);
-                    } else {
-                        if (startLeft != endLeft) view.setLeft(startLeft);
-                        if (startTop != endTop) view.setTop(startTop);
-                        if (startRight != endRight) view.setRight(startRight);
-                        if (startBottom != endBottom) view.setBottom(startBottom);
-                        ObjectAnimator topLeftAnimator = null;
-                        if (startLeft != endLeft || startTop != endTop) {
-                            Path topLeftPath = getPathMotion().getPath(startLeft, startTop,
-                                    endLeft, endTop);
-                            topLeftAnimator = ObjectAnimator
-                                    .ofInt(view, "left", "top", topLeftPath);
-                        }
-                        ObjectAnimator bottomRightAnimator = null;
-                        if (startRight != endRight || startBottom != endBottom) {
-                            Path bottomRightPath = getPathMotion().getPath(startRight, startBottom,
-                                    endRight, endBottom);
-                            bottomRightAnimator = ObjectAnimator.ofInt(view, "right", "bottom",
-                                    bottomRightPath);
-                        }
-                        anim = TransitionUtils.mergeAnimators(topLeftAnimator,
-                                bottomRightAnimator);
-                    }
+                    view.setLeftTopRightBottom(startLeft, startTop, startRight, startBottom);
+                    ViewBounds viewBounds = new ViewBounds(view);
+                    Path topLeftPath = getPathMotion().getPath(startLeft, startTop,
+                            endLeft, endTop);
+                    ObjectAnimator topLeftAnimator = ObjectAnimator
+                            .ofObject(viewBounds, TOP_LEFT_PROPERTY, null, topLeftPath);
+
+                    Path bottomRightPath = getPathMotion().getPath(startRight, startBottom,
+                            endRight, endBottom);
+                    ObjectAnimator bottomRightAnimator = ObjectAnimator.ofObject(viewBounds,
+                            BOTTOM_RIGHT_PROPERTY, null, bottomRightPath);
+                    AnimatorSet anim = new AnimatorSet();
+                    anim.playTogether(topLeftAnimator, bottomRightAnimator);
+
                     if (view.getParent() instanceof ViewGroup) {
                         final ViewGroup parent = (ViewGroup) view.getParent();
                         parent.suppressLayout(true);
@@ -357,47 +367,41 @@
         return null;
     }
 
-    private abstract static class OffsetProperty extends IntProperty<View> {
-        int mPreviousValue;
+    private static class ViewBounds {
+        private int mLeft;
+        private int mTop;
+        private int mRight;
+        private int mBottom;
+        private boolean mIsTopLeftSet;
+        private boolean mIsBottomRightSet;
+        private View mView;
 
-        public OffsetProperty(String name) {
-            super(name);
+        public ViewBounds(View view) {
+            mView = view;
         }
 
-        @Override
-        public void setValue(View view, int value) {
-            int offset = value - mPreviousValue;
-            offsetBy(view, offset);
-            mPreviousValue = value;
+        public void setTopLeft(PointF topLeft) {
+            mLeft = Math.round(topLeft.x);
+            mTop = Math.round(topLeft.y);
+            mIsTopLeftSet = true;
+            if (mIsBottomRightSet) {
+                setLeftTopRightBottom();
+            }
         }
 
-        @Override
-        public Integer get(View object) {
-            return null;
+        public void setBottomRight(PointF bottomRight) {
+            mRight = Math.round(bottomRight.x);
+            mBottom = Math.round(bottomRight.y);
+            mIsBottomRightSet = true;
+            if (mIsTopLeftSet) {
+                setLeftTopRightBottom();
+            }
         }
 
-        protected abstract void offsetBy(View view, int by);
-    }
-
-    private static class HorizontalOffsetProperty extends OffsetProperty {
-        public HorizontalOffsetProperty() {
-            super("offsetLeftAndRight");
-        }
-
-        @Override
-        protected void offsetBy(View view, int by) {
-            view.offsetLeftAndRight(by);
-        }
-    }
-
-    private static class VerticalOffsetProperty extends OffsetProperty {
-        public VerticalOffsetProperty() {
-            super("offsetTopAndBottom");
-        }
-
-        @Override
-        protected void offsetBy(View view, int by) {
-            view.offsetTopAndBottom(by);
+        private void setLeftTopRightBottom() {
+            mView.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
+            mIsTopLeftSet = false;
+            mIsBottomRightSet = false;
         }
     }
 }
diff --git a/core/java/android/util/FloatMath.java b/core/java/android/util/FloatMath.java
index 0ffd5bd..bdcf5ca 100644
--- a/core/java/android/util/FloatMath.java
+++ b/core/java/android/util/FloatMath.java
@@ -21,7 +21,10 @@
  * versions of Android with a JIT, these are significantly slower than
  * the equivalent {@code Math} functions, which should be used in preference
  * to these.
+ *
+ * @deprecated Use {@link java.lang.Math} instead.
  */
+@Deprecated
 public class FloatMath {
 
     /** Prevents instantiation. */
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 132e25c..562d138 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -311,7 +311,10 @@
      * Unlike {@link #lockCanvas(Rect)} this will return a hardware-accelerated
      * canvas. See the <a href="{@docRoot}guide/topics/graphics/hardware-accel.html#unsupported">
      * unsupported drawing operations</a> for a list of what is and isn't
-     * supported in a hardware-accelerated canvas.
+     * supported in a hardware-accelerated canvas. It is also required to
+     * fully cover the surface every time {@link #lockHardwareCanvas()} is
+     * called as the buffer is not preserved between frames. Partial updates
+     * are not supported.
      *
      * @return A canvas for drawing into the surface.
      *
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 8e58cd6..8664a24 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -15699,6 +15699,14 @@
         return changed;
     }
 
+    /**
+     * Same as setFrame, but public and hidden. For use in {@link android.transition.ChangeBounds}.
+     * @hide
+     */
+    public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
+        setFrame(left, top, right, bottom);
+    }
+
     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
         if (mOverlay != null) {
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 63ab7d2..ef073b5 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -24,7 +24,6 @@
 import android.graphics.PixelFormat;
 import android.graphics.drawable.Drawable;
 import android.media.session.MediaController;
-import android.media.session.MediaSession;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -801,9 +800,6 @@
     public void setFlags(int flags, int mask) {
         final WindowManager.LayoutParams attrs = getAttributes();
         attrs.flags = (attrs.flags&~mask) | (flags&mask);
-        if ((mask&WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0) {
-            attrs.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY;
-        }
         mForcedWindowFlags |= mask;
         dispatchWindowAttributesChanged(attrs);
     }
@@ -817,6 +813,15 @@
     /**
      * {@hide}
      */
+    protected void setNeedsMenuKey(int value) {
+        final WindowManager.LayoutParams attrs = getAttributes();
+        attrs.needsMenuKey = value;
+        dispatchWindowAttributesChanged(attrs);
+    }
+
+    /**
+     * {@hide}
+     */
     protected void dispatchWindowAttributesChanged(WindowManager.LayoutParams attrs) {
         if (mCallback != null) {
             mCallback.onWindowAttributesChanged(attrs);
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 75c9ebd..5b48c0d 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -542,6 +542,19 @@
         public static final int TYPE_VOICE_INTERACTION = FIRST_SYSTEM_WINDOW+31;
 
         /**
+         * Window type: Windows that are overlaid <em>only</em> by an {@link
+         * android.accessibilityservice.AccessibilityService} for interception of
+         * user interactions without changing the windows an accessibility service
+         * can introspect. In particular, an accessibility service can introspect
+         * only windows that a sighted user can interact with which is they can touch
+         * these windows or can type into these windows. For example, if there
+         * is a full screen accessibility overlay that is touchable, the windows
+         * below it will be introspectable by an accessibility service regardless
+         * they are covered by a touchable window.
+         */
+        public static final int TYPE_ACCESSIBILITY_OVERLAY = FIRST_SYSTEM_WINDOW+32;
+
+        /**
          * End of types of system windows.
          */
         public static final int LAST_SYSTEM_WINDOW      = 2999;
@@ -878,9 +891,6 @@
          */
         public static final int FLAG_TRANSLUCENT_NAVIGATION = 0x08000000;
 
-        // ----- HIDDEN FLAGS.
-        // These start at the high bit and go down.
-
         /**
          * Flag for a window in local focus mode.
          * Window in local focus mode can control focus independent of window manager using
@@ -903,17 +913,12 @@
         public static final int FLAG_SLIPPERY = 0x20000000;
 
         /**
-         * Flag for a window belonging to an activity that responds to {@link KeyEvent#KEYCODE_MENU}
-         * and therefore needs a Menu key. For devices where Menu is a physical button this flag is
-         * ignored, but on devices where the Menu key is drawn in software it may be hidden unless
-         * this flag is set.
-         *
-         * (Note that Action Bars, when available, are the preferred way to offer additional
-         * functions otherwise accessed via an options menu.)
-         *
-         * {@hide}
+         * Window flag: When requesting layout with an attached window, the attached window may
+         * overlap with the screen decorations of the parent window such as the navigation bar. By
+         * including this flag, the window manager will layout the attached window within the decor
+         * frame of the parent window such that it doesn't overlap with screen decorations.
          */
-        public static final int FLAG_NEEDS_MENU_KEY = 0x40000000;
+        public static final int FLAG_LAYOUT_ATTACHED_IN_DECOR = 0x40000000;
 
         /**
          * Flag indicating that this Window is responsible for drawing the background for the
@@ -1056,16 +1061,6 @@
          */
         public static final int PRIVATE_FLAG_WANTS_OFFSET_NOTIFICATIONS = 0x00000004;
 
-        /**
-         * This is set for a window that has explicitly specified its
-         * FLAG_NEEDS_MENU_KEY, so we know the value on this window is the
-         * appropriate one to use.  If this is not set, we should look at
-         * windows behind it to determine the appropriate value.
-         *
-         * @hide
-         */
-        public static final int PRIVATE_FLAG_SET_NEEDS_MENU_KEY = 0x00000008;
-
         /** In a multiuser system if this flag is set and the owner is a system process then this
          * window will appear on all user screens. This overrides the default behavior of window
          * types that normally only appear on the owning user's screen. Refer to each window type
@@ -1113,6 +1108,45 @@
         public int privateFlags;
 
         /**
+         * Value for {@link #needsMenuKey} for a window that has not explicitly specified if it
+         * needs {@link #NEEDS_MENU_SET_TRUE} or doesn't need {@link #NEEDS_MENU_SET_FALSE} a menu
+         * key. For this case, we should look at windows behind it to determine the appropriate
+         * value.
+         *
+         * @hide
+         */
+        public static final int NEEDS_MENU_UNSET = 0;
+
+        /**
+         * Value for {@link #needsMenuKey} for a window that has explicitly specified it needs a
+         * menu key.
+         *
+         * @hide
+         */
+        public static final int NEEDS_MENU_SET_TRUE = 1;
+
+        /**
+         * Value for {@link #needsMenuKey} for a window that has explicitly specified it doesn't
+         * needs a menu key.
+         *
+         * @hide
+         */
+        public static final int NEEDS_MENU_SET_FALSE = 2;
+
+        /**
+         * State variable for a window belonging to an activity that responds to
+         * {@link KeyEvent#KEYCODE_MENU} and therefore needs a Menu key. For devices where Menu is a
+         * physical button this variable is ignored, but on devices where the Menu key is drawn in
+         * software it may be hidden unless this variable is set to {@link #NEEDS_MENU_SET_TRUE}.
+         *
+         *  (Note that Action Bars, when available, are the preferred way to offer additional
+         * functions otherwise accessed via an options menu.)
+         *
+         * {@hide}
+         */
+        public int needsMenuKey = NEEDS_MENU_UNSET;
+
+        /**
          * Given a particular set of window manager flags, determine whether
          * such a window may be a target for an input method when it has
          * focus.  In particular, this checks the
@@ -1120,9 +1154,9 @@
          * flags and returns true if the combination of the two corresponds
          * to a window that needs to be behind the input method so that the
          * user can type into it.
-         * 
+         *
          * @param flags The current window manager flags.
-         * 
+         *
          * @return Returns true if such a window should be behind/interact
          * with an input method, false if not.
          */
@@ -1587,14 +1621,15 @@
             out.writeInt(surfaceInsets.top);
             out.writeInt(surfaceInsets.right);
             out.writeInt(surfaceInsets.bottom);
+            out.writeInt(needsMenuKey);
         }
-        
+
         public static final Parcelable.Creator<LayoutParams> CREATOR
                     = new Parcelable.Creator<LayoutParams>() {
             public LayoutParams createFromParcel(Parcel in) {
                 return new LayoutParams(in);
             }
-    
+
             public LayoutParams[] newArray(int size) {
                 return new LayoutParams[size];
             }
@@ -1634,8 +1669,9 @@
             surfaceInsets.top = in.readInt();
             surfaceInsets.right = in.readInt();
             surfaceInsets.bottom = in.readInt();
+            needsMenuKey = in.readInt();
         }
-    
+
         @SuppressWarnings({"PointlessBitwiseExpression"})
         public static final int LAYOUT_CHANGED = 1<<0;
         public static final int TYPE_CHANGED = 1<<1;
@@ -1669,14 +1705,16 @@
         /** {@hide} */
         public static final int PREFERRED_REFRESH_RATE_CHANGED = 1 << 21;
         /** {@hide} */
+        public static final int NEEDS_MENU_KEY_CHANGED = 1 << 22;
+        /** {@hide} */
         public static final int EVERYTHING_CHANGED = 0xffffffff;
 
         // internal buffer to backup/restore parameters under compatibility mode.
         private int[] mCompatibilityParamsBackup = null;
-        
+
         public final int copyFrom(LayoutParams o) {
             int changes = 0;
-    
+
             if (width != o.width) {
                 width = o.width;
                 changes |= LAYOUT_CHANGED;
@@ -1813,9 +1851,14 @@
                 changes |= SURFACE_INSETS_CHANGED;
             }
 
+            if (needsMenuKey != o.needsMenuKey) {
+                needsMenuKey = o.needsMenuKey;
+                changes |= NEEDS_MENU_KEY_CHANGED;
+            }
+
             return changes;
         }
-    
+
         @Override
         public String debug(String output) {
             output += "Contents of " + this + ":";
@@ -1919,6 +1962,10 @@
             if (!surfaceInsets.equals(Insets.NONE)) {
                 sb.append(" surfaceInsets=").append(surfaceInsets);
             }
+            if (needsMenuKey != NEEDS_MENU_UNSET) {
+                sb.append(" needsMenuKey=");
+                sb.append(needsMenuKey);
+            }
             sb.append('}');
             return sb.toString();
         }
diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java
index 38e3723..f557b97 100644
--- a/core/java/android/view/WindowManagerInternal.java
+++ b/core/java/android/view/WindowManagerInternal.java
@@ -173,4 +173,20 @@
      * redrawn.
      */
     public abstract void waitForAllWindowsDrawn(Runnable callback, long timeout);
+
+    /**
+     * Adds a window token for a given window type.
+     *
+     * @param token The token to add.
+     * @param type The window type.
+     */
+    public abstract void addWindowToken(android.os.IBinder token, int type);
+
+    /**
+     * Removes a window token.
+     *
+     * @param token The toke to remove.
+     * @param removeWindows Whether to also remove the windows associated with the token.
+     */
+    public abstract void removeWindowToken(android.os.IBinder token, boolean removeWindows);
 }
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index ad55f5f..e1942be 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -51,11 +51,24 @@
      */
     public static final int TYPE_SYSTEM = 3;
 
+    /**
+     * Window type: Windows that are overlaid <em>only</em> by an {@link
+     * android.accessibilityservice.AccessibilityService} for interception of
+     * user interactions without changing the windows an accessibility service
+     * can introspect. In particular, an accessibility service can introspect
+     * only windows that a sighted user can interact with which they can touch
+     * these windows or can type into these windows. For example, if there
+     * is a full screen accessibility overlay that is touchable, the windows
+     * below it will be introspectable by an accessibility service regardless
+     * they are covered by a touchable window.
+     */
+    public static final int TYPE_ACCESSIBILITY_OVERLAY = 4;
+
     private static final int UNDEFINED = -1;
 
     private static final int BOOLEAN_PROPERTY_ACTIVE = 1 << 0;
     private static final int BOOLEAN_PROPERTY_FOCUSED = 1 << 1;
-    private static final int BOOLEAN_PROPERTY_ACCESSIBLITY_FOCUSED = 1 << 2;
+    private static final int BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED = 1 << 2;
 
     // Housekeeping.
     private static final int MAX_POOL_SIZE = 10;
@@ -85,6 +98,7 @@
      * @see #TYPE_APPLICATION
      * @see #TYPE_INPUT_METHOD
      * @see #TYPE_SYSTEM
+     * @see #TYPE_ACCESSIBILITY_OVERLAY
      */
     public int getType() {
         return mType;
@@ -93,7 +107,7 @@
     /**
      * Sets the type of the window.
      *
-     * @param The type
+     * @param type The type
      *
      * @hide
      */
@@ -115,7 +129,7 @@
      * Sets the layer which determines the Z-order of the window. Windows
      * with greater layer appear on top of windows with lesser layer.
      *
-     * @param The window layer.
+     * @param layer The window layer.
      *
      * @hide
      */
@@ -174,7 +188,7 @@
     /**
      * Sets the unique window id.
      *
-     * @param windowId The window id.
+     * @param id The window id.
      *
      * @hide
      */
@@ -230,7 +244,7 @@
      * the user is currently touching or the window has input focus
      * and the user is not touching any window.
      *
-     * @param Whether this is the active window.
+     * @param active Whether this is the active window.
      *
      * @hide
      */
@@ -250,7 +264,7 @@
     /**
      * Sets if this window has input focus.
      *
-     * @param Whether has input focus.
+     * @param focused Whether has input focus.
      *
      * @hide
      */
@@ -264,18 +278,18 @@
      * @return Whether has accessibility focus.
      */
     public boolean isAccessibilityFocused() {
-        return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBLITY_FOCUSED);
+        return getBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED);
     }
 
     /**
      * Sets if this window has accessibility focus.
      *
-     * @param Whether has accessibility focus.
+     * @param focused Whether has accessibility focus.
      *
      * @hide
      */
     public void setAccessibilityFocused(boolean focused) {
-        setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBLITY_FOCUSED, focused);
+        setBooleanProperty(BOOLEAN_PROPERTY_ACCESSIBILITY_FOCUSED, focused);
     }
 
     /**
@@ -534,6 +548,9 @@
             case TYPE_SYSTEM: {
                 return "TYPE_SYSTEM";
             }
+            case TYPE_ACCESSIBILITY_OVERLAY: {
+                return "TYPE_ACCESSIBILITY_OVERLAY";
+            }
             default:
                 return "<UNKNOWN>";
         }
diff --git a/core/java/android/view/animation/AccelerateDecelerateInterpolator.java b/core/java/android/view/animation/AccelerateDecelerateInterpolator.java
index ed6949a..21d5a5b 100644
--- a/core/java/android/view/animation/AccelerateDecelerateInterpolator.java
+++ b/core/java/android/view/animation/AccelerateDecelerateInterpolator.java
@@ -26,17 +26,17 @@
 /**
  * An interpolator where the rate of change starts and ends slowly but
  * accelerates through the middle.
- * 
  */
 @HasNativeInterpolator
-public class AccelerateDecelerateInterpolator implements Interpolator, NativeInterpolatorFactory {
+public class AccelerateDecelerateInterpolator extends BaseInterpolator
+        implements NativeInterpolatorFactory {
     public AccelerateDecelerateInterpolator() {
     }
-    
+
     @SuppressWarnings({"UnusedDeclaration"})
     public AccelerateDecelerateInterpolator(Context context, AttributeSet attrs) {
     }
-    
+
     public float getInterpolation(float input) {
         return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
     }
diff --git a/core/java/android/view/animation/AccelerateInterpolator.java b/core/java/android/view/animation/AccelerateInterpolator.java
index 1c75f16..6c8d7b1 100644
--- a/core/java/android/view/animation/AccelerateInterpolator.java
+++ b/core/java/android/view/animation/AccelerateInterpolator.java
@@ -33,7 +33,7 @@
  *
  */
 @HasNativeInterpolator
-public class AccelerateInterpolator implements Interpolator, NativeInterpolatorFactory {
+public class AccelerateInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
     private final float mFactor;
     private final double mDoubleFactor;
 
@@ -70,7 +70,7 @@
 
         mFactor = a.getFloat(R.styleable.AccelerateInterpolator_factor, 1.0f);
         mDoubleFactor = 2 * mFactor;
-
+        setChangingConfiguration(a.getChangingConfigurations());
         a.recycle();
     }
 
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index af4e04f..606c83e 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -321,7 +321,7 @@
     private static Interpolator createInterpolatorFromXml(Resources res, Theme theme, XmlPullParser parser)
             throws XmlPullParserException, IOException {
 
-        Interpolator interpolator = null;
+        BaseInterpolator interpolator = null;
 
         // Make sure we are on a start tag.
         int type;
@@ -361,10 +361,7 @@
             } else {
                 throw new RuntimeException("Unknown interpolator name: " + parser.getName());
             }
-
         }
-
         return interpolator;
-
     }
 }
diff --git a/core/java/android/view/animation/AnticipateInterpolator.java b/core/java/android/view/animation/AnticipateInterpolator.java
index fe756bd..fb66c31 100644
--- a/core/java/android/view/animation/AnticipateInterpolator.java
+++ b/core/java/android/view/animation/AnticipateInterpolator.java
@@ -31,7 +31,7 @@
  * An interpolator where the change starts backward then flings forward.
  */
 @HasNativeInterpolator
-public class AnticipateInterpolator implements Interpolator, NativeInterpolatorFactory {
+public class AnticipateInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
     private final float mTension;
 
     public AnticipateInterpolator() {
@@ -60,9 +60,8 @@
             a = res.obtainAttributes(attrs, R.styleable.AnticipateInterpolator);
         }
 
-        mTension =
-                a.getFloat(R.styleable.AnticipateInterpolator_tension, 2.0f);
-
+        mTension = a.getFloat(R.styleable.AnticipateInterpolator_tension, 2.0f);
+        setChangingConfiguration(a.getChangingConfigurations());
         a.recycle();
     }
 
diff --git a/core/java/android/view/animation/AnticipateOvershootInterpolator.java b/core/java/android/view/animation/AnticipateOvershootInterpolator.java
index 78e5acf..1af72da 100644
--- a/core/java/android/view/animation/AnticipateOvershootInterpolator.java
+++ b/core/java/android/view/animation/AnticipateOvershootInterpolator.java
@@ -35,7 +35,8 @@
  * the target value and finally goes back to the final value.
  */
 @HasNativeInterpolator
-public class AnticipateOvershootInterpolator implements Interpolator, NativeInterpolatorFactory {
+public class AnticipateOvershootInterpolator extends BaseInterpolator
+        implements NativeInterpolatorFactory {
     private final float mTension;
 
     public AnticipateOvershootInterpolator() {
@@ -78,7 +79,7 @@
 
         mTension = a.getFloat(AnticipateOvershootInterpolator_tension, 2.0f) *
                 a.getFloat(AnticipateOvershootInterpolator_extraTension, 1.5f);
-
+        setChangingConfiguration(a.getChangingConfigurations());
         a.recycle();
     }
 
diff --git a/core/java/android/view/animation/BaseInterpolator.java b/core/java/android/view/animation/BaseInterpolator.java
new file mode 100644
index 0000000..9c0014c
--- /dev/null
+++ b/core/java/android/view/animation/BaseInterpolator.java
@@ -0,0 +1,37 @@
+/*
+ * 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.view.animation;
+
+/**
+ * An abstract class which is extended by default interpolators.
+ */
+abstract public class BaseInterpolator implements Interpolator {
+    private int mChangingConfiguration;
+    /**
+     * @hide
+     */
+    public int getChangingConfiguration() {
+        return mChangingConfiguration;
+    }
+
+    /**
+     * @hide
+     */
+    void setChangingConfiguration(int changingConfiguration) {
+        mChangingConfiguration = changingConfiguration;
+    }
+}
diff --git a/core/java/android/view/animation/BounceInterpolator.java b/core/java/android/view/animation/BounceInterpolator.java
index 9d8ca90..909eaa4 100644
--- a/core/java/android/view/animation/BounceInterpolator.java
+++ b/core/java/android/view/animation/BounceInterpolator.java
@@ -27,7 +27,7 @@
  * An interpolator where the change bounces at the end.
  */
 @HasNativeInterpolator
-public class BounceInterpolator implements Interpolator, NativeInterpolatorFactory {
+public class BounceInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
     public BounceInterpolator() {
     }
 
diff --git a/core/java/android/view/animation/CycleInterpolator.java b/core/java/android/view/animation/CycleInterpolator.java
index 3114aa3..663c109 100644
--- a/core/java/android/view/animation/CycleInterpolator.java
+++ b/core/java/android/view/animation/CycleInterpolator.java
@@ -33,7 +33,7 @@
  *
  */
 @HasNativeInterpolator
-public class CycleInterpolator implements Interpolator, NativeInterpolatorFactory {
+public class CycleInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
     public CycleInterpolator(float cycles) {
         mCycles = cycles;
     }
@@ -52,7 +52,7 @@
         }
 
         mCycles = a.getFloat(R.styleable.CycleInterpolator_cycles, 1.0f);
-
+        setChangingConfiguration(a.getChangingConfigurations());
         a.recycle();
     }
 
diff --git a/core/java/android/view/animation/DecelerateInterpolator.java b/core/java/android/view/animation/DecelerateInterpolator.java
index 674207c..f426f60 100644
--- a/core/java/android/view/animation/DecelerateInterpolator.java
+++ b/core/java/android/view/animation/DecelerateInterpolator.java
@@ -33,7 +33,7 @@
  *
  */
 @HasNativeInterpolator
-public class DecelerateInterpolator implements Interpolator, NativeInterpolatorFactory {
+public class DecelerateInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
     public DecelerateInterpolator() {
     }
 
@@ -62,7 +62,7 @@
         }
 
         mFactor = a.getFloat(R.styleable.DecelerateInterpolator_factor, 1.0f);
-
+        setChangingConfiguration(a.getChangingConfigurations());
         a.recycle();
     }
 
diff --git a/core/java/android/view/animation/LinearInterpolator.java b/core/java/android/view/animation/LinearInterpolator.java
index 552c611..2a047b4 100644
--- a/core/java/android/view/animation/LinearInterpolator.java
+++ b/core/java/android/view/animation/LinearInterpolator.java
@@ -25,17 +25,16 @@
 
 /**
  * An interpolator where the rate of change is constant
- *
  */
 @HasNativeInterpolator
-public class LinearInterpolator implements Interpolator, NativeInterpolatorFactory {
+public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
 
     public LinearInterpolator() {
     }
-    
+
     public LinearInterpolator(Context context, AttributeSet attrs) {
     }
-    
+
     public float getInterpolation(float input) {
         return input;
     }
diff --git a/core/java/android/view/animation/OvershootInterpolator.java b/core/java/android/view/animation/OvershootInterpolator.java
index d6c2808..306688a 100644
--- a/core/java/android/view/animation/OvershootInterpolator.java
+++ b/core/java/android/view/animation/OvershootInterpolator.java
@@ -32,7 +32,7 @@
  * then comes back.
  */
 @HasNativeInterpolator
-public class OvershootInterpolator implements Interpolator, NativeInterpolatorFactory {
+public class OvershootInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
     private final float mTension;
 
     public OvershootInterpolator() {
@@ -61,9 +61,8 @@
             a = res.obtainAttributes(attrs, R.styleable.OvershootInterpolator);
         }
 
-        mTension =
-                a.getFloat(R.styleable.OvershootInterpolator_tension, 2.0f);
-
+        mTension = a.getFloat(R.styleable.OvershootInterpolator_tension, 2.0f);
+        setChangingConfiguration(a.getChangingConfigurations());
         a.recycle();
     }
 
diff --git a/core/java/android/view/animation/PathInterpolator.java b/core/java/android/view/animation/PathInterpolator.java
index 945ecf0..eec5555 100644
--- a/core/java/android/view/animation/PathInterpolator.java
+++ b/core/java/android/view/animation/PathInterpolator.java
@@ -42,7 +42,7 @@
  *     path.lineTo(1f, 1f);
  * </pre></blockquote></p>
  */
-public class PathInterpolator implements Interpolator {
+public class PathInterpolator extends BaseInterpolator {
 
     // This governs how accurate the approximation of the Path is.
     private static final float PRECISION = 0.002f;
@@ -98,7 +98,7 @@
             a = res.obtainAttributes(attrs, R.styleable.PathInterpolator);
         }
         parseInterpolatorFromTypeArray(a);
-
+        setChangingConfiguration(a.getChangingConfigurations());
         a.recycle();
     }
 
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 0439168..4aebaae 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -4653,7 +4653,7 @@
         if (mPositionScroller == null) {
             mPositionScroller = createPositionScroller();
         }
-        mPositionScroller.startWithOffset(position, offset, offset);
+        mPositionScroller.startWithOffset(position, offset);
     }
 
     /**
diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java
index b9f891c..5fa6e60 100644
--- a/core/java/android/widget/AdapterView.java
+++ b/core/java/android/widget/AdapterView.java
@@ -215,7 +215,12 @@
     private boolean mDesiredFocusableState;
     private boolean mDesiredFocusableInTouchModeState;
 
+    /** Lazily-constructed runnable for dispatching selection events. */
     private SelectionNotifier mSelectionNotifier;
+
+    /** Selection notifier that's waiting for the next layout pass. */
+    private SelectionNotifier mPendingSelectionNotifier;
+
     /**
      * When set to true, calls to requestLayout() will not propagate up the parent hierarchy.
      * This is used to layout the children during a layout pass.
@@ -854,39 +859,50 @@
 
     private class SelectionNotifier implements Runnable {
         public void run() {
+            mPendingSelectionNotifier = null;
+
             if (mDataChanged) {
-                // Data has changed between when this SelectionNotifier
-                // was posted and now. We need to wait until the AdapterView
-                // has been synched to the new data.
+                // Data has changed between when this SelectionNotifier was
+                // posted and now. Postpone the notification until the next
+                // layout is complete and we run checkSelectionChanged().
                 if (getAdapter() != null) {
-                    post(this);
+                    mPendingSelectionNotifier = this;
                 }
             } else {
-                fireOnSelected();
-                performAccessibilityActionsOnSelected();
+                dispatchOnItemSelected();
             }
         }
     }
 
     void selectionChanged() {
+        // We're about to post or run the selection notifier, so we don't need
+        // a pending notifier.
+        mPendingSelectionNotifier = null;
+
         if (mOnItemSelectedListener != null
                 || AccessibilityManager.getInstance(mContext).isEnabled()) {
             if (mInLayout || mBlockLayoutRequests) {
                 // If we are in a layout traversal, defer notification
                 // by posting. This ensures that the view tree is
-                // in a consistent state and is able to accomodate
+                // in a consistent state and is able to accommodate
                 // new layout or invalidate requests.
                 if (mSelectionNotifier == null) {
                     mSelectionNotifier = new SelectionNotifier();
+                } else {
+                    removeCallbacks(mSelectionNotifier);
                 }
                 post(mSelectionNotifier);
             } else {
-                fireOnSelected();
-                performAccessibilityActionsOnSelected();
+                dispatchOnItemSelected();
             }
         }
     }
 
+    private void dispatchOnItemSelected() {
+        fireOnSelected();
+        performAccessibilityActionsOnSelected();
+    }
+
     private void fireOnSelected() {
         if (mOnItemSelectedListener == null) {
             return;
@@ -1042,12 +1058,22 @@
         notifySubtreeAccessibilityStateChangedIfNeeded();
     }
 
+    /**
+     * Called after layout to determine whether the selection position needs to
+     * be updated. Also used to fire any pending selection events.
+     */
     void checkSelectionChanged() {
         if ((mSelectedPosition != mOldSelectedPosition) || (mSelectedRowId != mOldSelectedRowId)) {
             selectionChanged();
             mOldSelectedPosition = mSelectedPosition;
             mOldSelectedRowId = mSelectedRowId;
         }
+
+        // If we have a pending selection notification -- and we won't if we
+        // just fired one in selectionChanged() -- run it now.
+        if (mPendingSelectionNotifier != null) {
+            mPendingSelectionNotifier.run();
+        }
     }
 
     /**
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index f90a9fe..75dfcca 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -1120,6 +1120,9 @@
 
     /** @hide */
     public void animateTransform(Matrix matrix) {
+        if (mDrawable == null) {
+            return;
+        }
         if (matrix == null) {
             mDrawable.setBounds(0, 0, getWidth(), getHeight());
         } else {
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 41d3e320..54a7940 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -97,9 +97,11 @@
     private boolean mAllowScrollingAnchorParent = true;
     private boolean mLayoutInsetDecor = false;
     private boolean mNotTouchModal;
+    private boolean mAttachedInDecor = true;
+    private boolean mAttachedInDecorSet = false;
 
     private OnTouchListener mTouchInterceptor;
-    
+
     private int mWidthMode;
     private int mWidth;
     private int mLastWidth;
@@ -316,6 +318,7 @@
             mContext = contentView.getContext();
             mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
         }
+
         setContentView(contentView);
         setWidth(width);
         setHeight(height);
@@ -373,16 +376,16 @@
     public int getAnimationStyle() {
         return mAnimationStyle;
     }
-    
+
     /**
-     * Set the flag on popup to ignore cheek press eventt; by default this flag
+     * Set the flag on popup to ignore cheek press event; by default this flag
      * is set to false
      * which means the pop wont ignore cheek press dispatch events.
-     * 
+     *
      * <p>If the popup is showing, calling this method will take effect only
      * the next time the popup is shown or through a manual call to one of
      * the {@link #update()} methods.</p>
-     * 
+     *
      * @see #update()
      */
     public void setIgnoreCheekPress() {
@@ -443,6 +446,19 @@
         if (mWindowManager == null && mContentView != null) {
             mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
         }
+
+        // Setting the default for attachedInDecor based on SDK version here
+        // instead of in the constructor since we might not have the context
+        // object in the constructor. We only want to set default here if the
+        // app hasn't already set the attachedInDecor.
+        if (mContext != null && !mAttachedInDecorSet) {
+            // Attach popup window in decor frame of parent window by default for
+            // {@link Build.VERSION_CODES.LOLLIPOP_MR1} or greater. Keep current
+            // behavior of not attaching to decor frame for older SDKs.
+            setAttachedInDecor(mContext.getApplicationInfo().targetSdkVersion
+                    >= Build.VERSION_CODES.LOLLIPOP_MR1);
+        }
+
     }
 
     /**
@@ -452,7 +468,7 @@
     public void setTouchInterceptor(OnTouchListener l) {
         mTouchInterceptor = l;
     }
-    
+
     /**
      * <p>Indicate whether the popup window can grab the focus.</p>
      *
@@ -702,6 +718,36 @@
     }
 
     /**
+     * <p>Indicates whether the popup window will be attached in the decor frame of its parent
+     * window.
+     *
+     * @return true if the window will be attached to the decor frame of its parent window.
+     *
+     * @see #setAttachedInDecor(boolean)
+     * @see WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR
+     */
+    public boolean isAttachedInDecor() {
+        return mAttachedInDecor;
+    }
+
+    /**
+     * <p>This will attach the popup window to the decor frame of the parent window to avoid
+     * overlaping with screen decorations like the navigation bar. Overrides the default behavior of
+     * the flag {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR}.
+     *
+     * <p>By default the flag is set on SDK version {@link Build.VERSION_CODES#LOLLIPOP_MR1} or
+     * greater and cleared on lesser SDK versions.
+     *
+     * @param enabled true if the popup should be attached to the decor frame of its parent window.
+     *
+     * @see WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR
+     */
+    public void setAttachedInDecor(boolean enabled) {
+        mAttachedInDecor = enabled;
+        mAttachedInDecorSet = true;
+    }
+
+    /**
      * Allows the popup window to force the flag
      * {@link WindowManager.LayoutParams#FLAG_LAYOUT_INSET_DECOR}, overriding default behavior.
      * This will cause the popup to inset its content to account for system windows overlaying
@@ -1140,9 +1186,12 @@
         if (mNotTouchModal) {
             curFlags |= WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
         }
+        if (mAttachedInDecor) {
+          curFlags |= WindowManager.LayoutParams.FLAG_LAYOUT_ATTACHED_IN_DECOR;
+        }
         return curFlags;
     }
-    
+
     private int computeAnimationResource() {
         if (mAnimationStyle == -1) {
             if (mIsDropdown) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5cdee53..0917b32 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -8518,6 +8518,7 @@
             } return false;
             case AccessibilityNodeInfo.ACTION_SET_SELECTION: {
                 if (isFocused() && canSelectText()) {
+                    ensureIterableTextForAccessibilitySelectable();
                     CharSequence text = getIterableTextForAccessibility();
                     if (text == null) {
                         return false;
@@ -8543,6 +8544,11 @@
                     }
                 }
             } return false;
+            case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY:
+            case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
+                ensureIterableTextForAccessibilitySelectable();
+                return super.performAccessibilityAction(action, arguments);
+            }
             default: {
                 return super.performAccessibilityAction(action, arguments);
             }
@@ -9032,10 +9038,13 @@
      */
     @Override
     public CharSequence getIterableTextForAccessibility() {
+        return mText;
+    }
+
+    private void ensureIterableTextForAccessibilitySelectable() {
         if (!(mText instanceof Spannable)) {
             setText(mText, BufferType.SPANNABLE);
         }
-        return mText;
     }
 
     /**
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index 85cf67b..26e02f8 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -86,12 +86,12 @@
 
         switch (mode) {
             case MODE_CLOCK:
-                mDelegate = new TimePickerSpinnerDelegate(
+                mDelegate = new TimePickerClockDelegate(
                         this, context, attrs, defStyleAttr, defStyleRes);
                 break;
             case MODE_SPINNER:
             default:
-                mDelegate = new TimePickerClockDelegate(
+                mDelegate = new TimePickerSpinnerDelegate(
                         this, context, attrs, defStyleAttr, defStyleRes);
                 break;
         }
diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java
index 6dfea92..eca3048 100644
--- a/core/java/android/widget/TimePickerClockDelegate.java
+++ b/core/java/android/widget/TimePickerClockDelegate.java
@@ -17,365 +17,376 @@
 package android.widget;
 
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.content.res.Configuration;
+import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.text.TextUtils;
 import android.text.format.DateFormat;
 import android.text.format.DateUtils;
 import android.util.AttributeSet;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.HapticFeedbackConstants;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputMethodManager;
+
 import com.android.internal.R;
 
-import java.text.DateFormatSymbols;
+import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Locale;
 
-import libcore.icu.LocaleData;
-
-import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO;
-import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_YES;
-
 /**
- * A delegate implementing the basic spinner-based TimePicker.
+ * A delegate implementing the radial clock-based TimePicker.
  */
-class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate {
+class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate implements
+        RadialTimePickerView.OnValueSelectedListener {
+
+    private static final String TAG = "TimePickerClockDelegate";
+
+    // Index used by RadialPickerLayout
+    private static final int HOUR_INDEX = 0;
+    private static final int MINUTE_INDEX = 1;
+
+    // NOT a real index for the purpose of what's showing.
+    private static final int AMPM_INDEX = 2;
+
+    // Also NOT a real index, just used for keyboard mode.
+    private static final int ENABLE_PICKER_INDEX = 3;
+
+    static final int AM = 0;
+    static final int PM = 1;
+
     private static final boolean DEFAULT_ENABLED_STATE = true;
+    private boolean mIsEnabled = DEFAULT_ENABLED_STATE;
+
     private static final int HOURS_IN_HALF_DAY = 12;
 
-    // state
+    private final View mHeaderView;
+    private final TextView mHourView;
+    private final TextView mMinuteView;
+    private final View mAmPmLayout;
+    private final CheckedTextView mAmLabel;
+    private final CheckedTextView mPmLabel;
+    private final RadialTimePickerView mRadialTimePickerView;
+    private final TextView mSeparatorView;
+
+    private final String mAmText;
+    private final String mPmText;
+
+    private final float mDisabledAlpha;
+
+    private boolean mAllowAutoAdvance;
+    private int mInitialHourOfDay;
+    private int mInitialMinute;
     private boolean mIs24HourView;
-    private boolean mIsAm;
 
-    // ui components
-    private final NumberPicker mHourSpinner;
-    private final NumberPicker mMinuteSpinner;
-    private final NumberPicker mAmPmSpinner;
-    private final EditText mHourSpinnerInput;
-    private final EditText mMinuteSpinnerInput;
-    private final EditText mAmPmSpinnerInput;
-    private final TextView mDivider;
+    // For hardware IME input.
+    private char mPlaceholderText;
+    private String mDoublePlaceholderText;
+    private String mDeletedKeyFormat;
+    private boolean mInKbMode;
+    private ArrayList<Integer> mTypedTimes = new ArrayList<Integer>();
+    private Node mLegalTimesTree;
+    private int mAmKeyCode;
+    private int mPmKeyCode;
 
-    // Note that the legacy implementation of the TimePicker is
-    // using a button for toggling between AM/PM while the new
-    // version uses a NumberPicker spinner. Therefore the code
-    // accommodates these two cases to be backwards compatible.
-    private final Button mAmPmButton;
+    // Accessibility strings.
+    private String mHourPickerDescription;
+    private String mSelectHours;
+    private String mMinutePickerDescription;
+    private String mSelectMinutes;
 
-    private final String[] mAmPmStrings;
+    // Most recent time announcement values for accessibility.
+    private CharSequence mLastAnnouncedText;
+    private boolean mLastAnnouncedIsHour;
 
-    private boolean mIsEnabled = DEFAULT_ENABLED_STATE;
     private Calendar mTempCalendar;
-    private boolean mHourWithTwoDigit;
-    private char mHourFormat;
 
     public TimePickerClockDelegate(TimePicker delegator, Context context, AttributeSet attrs,
             int defStyleAttr, int defStyleRes) {
         super(delegator, context);
 
         // process style attributes
-        final TypedArray a = mContext.obtainStyledAttributes(
-                attrs, R.styleable.TimePicker, defStyleAttr, defStyleRes);
-        final int layoutResourceId = a.getResourceId(
-                R.styleable.TimePicker_legacyLayout, R.layout.time_picker_legacy);
+        final TypedArray a = mContext.obtainStyledAttributes(attrs,
+                R.styleable.TimePicker, defStyleAttr, defStyleRes);
+        final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
+                Context.LAYOUT_INFLATER_SERVICE);
+        final Resources res = mContext.getResources();
+
+        mHourPickerDescription = res.getString(R.string.hour_picker_description);
+        mSelectHours = res.getString(R.string.select_hours);
+        mMinutePickerDescription = res.getString(R.string.minute_picker_description);
+        mSelectMinutes = res.getString(R.string.select_minutes);
+
+        String[] amPmStrings = TimePickerSpinnerDelegate.getAmPmStrings(context);
+        mAmText = amPmStrings[0];
+        mPmText = amPmStrings[1];
+
+        final int layoutResourceId = a.getResourceId(R.styleable.TimePicker_internalLayout,
+                R.layout.time_picker_holo);
+        final View mainView = inflater.inflate(layoutResourceId, delegator);
+
+        mHeaderView = mainView.findViewById(R.id.time_header);
+        mHeaderView.setBackground(a.getDrawable(R.styleable.TimePicker_headerBackground));
+
+        // Set up hour/minute labels.
+        mHourView = (TextView) mHeaderView.findViewById(R.id.hours);
+        mHourView.setOnClickListener(mClickListener);
+        mSeparatorView = (TextView) mHeaderView.findViewById(R.id.separator);
+        mMinuteView = (TextView) mHeaderView.findViewById(R.id.minutes);
+        mMinuteView.setOnClickListener(mClickListener);
+
+        final int headerTimeTextAppearance = a.getResourceId(
+                R.styleable.TimePicker_headerTimeTextAppearance, 0);
+        if (headerTimeTextAppearance != 0) {
+            mHourView.setTextAppearance(context, headerTimeTextAppearance);
+            mSeparatorView.setTextAppearance(context, headerTimeTextAppearance);
+            mMinuteView.setTextAppearance(context, headerTimeTextAppearance);
+        }
+
+        // TODO: This can be removed once we support themed color state lists.
+        final int headerSelectedTextColor = a.getColor(
+                R.styleable.TimePicker_headerSelectedTextColor,
+                res.getColor(R.color.timepicker_default_selector_color_material));
+        mHourView.setTextColor(ColorStateList.addFirstIfMissing(mHourView.getTextColors(),
+                R.attr.state_selected, headerSelectedTextColor));
+        mMinuteView.setTextColor(ColorStateList.addFirstIfMissing(mMinuteView.getTextColors(),
+                R.attr.state_selected, headerSelectedTextColor));
+
+        // Set up AM/PM labels.
+        mAmPmLayout = mHeaderView.findViewById(R.id.ampm_layout);
+        mAmLabel = (CheckedTextView) mAmPmLayout.findViewById(R.id.am_label);
+        mAmLabel.setText(amPmStrings[0]);
+        mAmLabel.setOnClickListener(mClickListener);
+        mPmLabel = (CheckedTextView) mAmPmLayout.findViewById(R.id.pm_label);
+        mPmLabel.setText(amPmStrings[1]);
+        mPmLabel.setOnClickListener(mClickListener);
+
+        final int headerAmPmTextAppearance = a.getResourceId(
+                R.styleable.TimePicker_headerAmPmTextAppearance, 0);
+        if (headerAmPmTextAppearance != 0) {
+            mAmLabel.setTextAppearance(context, headerAmPmTextAppearance);
+            mPmLabel.setTextAppearance(context, headerAmPmTextAppearance);
+        }
+
         a.recycle();
 
-        final LayoutInflater inflater = LayoutInflater.from(mContext);
-        inflater.inflate(layoutResourceId, mDelegator, true);
+        // Pull disabled alpha from theme.
+        final TypedValue outValue = new TypedValue();
+        context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, outValue, true);
+        mDisabledAlpha = outValue.getFloat();
 
-        // hour
-        mHourSpinner = (NumberPicker) delegator.findViewById(R.id.hour);
-        mHourSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
-            public void onValueChange(NumberPicker spinner, int oldVal, int newVal) {
-                updateInputState();
-                if (!is24HourView()) {
-                    if ((oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY) ||
-                            (oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1)) {
-                        mIsAm = !mIsAm;
-                        updateAmPmControl();
-                    }
-                }
-                onTimeChanged();
-            }
-        });
-        mHourSpinnerInput = (EditText) mHourSpinner.findViewById(R.id.numberpicker_input);
-        mHourSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
+        mRadialTimePickerView = (RadialTimePickerView) mainView.findViewById(
+                R.id.radial_picker);
 
-        // divider (only for the new widget style)
-        mDivider = (TextView) mDelegator.findViewById(R.id.divider);
-        if (mDivider != null) {
-            setDividerText();
+        setupListeners();
+
+        mAllowAutoAdvance = true;
+
+        // Set up for keyboard mode.
+        mDoublePlaceholderText = res.getString(R.string.time_placeholder);
+        mDeletedKeyFormat = res.getString(R.string.deleted_key);
+        mPlaceholderText = mDoublePlaceholderText.charAt(0);
+        mAmKeyCode = mPmKeyCode = -1;
+        generateLegalTimesTree();
+
+        // Initialize with current time
+        final Calendar calendar = Calendar.getInstance(mCurrentLocale);
+        final int currentHour = calendar.get(Calendar.HOUR_OF_DAY);
+        final int currentMinute = calendar.get(Calendar.MINUTE);
+        initialize(currentHour, currentMinute, false /* 12h */, HOUR_INDEX);
+    }
+
+    private void initialize(int hourOfDay, int minute, boolean is24HourView, int index) {
+        mInitialHourOfDay = hourOfDay;
+        mInitialMinute = minute;
+        mIs24HourView = is24HourView;
+        mInKbMode = false;
+        updateUI(index);
+    }
+
+    private void setupListeners() {
+        mHeaderView.setOnKeyListener(mKeyListener);
+        mHeaderView.setOnFocusChangeListener(mFocusListener);
+        mHeaderView.setFocusable(true);
+
+        mRadialTimePickerView.setOnValueSelectedListener(this);
+    }
+
+    private void updateUI(int index) {
+        // Update RadialPicker values
+        updateRadialPicker(index);
+        // Enable or disable the AM/PM view.
+        updateHeaderAmPm();
+        // Update Hour and Minutes
+        updateHeaderHour(mInitialHourOfDay, false);
+        // Update time separator
+        updateHeaderSeparator();
+        // Update Minutes
+        updateHeaderMinute(mInitialMinute, false);
+        // Invalidate everything
+        mDelegator.invalidate();
+    }
+
+    private void updateRadialPicker(int index) {
+        mRadialTimePickerView.initialize(mInitialHourOfDay, mInitialMinute, mIs24HourView);
+        setCurrentItemShowing(index, false, true);
+    }
+
+    private int computeMaxWidthOfNumbers(int max) {
+        TextView tempView = new TextView(mContext);
+        tempView.setTextAppearance(mContext, R.style.TextAppearance_Material_TimePicker_TimeLabel);
+        ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
+                ViewGroup.LayoutParams.WRAP_CONTENT);
+        tempView.setLayoutParams(lp);
+        int maxWidth = 0;
+        for (int minutes = 0; minutes < max; minutes++) {
+            final String text = String.format("%02d", minutes);
+            tempView.setText(text);
+            tempView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+            maxWidth = Math.max(maxWidth, tempView.getMeasuredWidth());
         }
+        return maxWidth;
+    }
 
-        // minute
-        mMinuteSpinner = (NumberPicker) mDelegator.findViewById(R.id.minute);
-        mMinuteSpinner.setMinValue(0);
-        mMinuteSpinner.setMaxValue(59);
-        mMinuteSpinner.setOnLongPressUpdateInterval(100);
-        mMinuteSpinner.setFormatter(NumberPicker.getTwoDigitFormatter());
-        mMinuteSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
-            public void onValueChange(NumberPicker spinner, int oldVal, int newVal) {
-                updateInputState();
-                int minValue = mMinuteSpinner.getMinValue();
-                int maxValue = mMinuteSpinner.getMaxValue();
-                if (oldVal == maxValue && newVal == minValue) {
-                    int newHour = mHourSpinner.getValue() + 1;
-                    if (!is24HourView() && newHour == HOURS_IN_HALF_DAY) {
-                        mIsAm = !mIsAm;
-                        updateAmPmControl();
-                    }
-                    mHourSpinner.setValue(newHour);
-                } else if (oldVal == minValue && newVal == maxValue) {
-                    int newHour = mHourSpinner.getValue() - 1;
-                    if (!is24HourView() && newHour == HOURS_IN_HALF_DAY - 1) {
-                        mIsAm = !mIsAm;
-                        updateAmPmControl();
-                    }
-                    mHourSpinner.setValue(newHour);
-                }
-                onTimeChanged();
-            }
-        });
-        mMinuteSpinnerInput = (EditText) mMinuteSpinner.findViewById(R.id.numberpicker_input);
-        mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
-
-        // Get the localized am/pm strings and use them in the spinner.
-        mAmPmStrings = getAmPmStrings(context);
-
-        // am/pm
-        final View amPmView = mDelegator.findViewById(R.id.amPm);
-        if (amPmView instanceof Button) {
-            mAmPmSpinner = null;
-            mAmPmSpinnerInput = null;
-            mAmPmButton = (Button) amPmView;
-            mAmPmButton.setOnClickListener(new View.OnClickListener() {
-                public void onClick(View button) {
-                    button.requestFocus();
-                    mIsAm = !mIsAm;
-                    updateAmPmControl();
-                    onTimeChanged();
-                }
-            });
+    private void updateHeaderAmPm() {
+        if (mIs24HourView) {
+            mAmPmLayout.setVisibility(View.GONE);
         } else {
-            mAmPmButton = null;
-            mAmPmSpinner = (NumberPicker) amPmView;
-            mAmPmSpinner.setMinValue(0);
-            mAmPmSpinner.setMaxValue(1);
-            mAmPmSpinner.setDisplayedValues(mAmPmStrings);
-            mAmPmSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
-                public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
-                    updateInputState();
-                    picker.requestFocus();
-                    mIsAm = !mIsAm;
-                    updateAmPmControl();
-                    onTimeChanged();
-                }
-            });
-            mAmPmSpinnerInput = (EditText) mAmPmSpinner.findViewById(R.id.numberpicker_input);
-            mAmPmSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE);
-        }
-
-        if (isAmPmAtStart()) {
-            // Move the am/pm view to the beginning
-            ViewGroup amPmParent = (ViewGroup) delegator.findViewById(R.id.timePickerLayout);
-            amPmParent.removeView(amPmView);
-            amPmParent.addView(amPmView, 0);
-            // Swap layout margins if needed. They may be not symmetrical (Old Standard Theme
-            // for example and not for Holo Theme)
-            ViewGroup.MarginLayoutParams lp =
-                    (ViewGroup.MarginLayoutParams) amPmView.getLayoutParams();
-            final int startMargin = lp.getMarginStart();
-            final int endMargin = lp.getMarginEnd();
-            if (startMargin != endMargin) {
-                lp.setMarginStart(endMargin);
-                lp.setMarginEnd(startMargin);
+            final String bestDateTimePattern = DateFormat.getBestDateTimePattern(
+                    mCurrentLocale, "hm");
+            boolean amPmOnLeft = bestDateTimePattern.startsWith("a");
+            if (TextUtils.getLayoutDirectionFromLocale(mCurrentLocale) ==
+                    View.LAYOUT_DIRECTION_RTL) {
+                amPmOnLeft = !amPmOnLeft;
             }
-        }
 
-        getHourFormatData();
+            final ViewGroup.MarginLayoutParams params =
+                    (ViewGroup.MarginLayoutParams) mAmPmLayout.getLayoutParams();
 
-        // update controls to initial state
-        updateHourControl();
-        updateMinuteControl();
-        updateAmPmControl();
-
-        // set to current time
-        setCurrentHour(mTempCalendar.get(Calendar.HOUR_OF_DAY));
-        setCurrentMinute(mTempCalendar.get(Calendar.MINUTE));
-
-        if (!isEnabled()) {
-            setEnabled(false);
-        }
-
-        // set the content descriptions
-        setContentDescriptions();
-
-        // If not explicitly specified this view is important for accessibility.
-        if (mDelegator.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
-            mDelegator.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
-        }
-    }
-
-    private void getHourFormatData() {
-        final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale,
-                (mIs24HourView) ? "Hm" : "hm");
-        final int lengthPattern = bestDateTimePattern.length();
-        mHourWithTwoDigit = false;
-        char hourFormat = '\0';
-        // Check if the returned pattern is single or double 'H', 'h', 'K', 'k'. We also save
-        // the hour format that we found.
-        for (int i = 0; i < lengthPattern; i++) {
-            final char c = bestDateTimePattern.charAt(i);
-            if (c == 'H' || c == 'h' || c == 'K' || c == 'k') {
-                mHourFormat = c;
-                if (i + 1 < lengthPattern && c == bestDateTimePattern.charAt(i + 1)) {
-                    mHourWithTwoDigit = true;
-                }
-                break;
+            if (amPmOnLeft) {
+                params.leftMargin = 0;
+                params.rightMargin = computeMaxWidthOfNumbers(12 /* for hours */);
+            } else {
+                params.leftMargin = computeMaxWidthOfNumbers(60 /* for minutes */);
+                params.rightMargin = 0;
             }
+
+            mAmPmLayout.setLayoutParams(params);
+            mAmPmLayout.setVisibility(View.VISIBLE);
+
+            updateAmPmLabelStates(mInitialHourOfDay < 12 ? AM : PM);
         }
     }
 
-    private boolean isAmPmAtStart() {
-        final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale,
-                "hm" /* skeleton */);
-
-        return bestDateTimePattern.startsWith("a");
-    }
-
     /**
-     * The time separator is defined in the Unicode CLDR and cannot be supposed to be ":".
-     *
-     * See http://unicode.org/cldr/trac/browser/trunk/common/main
-     *
-     * We pass the correct "skeleton" depending on 12 or 24 hours view and then extract the
-     * separator as the character which is just after the hour marker in the returned pattern.
+     * Set the current hour.
      */
-    private void setDividerText() {
-        final String skeleton = (mIs24HourView) ? "Hm" : "hm";
-        final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale,
-                skeleton);
-        final String separatorText;
-        int hourIndex = bestDateTimePattern.lastIndexOf('H');
-        if (hourIndex == -1) {
-            hourIndex = bestDateTimePattern.lastIndexOf('h');
-        }
-        if (hourIndex == -1) {
-            // Default case
-            separatorText = ":";
-        } else {
-            int minuteIndex = bestDateTimePattern.indexOf('m', hourIndex + 1);
-            if  (minuteIndex == -1) {
-                separatorText = Character.toString(bestDateTimePattern.charAt(hourIndex + 1));
-            } else {
-                separatorText = bestDateTimePattern.substring(hourIndex + 1, minuteIndex);
-            }
-        }
-        mDivider.setText(separatorText);
-    }
-
     @Override
     public void setCurrentHour(Integer currentHour) {
-        setCurrentHour(currentHour, true);
-    }
-
-    private void setCurrentHour(Integer currentHour, boolean notifyTimeChanged) {
-        // why was Integer used in the first place?
-        if (currentHour == null || currentHour == getCurrentHour()) {
+        if (mInitialHourOfDay == currentHour) {
             return;
         }
-        if (!is24HourView()) {
-            // convert [0,23] ordinal to wall clock display
-            if (currentHour >= HOURS_IN_HALF_DAY) {
-                mIsAm = false;
-                if (currentHour > HOURS_IN_HALF_DAY) {
-                    currentHour = currentHour - HOURS_IN_HALF_DAY;
-                }
-            } else {
-                mIsAm = true;
-                if (currentHour == 0) {
-                    currentHour = HOURS_IN_HALF_DAY;
-                }
-            }
-            updateAmPmControl();
-        }
-        mHourSpinner.setValue(currentHour);
-        if (notifyTimeChanged) {
-            onTimeChanged();
-        }
-    }
-
-    @Override
-    public Integer getCurrentHour() {
-        int currentHour = mHourSpinner.getValue();
-        if (is24HourView()) {
-            return currentHour;
-        } else if (mIsAm) {
-            return currentHour % HOURS_IN_HALF_DAY;
-        } else {
-            return (currentHour % HOURS_IN_HALF_DAY) + HOURS_IN_HALF_DAY;
-        }
-    }
-
-    @Override
-    public void setCurrentMinute(Integer currentMinute) {
-        if (currentMinute == getCurrentMinute()) {
-            return;
-        }
-        mMinuteSpinner.setValue(currentMinute);
+        mInitialHourOfDay = currentHour;
+        updateHeaderHour(currentHour, true);
+        updateHeaderAmPm();
+        mRadialTimePickerView.setCurrentHour(currentHour);
+        mRadialTimePickerView.setAmOrPm(mInitialHourOfDay < 12 ? AM : PM);
+        mDelegator.invalidate();
         onTimeChanged();
     }
 
+    /**
+     * @return The current hour in the range (0-23).
+     */
     @Override
-    public Integer getCurrentMinute() {
-        return mMinuteSpinner.getValue();
+    public Integer getCurrentHour() {
+        int currentHour = mRadialTimePickerView.getCurrentHour();
+        if (mIs24HourView) {
+            return currentHour;
+        } else {
+            switch(mRadialTimePickerView.getAmOrPm()) {
+                case PM:
+                    return (currentHour % HOURS_IN_HALF_DAY) + HOURS_IN_HALF_DAY;
+                case AM:
+                default:
+                    return currentHour % HOURS_IN_HALF_DAY;
+            }
+        }
     }
 
+    /**
+     * Set the current minute (0-59).
+     */
     @Override
-    public void setIs24HourView(Boolean is24HourView) {
-        if (mIs24HourView == is24HourView) {
+    public void setCurrentMinute(Integer currentMinute) {
+        if (mInitialMinute == currentMinute) {
             return;
         }
-        // cache the current hour since spinner range changes and BEFORE changing mIs24HourView!!
-        int currentHour = getCurrentHour();
-        // Order is important here.
-        mIs24HourView = is24HourView;
-        getHourFormatData();
-        updateHourControl();
-        // set value after spinner range is updated
-        setCurrentHour(currentHour, false);
-        updateMinuteControl();
-        updateAmPmControl();
+        mInitialMinute = currentMinute;
+        updateHeaderMinute(currentMinute, true);
+        mRadialTimePickerView.setCurrentMinute(currentMinute);
+        mDelegator.invalidate();
+        onTimeChanged();
     }
 
+    /**
+     * @return The current minute.
+     */
+    @Override
+    public Integer getCurrentMinute() {
+        return mRadialTimePickerView.getCurrentMinute();
+    }
+
+    /**
+     * Set whether in 24 hour or AM/PM mode.
+     *
+     * @param is24HourView True = 24 hour mode. False = AM/PM.
+     */
+    @Override
+    public void setIs24HourView(Boolean is24HourView) {
+        if (is24HourView == mIs24HourView) {
+            return;
+        }
+        mIs24HourView = is24HourView;
+        generateLegalTimesTree();
+        int hour = mRadialTimePickerView.getCurrentHour();
+        mInitialHourOfDay = hour;
+        updateHeaderHour(hour, false);
+        updateHeaderAmPm();
+        updateRadialPicker(mRadialTimePickerView.getCurrentItemShowing());
+        mDelegator.invalidate();
+    }
+
+    /**
+     * @return true if this is in 24 hour view else false.
+     */
     @Override
     public boolean is24HourView() {
         return mIs24HourView;
     }
 
     @Override
-    public void setOnTimeChangedListener(TimePicker.OnTimeChangedListener onTimeChangedListener) {
-        mOnTimeChangedListener = onTimeChangedListener;
+    public void setOnTimeChangedListener(TimePicker.OnTimeChangedListener callback) {
+        mOnTimeChangedListener = callback;
     }
 
     @Override
     public void setEnabled(boolean enabled) {
-        mMinuteSpinner.setEnabled(enabled);
-        if (mDivider != null) {
-            mDivider.setEnabled(enabled);
-        }
-        mHourSpinner.setEnabled(enabled);
-        if (mAmPmSpinner != null) {
-            mAmPmSpinner.setEnabled(enabled);
-        } else {
-            mAmPmButton.setEnabled(enabled);
-        }
+        mHourView.setEnabled(enabled);
+        mMinuteView.setEnabled(enabled);
+        mAmLabel.setEnabled(enabled);
+        mPmLabel.setEnabled(enabled);
+        mRadialTimePickerView.setEnabled(enabled);
         mIsEnabled = enabled;
     }
 
@@ -386,24 +397,38 @@
 
     @Override
     public int getBaseline() {
-        return mHourSpinner.getBaseline();
+        // does not support baseline alignment
+        return -1;
     }
 
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
-        setCurrentLocale(newConfig.locale);
+        updateUI(mRadialTimePickerView.getCurrentItemShowing());
     }
 
     @Override
     public Parcelable onSaveInstanceState(Parcelable superState) {
-        return new SavedState(superState, getCurrentHour(), getCurrentMinute());
+        return new SavedState(superState, getCurrentHour(), getCurrentMinute(),
+                is24HourView(), inKbMode(), getTypedTimes(), getCurrentItemShowing());
     }
 
     @Override
     public void onRestoreInstanceState(Parcelable state) {
         SavedState ss = (SavedState) state;
-        setCurrentHour(ss.getHour());
-        setCurrentMinute(ss.getMinute());
+        setInKbMode(ss.inKbMode());
+        setTypedTimes(ss.getTypesTimes());
+        initialize(ss.getHour(), ss.getMinute(), ss.is24HourMode(), ss.getCurrentItemShowing());
+        mRadialTimePickerView.invalidate();
+        if (mInKbMode) {
+            tryStartingKbMode(-1);
+            mHourView.invalidate();
+        }
+    }
+
+    @Override
+    public void setCurrentLocale(Locale locale) {
+        super.setCurrentLocale(locale);
+        mTempCalendar = Calendar.getInstance(locale);
     }
 
     @Override
@@ -422,9 +447,9 @@
         }
         mTempCalendar.set(Calendar.HOUR_OF_DAY, getCurrentHour());
         mTempCalendar.set(Calendar.MINUTE, getCurrentMinute());
-        String selectedDateUtterance = DateUtils.formatDateTime(mContext,
+        String selectedDate = DateUtils.formatDateTime(mContext,
                 mTempCalendar.getTimeInMillis(), flags);
-        event.getText().add(selectedDateUtterance);
+        event.getText().add(selectedDate);
     }
 
     @Override
@@ -437,121 +462,48 @@
         info.setClassName(TimePicker.class.getName());
     }
 
-    private void updateInputState() {
-        // Make sure that if the user changes the value and the IME is active
-        // for one of the inputs if this widget, the IME is closed. If the user
-        // changed the value via the IME and there is a next input the IME will
-        // be shown, otherwise the user chose another means of changing the
-        // value and having the IME up makes no sense.
-        InputMethodManager inputMethodManager = InputMethodManager.peekInstance();
-        if (inputMethodManager != null) {
-            if (inputMethodManager.isActive(mHourSpinnerInput)) {
-                mHourSpinnerInput.clearFocus();
-                inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
-            } else if (inputMethodManager.isActive(mMinuteSpinnerInput)) {
-                mMinuteSpinnerInput.clearFocus();
-                inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
-            } else if (inputMethodManager.isActive(mAmPmSpinnerInput)) {
-                mAmPmSpinnerInput.clearFocus();
-                inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
-            }
-        }
-    }
-
-    private void updateAmPmControl() {
-        if (is24HourView()) {
-            if (mAmPmSpinner != null) {
-                mAmPmSpinner.setVisibility(View.GONE);
-            } else {
-                mAmPmButton.setVisibility(View.GONE);
-            }
-        } else {
-            int index = mIsAm ? Calendar.AM : Calendar.PM;
-            if (mAmPmSpinner != null) {
-                mAmPmSpinner.setValue(index);
-                mAmPmSpinner.setVisibility(View.VISIBLE);
-            } else {
-                mAmPmButton.setText(mAmPmStrings[index]);
-                mAmPmButton.setVisibility(View.VISIBLE);
-            }
-        }
-        mDelegator.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
+    /**
+     * Set whether in keyboard mode or not.
+     *
+     * @param inKbMode True means in keyboard mode.
+     */
+    private void setInKbMode(boolean inKbMode) {
+        mInKbMode = inKbMode;
     }
 
     /**
-     * Sets the current locale.
-     *
-     * @param locale The current locale.
+     * @return true if in keyboard mode
      */
-    @Override
-    public void setCurrentLocale(Locale locale) {
-        super.setCurrentLocale(locale);
-        mTempCalendar = Calendar.getInstance(locale);
+    private boolean inKbMode() {
+        return mInKbMode;
     }
 
+    private void setTypedTimes(ArrayList<Integer> typeTimes) {
+        mTypedTimes = typeTimes;
+    }
+
+    /**
+     * @return an array of typed times
+     */
+    private ArrayList<Integer> getTypedTimes() {
+        return mTypedTimes;
+    }
+
+    /**
+     * @return the index of the current item showing
+     */
+    private int getCurrentItemShowing() {
+        return mRadialTimePickerView.getCurrentItemShowing();
+    }
+
+    /**
+     * Propagate the time change
+     */
     private void onTimeChanged() {
         mDelegator.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
         if (mOnTimeChangedListener != null) {
-            mOnTimeChangedListener.onTimeChanged(mDelegator, getCurrentHour(),
-                    getCurrentMinute());
-        }
-    }
-
-    private void updateHourControl() {
-        if (is24HourView()) {
-            // 'k' means 1-24 hour
-            if (mHourFormat == 'k') {
-                mHourSpinner.setMinValue(1);
-                mHourSpinner.setMaxValue(24);
-            } else {
-                mHourSpinner.setMinValue(0);
-                mHourSpinner.setMaxValue(23);
-            }
-        } else {
-            // 'K' means 0-11 hour
-            if (mHourFormat == 'K') {
-                mHourSpinner.setMinValue(0);
-                mHourSpinner.setMaxValue(11);
-            } else {
-                mHourSpinner.setMinValue(1);
-                mHourSpinner.setMaxValue(12);
-            }
-        }
-        mHourSpinner.setFormatter(mHourWithTwoDigit ? NumberPicker.getTwoDigitFormatter() : null);
-    }
-
-    private void updateMinuteControl() {
-        if (is24HourView()) {
-            mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE);
-        } else {
-            mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
-        }
-    }
-
-    private void setContentDescriptions() {
-        // Minute
-        trySetContentDescription(mMinuteSpinner, R.id.increment,
-                R.string.time_picker_increment_minute_button);
-        trySetContentDescription(mMinuteSpinner, R.id.decrement,
-                R.string.time_picker_decrement_minute_button);
-        // Hour
-        trySetContentDescription(mHourSpinner, R.id.increment,
-                R.string.time_picker_increment_hour_button);
-        trySetContentDescription(mHourSpinner, R.id.decrement,
-                R.string.time_picker_decrement_hour_button);
-        // AM/PM
-        if (mAmPmSpinner != null) {
-            trySetContentDescription(mAmPmSpinner, R.id.increment,
-                    R.string.time_picker_increment_set_pm_button);
-            trySetContentDescription(mAmPmSpinner, R.id.decrement,
-                    R.string.time_picker_decrement_set_am_button);
-        }
-    }
-
-    private void trySetContentDescription(View root, int viewId, int contDescResId) {
-        View target = root.findViewById(viewId);
-        if (target != null) {
-            target.setContentDescription(mContext.getString(contDescResId));
+            mOnTimeChangedListener.onTimeChanged(mDelegator,
+                    getCurrentHour(), getCurrentMinute());
         }
     }
 
@@ -559,19 +511,34 @@
      * Used to save / restore state of time picker
      */
     private static class SavedState extends View.BaseSavedState {
+
         private final int mHour;
         private final int mMinute;
+        private final boolean mIs24HourMode;
+        private final boolean mInKbMode;
+        private final ArrayList<Integer> mTypedTimes;
+        private final int mCurrentItemShowing;
 
-        private SavedState(Parcelable superState, int hour, int minute) {
+        private SavedState(Parcelable superState, int hour, int minute, boolean is24HourMode,
+                           boolean isKbMode, ArrayList<Integer> typedTimes,
+                           int currentItemShowing) {
             super(superState);
             mHour = hour;
             mMinute = minute;
+            mIs24HourMode = is24HourMode;
+            mInKbMode = isKbMode;
+            mTypedTimes = typedTimes;
+            mCurrentItemShowing = currentItemShowing;
         }
 
         private SavedState(Parcel in) {
             super(in);
             mHour = in.readInt();
             mMinute = in.readInt();
+            mIs24HourMode = (in.readInt() == 1);
+            mInKbMode = (in.readInt() == 1);
+            mTypedTimes = in.readArrayList(getClass().getClassLoader());
+            mCurrentItemShowing = in.readInt();
         }
 
         public int getHour() {
@@ -582,11 +549,31 @@
             return mMinute;
         }
 
+        public boolean is24HourMode() {
+            return mIs24HourMode;
+        }
+
+        public boolean inKbMode() {
+            return mInKbMode;
+        }
+
+        public ArrayList<Integer> getTypesTimes() {
+            return mTypedTimes;
+        }
+
+        public int getCurrentItemShowing() {
+            return mCurrentItemShowing;
+        }
+
         @Override
         public void writeToParcel(Parcel dest, int flags) {
             super.writeToParcel(dest, flags);
             dest.writeInt(mHour);
             dest.writeInt(mMinute);
+            dest.writeInt(mIs24HourMode ? 1 : 0);
+            dest.writeInt(mInKbMode ? 1 : 0);
+            dest.writeList(mTypedTimes);
+            dest.writeInt(mCurrentItemShowing);
         }
 
         @SuppressWarnings({"unused", "hiding"})
@@ -601,11 +588,706 @@
         };
     }
 
-    public static String[] getAmPmStrings(Context context) {
-        String[] result = new String[2];
-        LocaleData d = LocaleData.get(context.getResources().getConfiguration().locale);
-        result[0] = d.amPm[0].length() > 2 ? d.narrowAm : d.amPm[0];
-        result[1] = d.amPm[1].length() > 2 ? d.narrowPm : d.amPm[1];
-        return result;
+    private void tryVibrate() {
+        mDelegator.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK);
     }
+
+    private void updateAmPmLabelStates(int amOrPm) {
+        final boolean isAm = amOrPm == AM;
+        mAmLabel.setChecked(isAm);
+        mAmLabel.setAlpha(isAm ? 1 : mDisabledAlpha);
+
+        final boolean isPm = amOrPm == PM;
+        mPmLabel.setChecked(isPm);
+        mPmLabel.setAlpha(isPm ? 1 : mDisabledAlpha);
+    }
+
+    /**
+     * Called by the picker for updating the header display.
+     */
+    @Override
+    public void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance) {
+        if (pickerIndex == HOUR_INDEX) {
+            if (mAllowAutoAdvance && autoAdvance) {
+                updateHeaderHour(newValue, false);
+                setCurrentItemShowing(MINUTE_INDEX, true, false);
+                mRadialTimePickerView.announceForAccessibility(newValue + ". " + mSelectMinutes);
+            } else {
+                updateHeaderHour(newValue, true);
+                mRadialTimePickerView.setContentDescription(
+                        mHourPickerDescription + ": " + newValue);
+            }
+        } else if (pickerIndex == MINUTE_INDEX){
+            updateHeaderMinute(newValue, true);
+            mRadialTimePickerView.setContentDescription(mMinutePickerDescription + ": " + newValue);
+        } else if (pickerIndex == AMPM_INDEX) {
+            updateAmPmLabelStates(newValue);
+        } else if (pickerIndex == ENABLE_PICKER_INDEX) {
+            if (!isTypedTimeFullyLegal()) {
+                mTypedTimes.clear();
+            }
+            finishKbMode();
+        }
+    }
+
+    private void updateHeaderHour(int value, boolean announce) {
+        final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale,
+                (mIs24HourView) ? "Hm" : "hm");
+        final int lengthPattern = bestDateTimePattern.length();
+        boolean hourWithTwoDigit = false;
+        char hourFormat = '\0';
+        // Check if the returned pattern is single or double 'H', 'h', 'K', 'k'. We also save
+        // the hour format that we found.
+        for (int i = 0; i < lengthPattern; i++) {
+            final char c = bestDateTimePattern.charAt(i);
+            if (c == 'H' || c == 'h' || c == 'K' || c == 'k') {
+                hourFormat = c;
+                if (i + 1 < lengthPattern && c == bestDateTimePattern.charAt(i + 1)) {
+                    hourWithTwoDigit = true;
+                }
+                break;
+            }
+        }
+        final String format;
+        if (hourWithTwoDigit) {
+            format = "%02d";
+        } else {
+            format = "%d";
+        }
+        if (mIs24HourView) {
+            // 'k' means 1-24 hour
+            if (hourFormat == 'k' && value == 0) {
+                value = 24;
+            }
+        } else {
+            // 'K' means 0-11 hour
+            value = modulo12(value, hourFormat == 'K');
+        }
+        CharSequence text = String.format(format, value);
+        mHourView.setText(text);
+        if (announce) {
+            tryAnnounceForAccessibility(text, true);
+        }
+    }
+
+    private void tryAnnounceForAccessibility(CharSequence text, boolean isHour) {
+        if (mLastAnnouncedIsHour != isHour || !text.equals(mLastAnnouncedText)) {
+            // TODO: Find a better solution, potentially live regions?
+            mDelegator.announceForAccessibility(text);
+            mLastAnnouncedText = text;
+            mLastAnnouncedIsHour = isHour;
+        }
+    }
+
+    private static int modulo12(int n, boolean startWithZero) {
+        int value = n % 12;
+        if (value == 0 && !startWithZero) {
+            value = 12;
+        }
+        return value;
+    }
+
+    /**
+     * The time separator is defined in the Unicode CLDR and cannot be supposed to be ":".
+     *
+     * See http://unicode.org/cldr/trac/browser/trunk/common/main
+     *
+     * We pass the correct "skeleton" depending on 12 or 24 hours view and then extract the
+     * separator as the character which is just after the hour marker in the returned pattern.
+     */
+    private void updateHeaderSeparator() {
+        final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale,
+                (mIs24HourView) ? "Hm" : "hm");
+        final String separatorText;
+        // See http://www.unicode.org/reports/tr35/tr35-dates.html for hour formats
+        final char[] hourFormats = {'H', 'h', 'K', 'k'};
+        int hIndex = lastIndexOfAny(bestDateTimePattern, hourFormats);
+        if (hIndex == -1) {
+            // Default case
+            separatorText = ":";
+        } else {
+            separatorText = Character.toString(bestDateTimePattern.charAt(hIndex + 1));
+        }
+        mSeparatorView.setText(separatorText);
+    }
+
+    static private int lastIndexOfAny(String str, char[] any) {
+        final int lengthAny = any.length;
+        if (lengthAny > 0) {
+            for (int i = str.length() - 1; i >= 0; i--) {
+                char c = str.charAt(i);
+                for (int j = 0; j < lengthAny; j++) {
+                    if (c == any[j]) {
+                        return i;
+                    }
+                }
+            }
+        }
+        return -1;
+    }
+
+    private void updateHeaderMinute(int value, boolean announceForAccessibility) {
+        if (value == 60) {
+            value = 0;
+        }
+        final CharSequence text = String.format(mCurrentLocale, "%02d", value);
+        mMinuteView.setText(text);
+        if (announceForAccessibility) {
+            tryAnnounceForAccessibility(text, false);
+        }
+    }
+
+    /**
+     * Show either Hours or Minutes.
+     */
+    private void setCurrentItemShowing(int index, boolean animateCircle, boolean announce) {
+        mRadialTimePickerView.setCurrentItemShowing(index, animateCircle);
+
+        if (index == HOUR_INDEX) {
+            int hours = mRadialTimePickerView.getCurrentHour();
+            if (!mIs24HourView) {
+                hours = hours % 12;
+            }
+            mRadialTimePickerView.setContentDescription(mHourPickerDescription + ": " + hours);
+            if (announce) {
+                mRadialTimePickerView.announceForAccessibility(mSelectHours);
+            }
+        } else {
+            int minutes = mRadialTimePickerView.getCurrentMinute();
+            mRadialTimePickerView.setContentDescription(mMinutePickerDescription + ": " + minutes);
+            if (announce) {
+                mRadialTimePickerView.announceForAccessibility(mSelectMinutes);
+            }
+        }
+
+        mHourView.setSelected(index == HOUR_INDEX);
+        mMinuteView.setSelected(index == MINUTE_INDEX);
+    }
+
+    private void setAmOrPm(int amOrPm) {
+        updateAmPmLabelStates(amOrPm);
+        mRadialTimePickerView.setAmOrPm(amOrPm);
+    }
+
+    /**
+     * For keyboard mode, processes key events.
+     *
+     * @param keyCode the pressed key.
+     *
+     * @return true if the key was successfully processed, false otherwise.
+     */
+    private boolean processKeyUp(int keyCode) {
+        if (keyCode == KeyEvent.KEYCODE_DEL) {
+            if (mInKbMode) {
+                if (!mTypedTimes.isEmpty()) {
+                    int deleted = deleteLastTypedKey();
+                    String deletedKeyStr;
+                    if (deleted == getAmOrPmKeyCode(AM)) {
+                        deletedKeyStr = mAmText;
+                    } else if (deleted == getAmOrPmKeyCode(PM)) {
+                        deletedKeyStr = mPmText;
+                    } else {
+                        deletedKeyStr = String.format("%d", getValFromKeyCode(deleted));
+                    }
+                    mRadialTimePickerView.announceForAccessibility(
+                            String.format(mDeletedKeyFormat, deletedKeyStr));
+                    updateDisplay(true);
+                }
+            }
+        } else if (keyCode == KeyEvent.KEYCODE_0 || keyCode == KeyEvent.KEYCODE_1
+                || keyCode == KeyEvent.KEYCODE_2 || keyCode == KeyEvent.KEYCODE_3
+                || keyCode == KeyEvent.KEYCODE_4 || keyCode == KeyEvent.KEYCODE_5
+                || keyCode == KeyEvent.KEYCODE_6 || keyCode == KeyEvent.KEYCODE_7
+                || keyCode == KeyEvent.KEYCODE_8 || keyCode == KeyEvent.KEYCODE_9
+                || (!mIs24HourView &&
+                (keyCode == getAmOrPmKeyCode(AM) || keyCode == getAmOrPmKeyCode(PM)))) {
+            if (!mInKbMode) {
+                if (mRadialTimePickerView == null) {
+                    // Something's wrong, because time picker should definitely not be null.
+                    Log.e(TAG, "Unable to initiate keyboard mode, TimePicker was null.");
+                    return true;
+                }
+                mTypedTimes.clear();
+                tryStartingKbMode(keyCode);
+                return true;
+            }
+            // We're already in keyboard mode.
+            if (addKeyIfLegal(keyCode)) {
+                updateDisplay(false);
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Try to start keyboard mode with the specified key.
+     *
+     * @param keyCode The key to use as the first press. Keyboard mode will not be started if the
+     * key is not legal to start with. Or, pass in -1 to get into keyboard mode without a starting
+     * key.
+     */
+    private void tryStartingKbMode(int keyCode) {
+        if (keyCode == -1 || addKeyIfLegal(keyCode)) {
+            mInKbMode = true;
+            onValidationChanged(false);
+            updateDisplay(false);
+            mRadialTimePickerView.setInputEnabled(false);
+        }
+    }
+
+    private boolean addKeyIfLegal(int keyCode) {
+        // If we're in 24hour mode, we'll need to check if the input is full. If in AM/PM mode,
+        // we'll need to see if AM/PM have been typed.
+        if ((mIs24HourView && mTypedTimes.size() == 4) ||
+                (!mIs24HourView && isTypedTimeFullyLegal())) {
+            return false;
+        }
+
+        mTypedTimes.add(keyCode);
+        if (!isTypedTimeLegalSoFar()) {
+            deleteLastTypedKey();
+            return false;
+        }
+
+        int val = getValFromKeyCode(keyCode);
+        mRadialTimePickerView.announceForAccessibility(String.format("%d", val));
+        // Automatically fill in 0's if AM or PM was legally entered.
+        if (isTypedTimeFullyLegal()) {
+            if (!mIs24HourView && mTypedTimes.size() <= 3) {
+                mTypedTimes.add(mTypedTimes.size() - 1, KeyEvent.KEYCODE_0);
+                mTypedTimes.add(mTypedTimes.size() - 1, KeyEvent.KEYCODE_0);
+            }
+            onValidationChanged(true);
+        }
+
+        return true;
+    }
+
+    /**
+     * Traverse the tree to see if the keys that have been typed so far are legal as is,
+     * or may become legal as more keys are typed (excluding backspace).
+     */
+    private boolean isTypedTimeLegalSoFar() {
+        Node node = mLegalTimesTree;
+        for (int keyCode : mTypedTimes) {
+            node = node.canReach(keyCode);
+            if (node == null) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Check if the time that has been typed so far is completely legal, as is.
+     */
+    private boolean isTypedTimeFullyLegal() {
+        if (mIs24HourView) {
+            // For 24-hour mode, the time is legal if the hours and minutes are each legal. Note:
+            // getEnteredTime() will ONLY call isTypedTimeFullyLegal() when NOT in 24hour mode.
+            int[] values = getEnteredTime(null);
+            return (values[0] >= 0 && values[1] >= 0 && values[1] < 60);
+        } else {
+            // For AM/PM mode, the time is legal if it contains an AM or PM, as those can only be
+            // legally added at specific times based on the tree's algorithm.
+            return (mTypedTimes.contains(getAmOrPmKeyCode(AM)) ||
+                    mTypedTimes.contains(getAmOrPmKeyCode(PM)));
+        }
+    }
+
+    private int deleteLastTypedKey() {
+        int deleted = mTypedTimes.remove(mTypedTimes.size() - 1);
+        if (!isTypedTimeFullyLegal()) {
+            onValidationChanged(false);
+        }
+        return deleted;
+    }
+
+    /**
+     * Get out of keyboard mode. If there is nothing in typedTimes, revert to TimePicker's time.
+     */
+    private void finishKbMode() {
+        mInKbMode = false;
+        if (!mTypedTimes.isEmpty()) {
+            int values[] = getEnteredTime(null);
+            mRadialTimePickerView.setCurrentHour(values[0]);
+            mRadialTimePickerView.setCurrentMinute(values[1]);
+            if (!mIs24HourView) {
+                mRadialTimePickerView.setAmOrPm(values[2]);
+            }
+            mTypedTimes.clear();
+        }
+        updateDisplay(false);
+        mRadialTimePickerView.setInputEnabled(true);
+    }
+
+    /**
+     * Update the hours, minutes, and AM/PM displays with the typed times. If the typedTimes is
+     * empty, either show an empty display (filled with the placeholder text), or update from the
+     * timepicker's values.
+     *
+     * @param allowEmptyDisplay if true, then if the typedTimes is empty, use the placeholder text.
+     * Otherwise, revert to the timepicker's values.
+     */
+    private void updateDisplay(boolean allowEmptyDisplay) {
+        if (!allowEmptyDisplay && mTypedTimes.isEmpty()) {
+            int hour = mRadialTimePickerView.getCurrentHour();
+            int minute = mRadialTimePickerView.getCurrentMinute();
+            updateHeaderHour(hour, false);
+            updateHeaderMinute(minute, false);
+            if (!mIs24HourView) {
+                updateAmPmLabelStates(hour < 12 ? AM : PM);
+            }
+            setCurrentItemShowing(mRadialTimePickerView.getCurrentItemShowing(), true, true);
+            onValidationChanged(true);
+        } else {
+            boolean[] enteredZeros = {false, false};
+            int[] values = getEnteredTime(enteredZeros);
+            String hourFormat = enteredZeros[0] ? "%02d" : "%2d";
+            String minuteFormat = (enteredZeros[1]) ? "%02d" : "%2d";
+            String hourStr = (values[0] == -1) ? mDoublePlaceholderText :
+                    String.format(hourFormat, values[0]).replace(' ', mPlaceholderText);
+            String minuteStr = (values[1] == -1) ? mDoublePlaceholderText :
+                    String.format(minuteFormat, values[1]).replace(' ', mPlaceholderText);
+            mHourView.setText(hourStr);
+            mHourView.setSelected(false);
+            mMinuteView.setText(minuteStr);
+            mMinuteView.setSelected(false);
+            if (!mIs24HourView) {
+                updateAmPmLabelStates(values[2]);
+            }
+        }
+    }
+
+    private int getValFromKeyCode(int keyCode) {
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_0:
+                return 0;
+            case KeyEvent.KEYCODE_1:
+                return 1;
+            case KeyEvent.KEYCODE_2:
+                return 2;
+            case KeyEvent.KEYCODE_3:
+                return 3;
+            case KeyEvent.KEYCODE_4:
+                return 4;
+            case KeyEvent.KEYCODE_5:
+                return 5;
+            case KeyEvent.KEYCODE_6:
+                return 6;
+            case KeyEvent.KEYCODE_7:
+                return 7;
+            case KeyEvent.KEYCODE_8:
+                return 8;
+            case KeyEvent.KEYCODE_9:
+                return 9;
+            default:
+                return -1;
+        }
+    }
+
+    /**
+     * Get the currently-entered time, as integer values of the hours and minutes typed.
+     *
+     * @param enteredZeros A size-2 boolean array, which the caller should initialize, and which
+     * may then be used for the caller to know whether zeros had been explicitly entered as either
+     * hours of minutes. This is helpful for deciding whether to show the dashes, or actual 0's.
+     *
+     * @return A size-3 int array. The first value will be the hours, the second value will be the
+     * minutes, and the third will be either AM or PM.
+     */
+    private int[] getEnteredTime(boolean[] enteredZeros) {
+        int amOrPm = -1;
+        int startIndex = 1;
+        if (!mIs24HourView && isTypedTimeFullyLegal()) {
+            int keyCode = mTypedTimes.get(mTypedTimes.size() - 1);
+            if (keyCode == getAmOrPmKeyCode(AM)) {
+                amOrPm = AM;
+            } else if (keyCode == getAmOrPmKeyCode(PM)){
+                amOrPm = PM;
+            }
+            startIndex = 2;
+        }
+        int minute = -1;
+        int hour = -1;
+        for (int i = startIndex; i <= mTypedTimes.size(); i++) {
+            int val = getValFromKeyCode(mTypedTimes.get(mTypedTimes.size() - i));
+            if (i == startIndex) {
+                minute = val;
+            } else if (i == startIndex+1) {
+                minute += 10 * val;
+                if (enteredZeros != null && val == 0) {
+                    enteredZeros[1] = true;
+                }
+            } else if (i == startIndex+2) {
+                hour = val;
+            } else if (i == startIndex+3) {
+                hour += 10 * val;
+                if (enteredZeros != null && val == 0) {
+                    enteredZeros[0] = true;
+                }
+            }
+        }
+
+        return new int[] { hour, minute, amOrPm };
+    }
+
+    /**
+     * Get the keycode value for AM and PM in the current language.
+     */
+    private int getAmOrPmKeyCode(int amOrPm) {
+        // Cache the codes.
+        if (mAmKeyCode == -1 || mPmKeyCode == -1) {
+            // Find the first character in the AM/PM text that is unique.
+            KeyCharacterMap kcm = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
+            char amChar;
+            char pmChar;
+            for (int i = 0; i < Math.max(mAmText.length(), mPmText.length()); i++) {
+                amChar = mAmText.toLowerCase(mCurrentLocale).charAt(i);
+                pmChar = mPmText.toLowerCase(mCurrentLocale).charAt(i);
+                if (amChar != pmChar) {
+                    KeyEvent[] events = kcm.getEvents(new char[]{amChar, pmChar});
+                    // There should be 4 events: a down and up for both AM and PM.
+                    if (events != null && events.length == 4) {
+                        mAmKeyCode = events[0].getKeyCode();
+                        mPmKeyCode = events[2].getKeyCode();
+                    } else {
+                        Log.e(TAG, "Unable to find keycodes for AM and PM.");
+                    }
+                    break;
+                }
+            }
+        }
+        if (amOrPm == AM) {
+            return mAmKeyCode;
+        } else if (amOrPm == PM) {
+            return mPmKeyCode;
+        }
+
+        return -1;
+    }
+
+    /**
+     * Create a tree for deciding what keys can legally be typed.
+     */
+    private void generateLegalTimesTree() {
+        // Create a quick cache of numbers to their keycodes.
+        final int k0 = KeyEvent.KEYCODE_0;
+        final int k1 = KeyEvent.KEYCODE_1;
+        final int k2 = KeyEvent.KEYCODE_2;
+        final int k3 = KeyEvent.KEYCODE_3;
+        final int k4 = KeyEvent.KEYCODE_4;
+        final int k5 = KeyEvent.KEYCODE_5;
+        final int k6 = KeyEvent.KEYCODE_6;
+        final int k7 = KeyEvent.KEYCODE_7;
+        final int k8 = KeyEvent.KEYCODE_8;
+        final int k9 = KeyEvent.KEYCODE_9;
+
+        // The root of the tree doesn't contain any numbers.
+        mLegalTimesTree = new Node();
+        if (mIs24HourView) {
+            // We'll be re-using these nodes, so we'll save them.
+            Node minuteFirstDigit = new Node(k0, k1, k2, k3, k4, k5);
+            Node minuteSecondDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9);
+            // The first digit must be followed by the second digit.
+            minuteFirstDigit.addChild(minuteSecondDigit);
+
+            // The first digit may be 0-1.
+            Node firstDigit = new Node(k0, k1);
+            mLegalTimesTree.addChild(firstDigit);
+
+            // When the first digit is 0-1, the second digit may be 0-5.
+            Node secondDigit = new Node(k0, k1, k2, k3, k4, k5);
+            firstDigit.addChild(secondDigit);
+            // We may now be followed by the first minute digit. E.g. 00:09, 15:58.
+            secondDigit.addChild(minuteFirstDigit);
+
+            // When the first digit is 0-1, and the second digit is 0-5, the third digit may be 6-9.
+            Node thirdDigit = new Node(k6, k7, k8, k9);
+            // The time must now be finished. E.g. 0:55, 1:08.
+            secondDigit.addChild(thirdDigit);
+
+            // When the first digit is 0-1, the second digit may be 6-9.
+            secondDigit = new Node(k6, k7, k8, k9);
+            firstDigit.addChild(secondDigit);
+            // We must now be followed by the first minute digit. E.g. 06:50, 18:20.
+            secondDigit.addChild(minuteFirstDigit);
+
+            // The first digit may be 2.
+            firstDigit = new Node(k2);
+            mLegalTimesTree.addChild(firstDigit);
+
+            // When the first digit is 2, the second digit may be 0-3.
+            secondDigit = new Node(k0, k1, k2, k3);
+            firstDigit.addChild(secondDigit);
+            // We must now be followed by the first minute digit. E.g. 20:50, 23:09.
+            secondDigit.addChild(minuteFirstDigit);
+
+            // When the first digit is 2, the second digit may be 4-5.
+            secondDigit = new Node(k4, k5);
+            firstDigit.addChild(secondDigit);
+            // We must now be followd by the last minute digit. E.g. 2:40, 2:53.
+            secondDigit.addChild(minuteSecondDigit);
+
+            // The first digit may be 3-9.
+            firstDigit = new Node(k3, k4, k5, k6, k7, k8, k9);
+            mLegalTimesTree.addChild(firstDigit);
+            // We must now be followed by the first minute digit. E.g. 3:57, 8:12.
+            firstDigit.addChild(minuteFirstDigit);
+        } else {
+            // We'll need to use the AM/PM node a lot.
+            // Set up AM and PM to respond to "a" and "p".
+            Node ampm = new Node(getAmOrPmKeyCode(AM), getAmOrPmKeyCode(PM));
+
+            // The first hour digit may be 1.
+            Node firstDigit = new Node(k1);
+            mLegalTimesTree.addChild(firstDigit);
+            // We'll allow quick input of on-the-hour times. E.g. 1pm.
+            firstDigit.addChild(ampm);
+
+            // When the first digit is 1, the second digit may be 0-2.
+            Node secondDigit = new Node(k0, k1, k2);
+            firstDigit.addChild(secondDigit);
+            // Also for quick input of on-the-hour times. E.g. 10pm, 12am.
+            secondDigit.addChild(ampm);
+
+            // When the first digit is 1, and the second digit is 0-2, the third digit may be 0-5.
+            Node thirdDigit = new Node(k0, k1, k2, k3, k4, k5);
+            secondDigit.addChild(thirdDigit);
+            // The time may be finished now. E.g. 1:02pm, 1:25am.
+            thirdDigit.addChild(ampm);
+
+            // When the first digit is 1, the second digit is 0-2, and the third digit is 0-5,
+            // the fourth digit may be 0-9.
+            Node fourthDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9);
+            thirdDigit.addChild(fourthDigit);
+            // The time must be finished now. E.g. 10:49am, 12:40pm.
+            fourthDigit.addChild(ampm);
+
+            // When the first digit is 1, and the second digit is 0-2, the third digit may be 6-9.
+            thirdDigit = new Node(k6, k7, k8, k9);
+            secondDigit.addChild(thirdDigit);
+            // The time must be finished now. E.g. 1:08am, 1:26pm.
+            thirdDigit.addChild(ampm);
+
+            // When the first digit is 1, the second digit may be 3-5.
+            secondDigit = new Node(k3, k4, k5);
+            firstDigit.addChild(secondDigit);
+
+            // When the first digit is 1, and the second digit is 3-5, the third digit may be 0-9.
+            thirdDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9);
+            secondDigit.addChild(thirdDigit);
+            // The time must be finished now. E.g. 1:39am, 1:50pm.
+            thirdDigit.addChild(ampm);
+
+            // The hour digit may be 2-9.
+            firstDigit = new Node(k2, k3, k4, k5, k6, k7, k8, k9);
+            mLegalTimesTree.addChild(firstDigit);
+            // We'll allow quick input of on-the-hour-times. E.g. 2am, 5pm.
+            firstDigit.addChild(ampm);
+
+            // When the first digit is 2-9, the second digit may be 0-5.
+            secondDigit = new Node(k0, k1, k2, k3, k4, k5);
+            firstDigit.addChild(secondDigit);
+
+            // When the first digit is 2-9, and the second digit is 0-5, the third digit may be 0-9.
+            thirdDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9);
+            secondDigit.addChild(thirdDigit);
+            // The time must be finished now. E.g. 2:57am, 9:30pm.
+            thirdDigit.addChild(ampm);
+        }
+    }
+
+    /**
+     * Simple node class to be used for traversal to check for legal times.
+     * mLegalKeys represents the keys that can be typed to get to the node.
+     * mChildren are the children that can be reached from this node.
+     */
+    private class Node {
+        private int[] mLegalKeys;
+        private ArrayList<Node> mChildren;
+
+        public Node(int... legalKeys) {
+            mLegalKeys = legalKeys;
+            mChildren = new ArrayList<Node>();
+        }
+
+        public void addChild(Node child) {
+            mChildren.add(child);
+        }
+
+        public boolean containsKey(int key) {
+            for (int i = 0; i < mLegalKeys.length; i++) {
+                if (mLegalKeys[i] == key) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        public Node canReach(int key) {
+            if (mChildren == null) {
+                return null;
+            }
+            for (Node child : mChildren) {
+                if (child.containsKey(key)) {
+                    return child;
+                }
+            }
+            return null;
+        }
+    }
+
+    private final View.OnClickListener mClickListener = new View.OnClickListener() {
+        @Override
+        public void onClick(View v) {
+
+            final int amOrPm;
+            switch (v.getId()) {
+                case R.id.am_label:
+                    setAmOrPm(AM);
+                    break;
+                case R.id.pm_label:
+                    setAmOrPm(PM);
+                    break;
+                case R.id.hours:
+                    setCurrentItemShowing(HOUR_INDEX, true, true);
+                    break;
+                case R.id.minutes:
+                    setCurrentItemShowing(MINUTE_INDEX, true, true);
+                    break;
+                default:
+                    // Failed to handle this click, don't vibrate.
+                    return;
+            }
+
+            tryVibrate();
+        }
+    };
+
+    private final View.OnKeyListener mKeyListener = new View.OnKeyListener() {
+        @Override
+        public boolean onKey(View v, int keyCode, KeyEvent event) {
+            if (event.getAction() == KeyEvent.ACTION_UP) {
+                return processKeyUp(keyCode);
+            }
+            return false;
+        }
+    };
+
+    private final View.OnFocusChangeListener mFocusListener = new View.OnFocusChangeListener() {
+        @Override
+        public void onFocusChange(View v, boolean hasFocus) {
+            if (!hasFocus && mInKbMode && isTypedTimeFullyLegal()) {
+                finishKbMode();
+
+                if (mOnTimeChangedListener != null) {
+                    mOnTimeChangedListener.onTimeChanged(mDelegator,
+                            mRadialTimePickerView.getCurrentHour(),
+                            mRadialTimePickerView.getCurrentMinute());
+                }
+            }
+        }
+    };
 }
diff --git a/core/java/android/widget/TimePickerSpinnerDelegate.java b/core/java/android/widget/TimePickerSpinnerDelegate.java
index d9c4114..e162f4a 100644
--- a/core/java/android/widget/TimePickerSpinnerDelegate.java
+++ b/core/java/android/widget/TimePickerSpinnerDelegate.java
@@ -17,376 +17,365 @@
 package android.widget;
 
 import android.content.Context;
-import android.content.res.ColorStateList;
 import android.content.res.Configuration;
-import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.text.TextUtils;
 import android.text.format.DateFormat;
 import android.text.format.DateUtils;
 import android.util.AttributeSet;
-import android.util.Log;
-import android.util.TypedValue;
-import android.view.HapticFeedbackConstants;
-import android.view.KeyCharacterMap;
-import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
-
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputMethodManager;
 import com.android.internal.R;
 
-import java.util.ArrayList;
+import java.text.DateFormatSymbols;
 import java.util.Calendar;
 import java.util.Locale;
 
+import libcore.icu.LocaleData;
+
+import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_AUTO;
+import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_YES;
+
 /**
- * A delegate implementing the radial clock-based TimePicker.
+ * A delegate implementing the basic spinner-based TimePicker.
  */
-class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate implements
-        RadialTimePickerView.OnValueSelectedListener {
-
-    private static final String TAG = "TimePickerDelegate";
-
-    // Index used by RadialPickerLayout
-    private static final int HOUR_INDEX = 0;
-    private static final int MINUTE_INDEX = 1;
-
-    // NOT a real index for the purpose of what's showing.
-    private static final int AMPM_INDEX = 2;
-
-    // Also NOT a real index, just used for keyboard mode.
-    private static final int ENABLE_PICKER_INDEX = 3;
-
-    static final int AM = 0;
-    static final int PM = 1;
-
+class TimePickerSpinnerDelegate extends TimePicker.AbstractTimePickerDelegate {
     private static final boolean DEFAULT_ENABLED_STATE = true;
-    private boolean mIsEnabled = DEFAULT_ENABLED_STATE;
-
     private static final int HOURS_IN_HALF_DAY = 12;
 
-    private final View mHeaderView;
-    private final TextView mHourView;
-    private final TextView mMinuteView;
-    private final View mAmPmLayout;
-    private final CheckedTextView mAmLabel;
-    private final CheckedTextView mPmLabel;
-    private final RadialTimePickerView mRadialTimePickerView;
-    private final TextView mSeparatorView;
-
-    private final String mAmText;
-    private final String mPmText;
-
-    private final float mDisabledAlpha;
-
-    private boolean mAllowAutoAdvance;
-    private int mInitialHourOfDay;
-    private int mInitialMinute;
+    // state
     private boolean mIs24HourView;
+    private boolean mIsAm;
 
-    // For hardware IME input.
-    private char mPlaceholderText;
-    private String mDoublePlaceholderText;
-    private String mDeletedKeyFormat;
-    private boolean mInKbMode;
-    private ArrayList<Integer> mTypedTimes = new ArrayList<Integer>();
-    private Node mLegalTimesTree;
-    private int mAmKeyCode;
-    private int mPmKeyCode;
+    // ui components
+    private final NumberPicker mHourSpinner;
+    private final NumberPicker mMinuteSpinner;
+    private final NumberPicker mAmPmSpinner;
+    private final EditText mHourSpinnerInput;
+    private final EditText mMinuteSpinnerInput;
+    private final EditText mAmPmSpinnerInput;
+    private final TextView mDivider;
 
-    // Accessibility strings.
-    private String mHourPickerDescription;
-    private String mSelectHours;
-    private String mMinutePickerDescription;
-    private String mSelectMinutes;
+    // Note that the legacy implementation of the TimePicker is
+    // using a button for toggling between AM/PM while the new
+    // version uses a NumberPicker spinner. Therefore the code
+    // accommodates these two cases to be backwards compatible.
+    private final Button mAmPmButton;
 
-    // Most recent time announcement values for accessibility.
-    private CharSequence mLastAnnouncedText;
-    private boolean mLastAnnouncedIsHour;
+    private final String[] mAmPmStrings;
 
+    private boolean mIsEnabled = DEFAULT_ENABLED_STATE;
     private Calendar mTempCalendar;
+    private boolean mHourWithTwoDigit;
+    private char mHourFormat;
 
     public TimePickerSpinnerDelegate(TimePicker delegator, Context context, AttributeSet attrs,
             int defStyleAttr, int defStyleRes) {
         super(delegator, context);
 
         // process style attributes
-        final TypedArray a = mContext.obtainStyledAttributes(attrs,
-                R.styleable.TimePicker, defStyleAttr, defStyleRes);
-        final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
-                Context.LAYOUT_INFLATER_SERVICE);
-        final Resources res = mContext.getResources();
-
-        mHourPickerDescription = res.getString(R.string.hour_picker_description);
-        mSelectHours = res.getString(R.string.select_hours);
-        mMinutePickerDescription = res.getString(R.string.minute_picker_description);
-        mSelectMinutes = res.getString(R.string.select_minutes);
-
-        String[] amPmStrings = TimePickerClockDelegate.getAmPmStrings(context);
-        mAmText = amPmStrings[0];
-        mPmText = amPmStrings[1];
-
-        final int layoutResourceId = a.getResourceId(R.styleable.TimePicker_internalLayout,
-                R.layout.time_picker_holo);
-        final View mainView = inflater.inflate(layoutResourceId, delegator);
-
-        mHeaderView = mainView.findViewById(R.id.time_header);
-        mHeaderView.setBackground(a.getDrawable(R.styleable.TimePicker_headerBackground));
-
-        // Set up hour/minute labels.
-        mHourView = (TextView) mHeaderView.findViewById(R.id.hours);
-        mHourView.setOnClickListener(mClickListener);
-        mSeparatorView = (TextView) mHeaderView.findViewById(R.id.separator);
-        mMinuteView = (TextView) mHeaderView.findViewById(R.id.minutes);
-        mMinuteView.setOnClickListener(mClickListener);
-
-        final int headerTimeTextAppearance = a.getResourceId(
-                R.styleable.TimePicker_headerTimeTextAppearance, 0);
-        if (headerTimeTextAppearance != 0) {
-            mHourView.setTextAppearance(context, headerTimeTextAppearance);
-            mSeparatorView.setTextAppearance(context, headerTimeTextAppearance);
-            mMinuteView.setTextAppearance(context, headerTimeTextAppearance);
-        }
-
-        // TODO: This can be removed once we support themed color state lists.
-        final int headerSelectedTextColor = a.getColor(
-                R.styleable.TimePicker_headerSelectedTextColor,
-                res.getColor(R.color.timepicker_default_selector_color_material));
-        mHourView.setTextColor(ColorStateList.addFirstIfMissing(mHourView.getTextColors(),
-                R.attr.state_selected, headerSelectedTextColor));
-        mMinuteView.setTextColor(ColorStateList.addFirstIfMissing(mMinuteView.getTextColors(),
-                R.attr.state_selected, headerSelectedTextColor));
-
-        // Set up AM/PM labels.
-        mAmPmLayout = mHeaderView.findViewById(R.id.ampm_layout);
-        mAmLabel = (CheckedTextView) mAmPmLayout.findViewById(R.id.am_label);
-        mAmLabel.setText(amPmStrings[0]);
-        mAmLabel.setOnClickListener(mClickListener);
-        mPmLabel = (CheckedTextView) mAmPmLayout.findViewById(R.id.pm_label);
-        mPmLabel.setText(amPmStrings[1]);
-        mPmLabel.setOnClickListener(mClickListener);
-
-        final int headerAmPmTextAppearance = a.getResourceId(
-                R.styleable.TimePicker_headerAmPmTextAppearance, 0);
-        if (headerAmPmTextAppearance != 0) {
-            mAmLabel.setTextAppearance(context, headerAmPmTextAppearance);
-            mPmLabel.setTextAppearance(context, headerAmPmTextAppearance);
-        }
-
+        final TypedArray a = mContext.obtainStyledAttributes(
+                attrs, R.styleable.TimePicker, defStyleAttr, defStyleRes);
+        final int layoutResourceId = a.getResourceId(
+                R.styleable.TimePicker_legacyLayout, R.layout.time_picker_legacy);
         a.recycle();
 
-        // Pull disabled alpha from theme.
-        final TypedValue outValue = new TypedValue();
-        context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, outValue, true);
-        mDisabledAlpha = outValue.getFloat();
+        final LayoutInflater inflater = LayoutInflater.from(mContext);
+        inflater.inflate(layoutResourceId, mDelegator, true);
 
-        mRadialTimePickerView = (RadialTimePickerView) mainView.findViewById(
-                R.id.radial_picker);
+        // hour
+        mHourSpinner = (NumberPicker) delegator.findViewById(R.id.hour);
+        mHourSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
+            public void onValueChange(NumberPicker spinner, int oldVal, int newVal) {
+                updateInputState();
+                if (!is24HourView()) {
+                    if ((oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY) ||
+                            (oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1)) {
+                        mIsAm = !mIsAm;
+                        updateAmPmControl();
+                    }
+                }
+                onTimeChanged();
+            }
+        });
+        mHourSpinnerInput = (EditText) mHourSpinner.findViewById(R.id.numberpicker_input);
+        mHourSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
 
-        setupListeners();
-
-        mAllowAutoAdvance = true;
-
-        // Set up for keyboard mode.
-        mDoublePlaceholderText = res.getString(R.string.time_placeholder);
-        mDeletedKeyFormat = res.getString(R.string.deleted_key);
-        mPlaceholderText = mDoublePlaceholderText.charAt(0);
-        mAmKeyCode = mPmKeyCode = -1;
-        generateLegalTimesTree();
-
-        // Initialize with current time
-        final Calendar calendar = Calendar.getInstance(mCurrentLocale);
-        final int currentHour = calendar.get(Calendar.HOUR_OF_DAY);
-        final int currentMinute = calendar.get(Calendar.MINUTE);
-        initialize(currentHour, currentMinute, false /* 12h */, HOUR_INDEX);
-    }
-
-    private void initialize(int hourOfDay, int minute, boolean is24HourView, int index) {
-        mInitialHourOfDay = hourOfDay;
-        mInitialMinute = minute;
-        mIs24HourView = is24HourView;
-        mInKbMode = false;
-        updateUI(index);
-    }
-
-    private void setupListeners() {
-        mHeaderView.setOnKeyListener(mKeyListener);
-        mHeaderView.setOnFocusChangeListener(mFocusListener);
-        mHeaderView.setFocusable(true);
-
-        mRadialTimePickerView.setOnValueSelectedListener(this);
-    }
-
-    private void updateUI(int index) {
-        // Update RadialPicker values
-        updateRadialPicker(index);
-        // Enable or disable the AM/PM view.
-        updateHeaderAmPm();
-        // Update Hour and Minutes
-        updateHeaderHour(mInitialHourOfDay, false);
-        // Update time separator
-        updateHeaderSeparator();
-        // Update Minutes
-        updateHeaderMinute(mInitialMinute, false);
-        // Invalidate everything
-        mDelegator.invalidate();
-    }
-
-    private void updateRadialPicker(int index) {
-        mRadialTimePickerView.initialize(mInitialHourOfDay, mInitialMinute, mIs24HourView);
-        setCurrentItemShowing(index, false, true);
-    }
-
-    private int computeMaxWidthOfNumbers(int max) {
-        TextView tempView = new TextView(mContext);
-        tempView.setTextAppearance(mContext, R.style.TextAppearance_Material_TimePicker_TimeLabel);
-        ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
-                ViewGroup.LayoutParams.WRAP_CONTENT);
-        tempView.setLayoutParams(lp);
-        int maxWidth = 0;
-        for (int minutes = 0; minutes < max; minutes++) {
-            final String text = String.format("%02d", minutes);
-            tempView.setText(text);
-            tempView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
-            maxWidth = Math.max(maxWidth, tempView.getMeasuredWidth());
+        // divider (only for the new widget style)
+        mDivider = (TextView) mDelegator.findViewById(R.id.divider);
+        if (mDivider != null) {
+            setDividerText();
         }
-        return maxWidth;
-    }
 
-    private void updateHeaderAmPm() {
-        if (mIs24HourView) {
-            mAmPmLayout.setVisibility(View.GONE);
+        // minute
+        mMinuteSpinner = (NumberPicker) mDelegator.findViewById(R.id.minute);
+        mMinuteSpinner.setMinValue(0);
+        mMinuteSpinner.setMaxValue(59);
+        mMinuteSpinner.setOnLongPressUpdateInterval(100);
+        mMinuteSpinner.setFormatter(NumberPicker.getTwoDigitFormatter());
+        mMinuteSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
+            public void onValueChange(NumberPicker spinner, int oldVal, int newVal) {
+                updateInputState();
+                int minValue = mMinuteSpinner.getMinValue();
+                int maxValue = mMinuteSpinner.getMaxValue();
+                if (oldVal == maxValue && newVal == minValue) {
+                    int newHour = mHourSpinner.getValue() + 1;
+                    if (!is24HourView() && newHour == HOURS_IN_HALF_DAY) {
+                        mIsAm = !mIsAm;
+                        updateAmPmControl();
+                    }
+                    mHourSpinner.setValue(newHour);
+                } else if (oldVal == minValue && newVal == maxValue) {
+                    int newHour = mHourSpinner.getValue() - 1;
+                    if (!is24HourView() && newHour == HOURS_IN_HALF_DAY - 1) {
+                        mIsAm = !mIsAm;
+                        updateAmPmControl();
+                    }
+                    mHourSpinner.setValue(newHour);
+                }
+                onTimeChanged();
+            }
+        });
+        mMinuteSpinnerInput = (EditText) mMinuteSpinner.findViewById(R.id.numberpicker_input);
+        mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
+
+        // Get the localized am/pm strings and use them in the spinner.
+        mAmPmStrings = getAmPmStrings(context);
+
+        // am/pm
+        final View amPmView = mDelegator.findViewById(R.id.amPm);
+        if (amPmView instanceof Button) {
+            mAmPmSpinner = null;
+            mAmPmSpinnerInput = null;
+            mAmPmButton = (Button) amPmView;
+            mAmPmButton.setOnClickListener(new View.OnClickListener() {
+                public void onClick(View button) {
+                    button.requestFocus();
+                    mIsAm = !mIsAm;
+                    updateAmPmControl();
+                    onTimeChanged();
+                }
+            });
         } else {
-            final String bestDateTimePattern = DateFormat.getBestDateTimePattern(
-                    mCurrentLocale, "hm");
-            boolean amPmOnLeft = bestDateTimePattern.startsWith("a");
-            if (TextUtils.getLayoutDirectionFromLocale(mCurrentLocale) ==
-                    View.LAYOUT_DIRECTION_RTL) {
-                amPmOnLeft = !amPmOnLeft;
-            }
-
-            final ViewGroup.MarginLayoutParams params =
-                    (ViewGroup.MarginLayoutParams) mAmPmLayout.getLayoutParams();
-
-            if (amPmOnLeft) {
-                params.leftMargin = 0;
-                params.rightMargin = computeMaxWidthOfNumbers(12 /* for hours */);
-            } else {
-                params.leftMargin = computeMaxWidthOfNumbers(60 /* for minutes */);
-                params.rightMargin = 0;
-            }
-
-            mAmPmLayout.setLayoutParams(params);
-            mAmPmLayout.setVisibility(View.VISIBLE);
-
-            updateAmPmLabelStates(mInitialHourOfDay < 12 ? AM : PM);
+            mAmPmButton = null;
+            mAmPmSpinner = (NumberPicker) amPmView;
+            mAmPmSpinner.setMinValue(0);
+            mAmPmSpinner.setMaxValue(1);
+            mAmPmSpinner.setDisplayedValues(mAmPmStrings);
+            mAmPmSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
+                public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
+                    updateInputState();
+                    picker.requestFocus();
+                    mIsAm = !mIsAm;
+                    updateAmPmControl();
+                    onTimeChanged();
+                }
+            });
+            mAmPmSpinnerInput = (EditText) mAmPmSpinner.findViewById(R.id.numberpicker_input);
+            mAmPmSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE);
         }
+
+        if (isAmPmAtStart()) {
+            // Move the am/pm view to the beginning
+            ViewGroup amPmParent = (ViewGroup) delegator.findViewById(R.id.timePickerLayout);
+            amPmParent.removeView(amPmView);
+            amPmParent.addView(amPmView, 0);
+            // Swap layout margins if needed. They may be not symmetrical (Old Standard Theme
+            // for example and not for Holo Theme)
+            ViewGroup.MarginLayoutParams lp =
+                    (ViewGroup.MarginLayoutParams) amPmView.getLayoutParams();
+            final int startMargin = lp.getMarginStart();
+            final int endMargin = lp.getMarginEnd();
+            if (startMargin != endMargin) {
+                lp.setMarginStart(endMargin);
+                lp.setMarginEnd(startMargin);
+            }
+        }
+
+        getHourFormatData();
+
+        // update controls to initial state
+        updateHourControl();
+        updateMinuteControl();
+        updateAmPmControl();
+
+        // set to current time
+        setCurrentHour(mTempCalendar.get(Calendar.HOUR_OF_DAY));
+        setCurrentMinute(mTempCalendar.get(Calendar.MINUTE));
+
+        if (!isEnabled()) {
+            setEnabled(false);
+        }
+
+        // set the content descriptions
+        setContentDescriptions();
+
+        // If not explicitly specified this view is important for accessibility.
+        if (mDelegator.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
+            mDelegator.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
+        }
+    }
+
+    private void getHourFormatData() {
+        final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale,
+                (mIs24HourView) ? "Hm" : "hm");
+        final int lengthPattern = bestDateTimePattern.length();
+        mHourWithTwoDigit = false;
+        char hourFormat = '\0';
+        // Check if the returned pattern is single or double 'H', 'h', 'K', 'k'. We also save
+        // the hour format that we found.
+        for (int i = 0; i < lengthPattern; i++) {
+            final char c = bestDateTimePattern.charAt(i);
+            if (c == 'H' || c == 'h' || c == 'K' || c == 'k') {
+                mHourFormat = c;
+                if (i + 1 < lengthPattern && c == bestDateTimePattern.charAt(i + 1)) {
+                    mHourWithTwoDigit = true;
+                }
+                break;
+            }
+        }
+    }
+
+    private boolean isAmPmAtStart() {
+        final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale,
+                "hm" /* skeleton */);
+
+        return bestDateTimePattern.startsWith("a");
     }
 
     /**
-     * Set the current hour.
+     * The time separator is defined in the Unicode CLDR and cannot be supposed to be ":".
+     *
+     * See http://unicode.org/cldr/trac/browser/trunk/common/main
+     *
+     * We pass the correct "skeleton" depending on 12 or 24 hours view and then extract the
+     * separator as the character which is just after the hour marker in the returned pattern.
      */
+    private void setDividerText() {
+        final String skeleton = (mIs24HourView) ? "Hm" : "hm";
+        final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale,
+                skeleton);
+        final String separatorText;
+        int hourIndex = bestDateTimePattern.lastIndexOf('H');
+        if (hourIndex == -1) {
+            hourIndex = bestDateTimePattern.lastIndexOf('h');
+        }
+        if (hourIndex == -1) {
+            // Default case
+            separatorText = ":";
+        } else {
+            int minuteIndex = bestDateTimePattern.indexOf('m', hourIndex + 1);
+            if  (minuteIndex == -1) {
+                separatorText = Character.toString(bestDateTimePattern.charAt(hourIndex + 1));
+            } else {
+                separatorText = bestDateTimePattern.substring(hourIndex + 1, minuteIndex);
+            }
+        }
+        mDivider.setText(separatorText);
+    }
+
     @Override
     public void setCurrentHour(Integer currentHour) {
-        if (mInitialHourOfDay == currentHour) {
-            return;
-        }
-        mInitialHourOfDay = currentHour;
-        updateHeaderHour(currentHour, true);
-        updateHeaderAmPm();
-        mRadialTimePickerView.setCurrentHour(currentHour);
-        mRadialTimePickerView.setAmOrPm(mInitialHourOfDay < 12 ? AM : PM);
-        mDelegator.invalidate();
-        onTimeChanged();
+        setCurrentHour(currentHour, true);
     }
 
-    /**
-     * @return The current hour in the range (0-23).
-     */
+    private void setCurrentHour(Integer currentHour, boolean notifyTimeChanged) {
+        // why was Integer used in the first place?
+        if (currentHour == null || currentHour == getCurrentHour()) {
+            return;
+        }
+        if (!is24HourView()) {
+            // convert [0,23] ordinal to wall clock display
+            if (currentHour >= HOURS_IN_HALF_DAY) {
+                mIsAm = false;
+                if (currentHour > HOURS_IN_HALF_DAY) {
+                    currentHour = currentHour - HOURS_IN_HALF_DAY;
+                }
+            } else {
+                mIsAm = true;
+                if (currentHour == 0) {
+                    currentHour = HOURS_IN_HALF_DAY;
+                }
+            }
+            updateAmPmControl();
+        }
+        mHourSpinner.setValue(currentHour);
+        if (notifyTimeChanged) {
+            onTimeChanged();
+        }
+    }
+
     @Override
     public Integer getCurrentHour() {
-        int currentHour = mRadialTimePickerView.getCurrentHour();
-        if (mIs24HourView) {
+        int currentHour = mHourSpinner.getValue();
+        if (is24HourView()) {
             return currentHour;
+        } else if (mIsAm) {
+            return currentHour % HOURS_IN_HALF_DAY;
         } else {
-            switch(mRadialTimePickerView.getAmOrPm()) {
-                case PM:
-                    return (currentHour % HOURS_IN_HALF_DAY) + HOURS_IN_HALF_DAY;
-                case AM:
-                default:
-                    return currentHour % HOURS_IN_HALF_DAY;
-            }
+            return (currentHour % HOURS_IN_HALF_DAY) + HOURS_IN_HALF_DAY;
         }
     }
 
-    /**
-     * Set the current minute (0-59).
-     */
     @Override
     public void setCurrentMinute(Integer currentMinute) {
-        if (mInitialMinute == currentMinute) {
+        if (currentMinute == getCurrentMinute()) {
             return;
         }
-        mInitialMinute = currentMinute;
-        updateHeaderMinute(currentMinute, true);
-        mRadialTimePickerView.setCurrentMinute(currentMinute);
-        mDelegator.invalidate();
+        mMinuteSpinner.setValue(currentMinute);
         onTimeChanged();
     }
 
-    /**
-     * @return The current minute.
-     */
     @Override
     public Integer getCurrentMinute() {
-        return mRadialTimePickerView.getCurrentMinute();
+        return mMinuteSpinner.getValue();
     }
 
-    /**
-     * Set whether in 24 hour or AM/PM mode.
-     *
-     * @param is24HourView True = 24 hour mode. False = AM/PM.
-     */
     @Override
     public void setIs24HourView(Boolean is24HourView) {
-        if (is24HourView == mIs24HourView) {
+        if (mIs24HourView == is24HourView) {
             return;
         }
+        // cache the current hour since spinner range changes and BEFORE changing mIs24HourView!!
+        int currentHour = getCurrentHour();
+        // Order is important here.
         mIs24HourView = is24HourView;
-        generateLegalTimesTree();
-        int hour = mRadialTimePickerView.getCurrentHour();
-        mInitialHourOfDay = hour;
-        updateHeaderHour(hour, false);
-        updateHeaderAmPm();
-        updateRadialPicker(mRadialTimePickerView.getCurrentItemShowing());
-        mDelegator.invalidate();
+        getHourFormatData();
+        updateHourControl();
+        // set value after spinner range is updated
+        setCurrentHour(currentHour, false);
+        updateMinuteControl();
+        updateAmPmControl();
     }
 
-    /**
-     * @return true if this is in 24 hour view else false.
-     */
     @Override
     public boolean is24HourView() {
         return mIs24HourView;
     }
 
     @Override
-    public void setOnTimeChangedListener(TimePicker.OnTimeChangedListener callback) {
-        mOnTimeChangedListener = callback;
+    public void setOnTimeChangedListener(TimePicker.OnTimeChangedListener onTimeChangedListener) {
+        mOnTimeChangedListener = onTimeChangedListener;
     }
 
     @Override
     public void setEnabled(boolean enabled) {
-        mHourView.setEnabled(enabled);
-        mMinuteView.setEnabled(enabled);
-        mAmLabel.setEnabled(enabled);
-        mPmLabel.setEnabled(enabled);
-        mRadialTimePickerView.setEnabled(enabled);
+        mMinuteSpinner.setEnabled(enabled);
+        if (mDivider != null) {
+            mDivider.setEnabled(enabled);
+        }
+        mHourSpinner.setEnabled(enabled);
+        if (mAmPmSpinner != null) {
+            mAmPmSpinner.setEnabled(enabled);
+        } else {
+            mAmPmButton.setEnabled(enabled);
+        }
         mIsEnabled = enabled;
     }
 
@@ -397,38 +386,24 @@
 
     @Override
     public int getBaseline() {
-        // does not support baseline alignment
-        return -1;
+        return mHourSpinner.getBaseline();
     }
 
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
-        updateUI(mRadialTimePickerView.getCurrentItemShowing());
+        setCurrentLocale(newConfig.locale);
     }
 
     @Override
     public Parcelable onSaveInstanceState(Parcelable superState) {
-        return new SavedState(superState, getCurrentHour(), getCurrentMinute(),
-                is24HourView(), inKbMode(), getTypedTimes(), getCurrentItemShowing());
+        return new SavedState(superState, getCurrentHour(), getCurrentMinute());
     }
 
     @Override
     public void onRestoreInstanceState(Parcelable state) {
         SavedState ss = (SavedState) state;
-        setInKbMode(ss.inKbMode());
-        setTypedTimes(ss.getTypesTimes());
-        initialize(ss.getHour(), ss.getMinute(), ss.is24HourMode(), ss.getCurrentItemShowing());
-        mRadialTimePickerView.invalidate();
-        if (mInKbMode) {
-            tryStartingKbMode(-1);
-            mHourView.invalidate();
-        }
-    }
-
-    @Override
-    public void setCurrentLocale(Locale locale) {
-        super.setCurrentLocale(locale);
-        mTempCalendar = Calendar.getInstance(locale);
+        setCurrentHour(ss.getHour());
+        setCurrentMinute(ss.getMinute());
     }
 
     @Override
@@ -447,9 +422,9 @@
         }
         mTempCalendar.set(Calendar.HOUR_OF_DAY, getCurrentHour());
         mTempCalendar.set(Calendar.MINUTE, getCurrentMinute());
-        String selectedDate = DateUtils.formatDateTime(mContext,
+        String selectedDateUtterance = DateUtils.formatDateTime(mContext,
                 mTempCalendar.getTimeInMillis(), flags);
-        event.getText().add(selectedDate);
+        event.getText().add(selectedDateUtterance);
     }
 
     @Override
@@ -462,48 +437,121 @@
         info.setClassName(TimePicker.class.getName());
     }
 
+    private void updateInputState() {
+        // Make sure that if the user changes the value and the IME is active
+        // for one of the inputs if this widget, the IME is closed. If the user
+        // changed the value via the IME and there is a next input the IME will
+        // be shown, otherwise the user chose another means of changing the
+        // value and having the IME up makes no sense.
+        InputMethodManager inputMethodManager = InputMethodManager.peekInstance();
+        if (inputMethodManager != null) {
+            if (inputMethodManager.isActive(mHourSpinnerInput)) {
+                mHourSpinnerInput.clearFocus();
+                inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
+            } else if (inputMethodManager.isActive(mMinuteSpinnerInput)) {
+                mMinuteSpinnerInput.clearFocus();
+                inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
+            } else if (inputMethodManager.isActive(mAmPmSpinnerInput)) {
+                mAmPmSpinnerInput.clearFocus();
+                inputMethodManager.hideSoftInputFromWindow(mDelegator.getWindowToken(), 0);
+            }
+        }
+    }
+
+    private void updateAmPmControl() {
+        if (is24HourView()) {
+            if (mAmPmSpinner != null) {
+                mAmPmSpinner.setVisibility(View.GONE);
+            } else {
+                mAmPmButton.setVisibility(View.GONE);
+            }
+        } else {
+            int index = mIsAm ? Calendar.AM : Calendar.PM;
+            if (mAmPmSpinner != null) {
+                mAmPmSpinner.setValue(index);
+                mAmPmSpinner.setVisibility(View.VISIBLE);
+            } else {
+                mAmPmButton.setText(mAmPmStrings[index]);
+                mAmPmButton.setVisibility(View.VISIBLE);
+            }
+        }
+        mDelegator.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
+    }
+
     /**
-     * Set whether in keyboard mode or not.
+     * Sets the current locale.
      *
-     * @param inKbMode True means in keyboard mode.
+     * @param locale The current locale.
      */
-    private void setInKbMode(boolean inKbMode) {
-        mInKbMode = inKbMode;
+    @Override
+    public void setCurrentLocale(Locale locale) {
+        super.setCurrentLocale(locale);
+        mTempCalendar = Calendar.getInstance(locale);
     }
 
-    /**
-     * @return true if in keyboard mode
-     */
-    private boolean inKbMode() {
-        return mInKbMode;
-    }
-
-    private void setTypedTimes(ArrayList<Integer> typeTimes) {
-        mTypedTimes = typeTimes;
-    }
-
-    /**
-     * @return an array of typed times
-     */
-    private ArrayList<Integer> getTypedTimes() {
-        return mTypedTimes;
-    }
-
-    /**
-     * @return the index of the current item showing
-     */
-    private int getCurrentItemShowing() {
-        return mRadialTimePickerView.getCurrentItemShowing();
-    }
-
-    /**
-     * Propagate the time change
-     */
     private void onTimeChanged() {
         mDelegator.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
         if (mOnTimeChangedListener != null) {
-            mOnTimeChangedListener.onTimeChanged(mDelegator,
-                    getCurrentHour(), getCurrentMinute());
+            mOnTimeChangedListener.onTimeChanged(mDelegator, getCurrentHour(),
+                    getCurrentMinute());
+        }
+    }
+
+    private void updateHourControl() {
+        if (is24HourView()) {
+            // 'k' means 1-24 hour
+            if (mHourFormat == 'k') {
+                mHourSpinner.setMinValue(1);
+                mHourSpinner.setMaxValue(24);
+            } else {
+                mHourSpinner.setMinValue(0);
+                mHourSpinner.setMaxValue(23);
+            }
+        } else {
+            // 'K' means 0-11 hour
+            if (mHourFormat == 'K') {
+                mHourSpinner.setMinValue(0);
+                mHourSpinner.setMaxValue(11);
+            } else {
+                mHourSpinner.setMinValue(1);
+                mHourSpinner.setMaxValue(12);
+            }
+        }
+        mHourSpinner.setFormatter(mHourWithTwoDigit ? NumberPicker.getTwoDigitFormatter() : null);
+    }
+
+    private void updateMinuteControl() {
+        if (is24HourView()) {
+            mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_DONE);
+        } else {
+            mMinuteSpinnerInput.setImeOptions(EditorInfo.IME_ACTION_NEXT);
+        }
+    }
+
+    private void setContentDescriptions() {
+        // Minute
+        trySetContentDescription(mMinuteSpinner, R.id.increment,
+                R.string.time_picker_increment_minute_button);
+        trySetContentDescription(mMinuteSpinner, R.id.decrement,
+                R.string.time_picker_decrement_minute_button);
+        // Hour
+        trySetContentDescription(mHourSpinner, R.id.increment,
+                R.string.time_picker_increment_hour_button);
+        trySetContentDescription(mHourSpinner, R.id.decrement,
+                R.string.time_picker_decrement_hour_button);
+        // AM/PM
+        if (mAmPmSpinner != null) {
+            trySetContentDescription(mAmPmSpinner, R.id.increment,
+                    R.string.time_picker_increment_set_pm_button);
+            trySetContentDescription(mAmPmSpinner, R.id.decrement,
+                    R.string.time_picker_decrement_set_am_button);
+        }
+    }
+
+    private void trySetContentDescription(View root, int viewId, int contDescResId) {
+        View target = root.findViewById(viewId);
+        if (target != null) {
+            target.setContentDescription(mContext.getString(contDescResId));
         }
     }
 
@@ -511,34 +559,19 @@
      * Used to save / restore state of time picker
      */
     private static class SavedState extends View.BaseSavedState {
-
         private final int mHour;
         private final int mMinute;
-        private final boolean mIs24HourMode;
-        private final boolean mInKbMode;
-        private final ArrayList<Integer> mTypedTimes;
-        private final int mCurrentItemShowing;
 
-        private SavedState(Parcelable superState, int hour, int minute, boolean is24HourMode,
-                           boolean isKbMode, ArrayList<Integer> typedTimes,
-                           int currentItemShowing) {
+        private SavedState(Parcelable superState, int hour, int minute) {
             super(superState);
             mHour = hour;
             mMinute = minute;
-            mIs24HourMode = is24HourMode;
-            mInKbMode = isKbMode;
-            mTypedTimes = typedTimes;
-            mCurrentItemShowing = currentItemShowing;
         }
 
         private SavedState(Parcel in) {
             super(in);
             mHour = in.readInt();
             mMinute = in.readInt();
-            mIs24HourMode = (in.readInt() == 1);
-            mInKbMode = (in.readInt() == 1);
-            mTypedTimes = in.readArrayList(getClass().getClassLoader());
-            mCurrentItemShowing = in.readInt();
         }
 
         public int getHour() {
@@ -549,31 +582,11 @@
             return mMinute;
         }
 
-        public boolean is24HourMode() {
-            return mIs24HourMode;
-        }
-
-        public boolean inKbMode() {
-            return mInKbMode;
-        }
-
-        public ArrayList<Integer> getTypesTimes() {
-            return mTypedTimes;
-        }
-
-        public int getCurrentItemShowing() {
-            return mCurrentItemShowing;
-        }
-
         @Override
         public void writeToParcel(Parcel dest, int flags) {
             super.writeToParcel(dest, flags);
             dest.writeInt(mHour);
             dest.writeInt(mMinute);
-            dest.writeInt(mIs24HourMode ? 1 : 0);
-            dest.writeInt(mInKbMode ? 1 : 0);
-            dest.writeList(mTypedTimes);
-            dest.writeInt(mCurrentItemShowing);
         }
 
         @SuppressWarnings({"unused", "hiding"})
@@ -588,706 +601,11 @@
         };
     }
 
-    private void tryVibrate() {
-        mDelegator.performHapticFeedback(HapticFeedbackConstants.CLOCK_TICK);
+    public static String[] getAmPmStrings(Context context) {
+        String[] result = new String[2];
+        LocaleData d = LocaleData.get(context.getResources().getConfiguration().locale);
+        result[0] = d.amPm[0].length() > 2 ? d.narrowAm : d.amPm[0];
+        result[1] = d.amPm[1].length() > 2 ? d.narrowPm : d.amPm[1];
+        return result;
     }
-
-    private void updateAmPmLabelStates(int amOrPm) {
-        final boolean isAm = amOrPm == AM;
-        mAmLabel.setChecked(isAm);
-        mAmLabel.setAlpha(isAm ? 1 : mDisabledAlpha);
-
-        final boolean isPm = amOrPm == PM;
-        mPmLabel.setChecked(isPm);
-        mPmLabel.setAlpha(isPm ? 1 : mDisabledAlpha);
-    }
-
-    /**
-     * Called by the picker for updating the header display.
-     */
-    @Override
-    public void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance) {
-        if (pickerIndex == HOUR_INDEX) {
-            if (mAllowAutoAdvance && autoAdvance) {
-                updateHeaderHour(newValue, false);
-                setCurrentItemShowing(MINUTE_INDEX, true, false);
-                mRadialTimePickerView.announceForAccessibility(newValue + ". " + mSelectMinutes);
-            } else {
-                updateHeaderHour(newValue, true);
-                mRadialTimePickerView.setContentDescription(
-                        mHourPickerDescription + ": " + newValue);
-            }
-        } else if (pickerIndex == MINUTE_INDEX){
-            updateHeaderMinute(newValue, true);
-            mRadialTimePickerView.setContentDescription(mMinutePickerDescription + ": " + newValue);
-        } else if (pickerIndex == AMPM_INDEX) {
-            updateAmPmLabelStates(newValue);
-        } else if (pickerIndex == ENABLE_PICKER_INDEX) {
-            if (!isTypedTimeFullyLegal()) {
-                mTypedTimes.clear();
-            }
-            finishKbMode();
-        }
-    }
-
-    private void updateHeaderHour(int value, boolean announce) {
-        final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale,
-                (mIs24HourView) ? "Hm" : "hm");
-        final int lengthPattern = bestDateTimePattern.length();
-        boolean hourWithTwoDigit = false;
-        char hourFormat = '\0';
-        // Check if the returned pattern is single or double 'H', 'h', 'K', 'k'. We also save
-        // the hour format that we found.
-        for (int i = 0; i < lengthPattern; i++) {
-            final char c = bestDateTimePattern.charAt(i);
-            if (c == 'H' || c == 'h' || c == 'K' || c == 'k') {
-                hourFormat = c;
-                if (i + 1 < lengthPattern && c == bestDateTimePattern.charAt(i + 1)) {
-                    hourWithTwoDigit = true;
-                }
-                break;
-            }
-        }
-        final String format;
-        if (hourWithTwoDigit) {
-            format = "%02d";
-        } else {
-            format = "%d";
-        }
-        if (mIs24HourView) {
-            // 'k' means 1-24 hour
-            if (hourFormat == 'k' && value == 0) {
-                value = 24;
-            }
-        } else {
-            // 'K' means 0-11 hour
-            value = modulo12(value, hourFormat == 'K');
-        }
-        CharSequence text = String.format(format, value);
-        mHourView.setText(text);
-        if (announce) {
-            tryAnnounceForAccessibility(text, true);
-        }
-    }
-
-    private void tryAnnounceForAccessibility(CharSequence text, boolean isHour) {
-        if (mLastAnnouncedIsHour != isHour || !text.equals(mLastAnnouncedText)) {
-            // TODO: Find a better solution, potentially live regions?
-            mDelegator.announceForAccessibility(text);
-            mLastAnnouncedText = text;
-            mLastAnnouncedIsHour = isHour;
-        }
-    }
-
-    private static int modulo12(int n, boolean startWithZero) {
-        int value = n % 12;
-        if (value == 0 && !startWithZero) {
-            value = 12;
-        }
-        return value;
-    }
-
-    /**
-     * The time separator is defined in the Unicode CLDR and cannot be supposed to be ":".
-     *
-     * See http://unicode.org/cldr/trac/browser/trunk/common/main
-     *
-     * We pass the correct "skeleton" depending on 12 or 24 hours view and then extract the
-     * separator as the character which is just after the hour marker in the returned pattern.
-     */
-    private void updateHeaderSeparator() {
-        final String bestDateTimePattern = DateFormat.getBestDateTimePattern(mCurrentLocale,
-                (mIs24HourView) ? "Hm" : "hm");
-        final String separatorText;
-        // See http://www.unicode.org/reports/tr35/tr35-dates.html for hour formats
-        final char[] hourFormats = {'H', 'h', 'K', 'k'};
-        int hIndex = lastIndexOfAny(bestDateTimePattern, hourFormats);
-        if (hIndex == -1) {
-            // Default case
-            separatorText = ":";
-        } else {
-            separatorText = Character.toString(bestDateTimePattern.charAt(hIndex + 1));
-        }
-        mSeparatorView.setText(separatorText);
-    }
-
-    static private int lastIndexOfAny(String str, char[] any) {
-        final int lengthAny = any.length;
-        if (lengthAny > 0) {
-            for (int i = str.length() - 1; i >= 0; i--) {
-                char c = str.charAt(i);
-                for (int j = 0; j < lengthAny; j++) {
-                    if (c == any[j]) {
-                        return i;
-                    }
-                }
-            }
-        }
-        return -1;
-    }
-
-    private void updateHeaderMinute(int value, boolean announceForAccessibility) {
-        if (value == 60) {
-            value = 0;
-        }
-        final CharSequence text = String.format(mCurrentLocale, "%02d", value);
-        mMinuteView.setText(text);
-        if (announceForAccessibility) {
-            tryAnnounceForAccessibility(text, false);
-        }
-    }
-
-    /**
-     * Show either Hours or Minutes.
-     */
-    private void setCurrentItemShowing(int index, boolean animateCircle, boolean announce) {
-        mRadialTimePickerView.setCurrentItemShowing(index, animateCircle);
-
-        if (index == HOUR_INDEX) {
-            int hours = mRadialTimePickerView.getCurrentHour();
-            if (!mIs24HourView) {
-                hours = hours % 12;
-            }
-            mRadialTimePickerView.setContentDescription(mHourPickerDescription + ": " + hours);
-            if (announce) {
-                mRadialTimePickerView.announceForAccessibility(mSelectHours);
-            }
-        } else {
-            int minutes = mRadialTimePickerView.getCurrentMinute();
-            mRadialTimePickerView.setContentDescription(mMinutePickerDescription + ": " + minutes);
-            if (announce) {
-                mRadialTimePickerView.announceForAccessibility(mSelectMinutes);
-            }
-        }
-
-        mHourView.setSelected(index == HOUR_INDEX);
-        mMinuteView.setSelected(index == MINUTE_INDEX);
-    }
-
-    private void setAmOrPm(int amOrPm) {
-        updateAmPmLabelStates(amOrPm);
-        mRadialTimePickerView.setAmOrPm(amOrPm);
-    }
-
-    /**
-     * For keyboard mode, processes key events.
-     *
-     * @param keyCode the pressed key.
-     *
-     * @return true if the key was successfully processed, false otherwise.
-     */
-    private boolean processKeyUp(int keyCode) {
-        if (keyCode == KeyEvent.KEYCODE_DEL) {
-            if (mInKbMode) {
-                if (!mTypedTimes.isEmpty()) {
-                    int deleted = deleteLastTypedKey();
-                    String deletedKeyStr;
-                    if (deleted == getAmOrPmKeyCode(AM)) {
-                        deletedKeyStr = mAmText;
-                    } else if (deleted == getAmOrPmKeyCode(PM)) {
-                        deletedKeyStr = mPmText;
-                    } else {
-                        deletedKeyStr = String.format("%d", getValFromKeyCode(deleted));
-                    }
-                    mRadialTimePickerView.announceForAccessibility(
-                            String.format(mDeletedKeyFormat, deletedKeyStr));
-                    updateDisplay(true);
-                }
-            }
-        } else if (keyCode == KeyEvent.KEYCODE_0 || keyCode == KeyEvent.KEYCODE_1
-                || keyCode == KeyEvent.KEYCODE_2 || keyCode == KeyEvent.KEYCODE_3
-                || keyCode == KeyEvent.KEYCODE_4 || keyCode == KeyEvent.KEYCODE_5
-                || keyCode == KeyEvent.KEYCODE_6 || keyCode == KeyEvent.KEYCODE_7
-                || keyCode == KeyEvent.KEYCODE_8 || keyCode == KeyEvent.KEYCODE_9
-                || (!mIs24HourView &&
-                (keyCode == getAmOrPmKeyCode(AM) || keyCode == getAmOrPmKeyCode(PM)))) {
-            if (!mInKbMode) {
-                if (mRadialTimePickerView == null) {
-                    // Something's wrong, because time picker should definitely not be null.
-                    Log.e(TAG, "Unable to initiate keyboard mode, TimePicker was null.");
-                    return true;
-                }
-                mTypedTimes.clear();
-                tryStartingKbMode(keyCode);
-                return true;
-            }
-            // We're already in keyboard mode.
-            if (addKeyIfLegal(keyCode)) {
-                updateDisplay(false);
-            }
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Try to start keyboard mode with the specified key.
-     *
-     * @param keyCode The key to use as the first press. Keyboard mode will not be started if the
-     * key is not legal to start with. Or, pass in -1 to get into keyboard mode without a starting
-     * key.
-     */
-    private void tryStartingKbMode(int keyCode) {
-        if (keyCode == -1 || addKeyIfLegal(keyCode)) {
-            mInKbMode = true;
-            onValidationChanged(false);
-            updateDisplay(false);
-            mRadialTimePickerView.setInputEnabled(false);
-        }
-    }
-
-    private boolean addKeyIfLegal(int keyCode) {
-        // If we're in 24hour mode, we'll need to check if the input is full. If in AM/PM mode,
-        // we'll need to see if AM/PM have been typed.
-        if ((mIs24HourView && mTypedTimes.size() == 4) ||
-                (!mIs24HourView && isTypedTimeFullyLegal())) {
-            return false;
-        }
-
-        mTypedTimes.add(keyCode);
-        if (!isTypedTimeLegalSoFar()) {
-            deleteLastTypedKey();
-            return false;
-        }
-
-        int val = getValFromKeyCode(keyCode);
-        mRadialTimePickerView.announceForAccessibility(String.format("%d", val));
-        // Automatically fill in 0's if AM or PM was legally entered.
-        if (isTypedTimeFullyLegal()) {
-            if (!mIs24HourView && mTypedTimes.size() <= 3) {
-                mTypedTimes.add(mTypedTimes.size() - 1, KeyEvent.KEYCODE_0);
-                mTypedTimes.add(mTypedTimes.size() - 1, KeyEvent.KEYCODE_0);
-            }
-            onValidationChanged(true);
-        }
-
-        return true;
-    }
-
-    /**
-     * Traverse the tree to see if the keys that have been typed so far are legal as is,
-     * or may become legal as more keys are typed (excluding backspace).
-     */
-    private boolean isTypedTimeLegalSoFar() {
-        Node node = mLegalTimesTree;
-        for (int keyCode : mTypedTimes) {
-            node = node.canReach(keyCode);
-            if (node == null) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Check if the time that has been typed so far is completely legal, as is.
-     */
-    private boolean isTypedTimeFullyLegal() {
-        if (mIs24HourView) {
-            // For 24-hour mode, the time is legal if the hours and minutes are each legal. Note:
-            // getEnteredTime() will ONLY call isTypedTimeFullyLegal() when NOT in 24hour mode.
-            int[] values = getEnteredTime(null);
-            return (values[0] >= 0 && values[1] >= 0 && values[1] < 60);
-        } else {
-            // For AM/PM mode, the time is legal if it contains an AM or PM, as those can only be
-            // legally added at specific times based on the tree's algorithm.
-            return (mTypedTimes.contains(getAmOrPmKeyCode(AM)) ||
-                    mTypedTimes.contains(getAmOrPmKeyCode(PM)));
-        }
-    }
-
-    private int deleteLastTypedKey() {
-        int deleted = mTypedTimes.remove(mTypedTimes.size() - 1);
-        if (!isTypedTimeFullyLegal()) {
-            onValidationChanged(false);
-        }
-        return deleted;
-    }
-
-    /**
-     * Get out of keyboard mode. If there is nothing in typedTimes, revert to TimePicker's time.
-     */
-    private void finishKbMode() {
-        mInKbMode = false;
-        if (!mTypedTimes.isEmpty()) {
-            int values[] = getEnteredTime(null);
-            mRadialTimePickerView.setCurrentHour(values[0]);
-            mRadialTimePickerView.setCurrentMinute(values[1]);
-            if (!mIs24HourView) {
-                mRadialTimePickerView.setAmOrPm(values[2]);
-            }
-            mTypedTimes.clear();
-        }
-        updateDisplay(false);
-        mRadialTimePickerView.setInputEnabled(true);
-    }
-
-    /**
-     * Update the hours, minutes, and AM/PM displays with the typed times. If the typedTimes is
-     * empty, either show an empty display (filled with the placeholder text), or update from the
-     * timepicker's values.
-     *
-     * @param allowEmptyDisplay if true, then if the typedTimes is empty, use the placeholder text.
-     * Otherwise, revert to the timepicker's values.
-     */
-    private void updateDisplay(boolean allowEmptyDisplay) {
-        if (!allowEmptyDisplay && mTypedTimes.isEmpty()) {
-            int hour = mRadialTimePickerView.getCurrentHour();
-            int minute = mRadialTimePickerView.getCurrentMinute();
-            updateHeaderHour(hour, false);
-            updateHeaderMinute(minute, false);
-            if (!mIs24HourView) {
-                updateAmPmLabelStates(hour < 12 ? AM : PM);
-            }
-            setCurrentItemShowing(mRadialTimePickerView.getCurrentItemShowing(), true, true);
-            onValidationChanged(true);
-        } else {
-            boolean[] enteredZeros = {false, false};
-            int[] values = getEnteredTime(enteredZeros);
-            String hourFormat = enteredZeros[0] ? "%02d" : "%2d";
-            String minuteFormat = (enteredZeros[1]) ? "%02d" : "%2d";
-            String hourStr = (values[0] == -1) ? mDoublePlaceholderText :
-                    String.format(hourFormat, values[0]).replace(' ', mPlaceholderText);
-            String minuteStr = (values[1] == -1) ? mDoublePlaceholderText :
-                    String.format(minuteFormat, values[1]).replace(' ', mPlaceholderText);
-            mHourView.setText(hourStr);
-            mHourView.setSelected(false);
-            mMinuteView.setText(minuteStr);
-            mMinuteView.setSelected(false);
-            if (!mIs24HourView) {
-                updateAmPmLabelStates(values[2]);
-            }
-        }
-    }
-
-    private int getValFromKeyCode(int keyCode) {
-        switch (keyCode) {
-            case KeyEvent.KEYCODE_0:
-                return 0;
-            case KeyEvent.KEYCODE_1:
-                return 1;
-            case KeyEvent.KEYCODE_2:
-                return 2;
-            case KeyEvent.KEYCODE_3:
-                return 3;
-            case KeyEvent.KEYCODE_4:
-                return 4;
-            case KeyEvent.KEYCODE_5:
-                return 5;
-            case KeyEvent.KEYCODE_6:
-                return 6;
-            case KeyEvent.KEYCODE_7:
-                return 7;
-            case KeyEvent.KEYCODE_8:
-                return 8;
-            case KeyEvent.KEYCODE_9:
-                return 9;
-            default:
-                return -1;
-        }
-    }
-
-    /**
-     * Get the currently-entered time, as integer values of the hours and minutes typed.
-     *
-     * @param enteredZeros A size-2 boolean array, which the caller should initialize, and which
-     * may then be used for the caller to know whether zeros had been explicitly entered as either
-     * hours of minutes. This is helpful for deciding whether to show the dashes, or actual 0's.
-     *
-     * @return A size-3 int array. The first value will be the hours, the second value will be the
-     * minutes, and the third will be either AM or PM.
-     */
-    private int[] getEnteredTime(boolean[] enteredZeros) {
-        int amOrPm = -1;
-        int startIndex = 1;
-        if (!mIs24HourView && isTypedTimeFullyLegal()) {
-            int keyCode = mTypedTimes.get(mTypedTimes.size() - 1);
-            if (keyCode == getAmOrPmKeyCode(AM)) {
-                amOrPm = AM;
-            } else if (keyCode == getAmOrPmKeyCode(PM)){
-                amOrPm = PM;
-            }
-            startIndex = 2;
-        }
-        int minute = -1;
-        int hour = -1;
-        for (int i = startIndex; i <= mTypedTimes.size(); i++) {
-            int val = getValFromKeyCode(mTypedTimes.get(mTypedTimes.size() - i));
-            if (i == startIndex) {
-                minute = val;
-            } else if (i == startIndex+1) {
-                minute += 10 * val;
-                if (enteredZeros != null && val == 0) {
-                    enteredZeros[1] = true;
-                }
-            } else if (i == startIndex+2) {
-                hour = val;
-            } else if (i == startIndex+3) {
-                hour += 10 * val;
-                if (enteredZeros != null && val == 0) {
-                    enteredZeros[0] = true;
-                }
-            }
-        }
-
-        return new int[] { hour, minute, amOrPm };
-    }
-
-    /**
-     * Get the keycode value for AM and PM in the current language.
-     */
-    private int getAmOrPmKeyCode(int amOrPm) {
-        // Cache the codes.
-        if (mAmKeyCode == -1 || mPmKeyCode == -1) {
-            // Find the first character in the AM/PM text that is unique.
-            KeyCharacterMap kcm = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
-            char amChar;
-            char pmChar;
-            for (int i = 0; i < Math.max(mAmText.length(), mPmText.length()); i++) {
-                amChar = mAmText.toLowerCase(mCurrentLocale).charAt(i);
-                pmChar = mPmText.toLowerCase(mCurrentLocale).charAt(i);
-                if (amChar != pmChar) {
-                    KeyEvent[] events = kcm.getEvents(new char[]{amChar, pmChar});
-                    // There should be 4 events: a down and up for both AM and PM.
-                    if (events != null && events.length == 4) {
-                        mAmKeyCode = events[0].getKeyCode();
-                        mPmKeyCode = events[2].getKeyCode();
-                    } else {
-                        Log.e(TAG, "Unable to find keycodes for AM and PM.");
-                    }
-                    break;
-                }
-            }
-        }
-        if (amOrPm == AM) {
-            return mAmKeyCode;
-        } else if (amOrPm == PM) {
-            return mPmKeyCode;
-        }
-
-        return -1;
-    }
-
-    /**
-     * Create a tree for deciding what keys can legally be typed.
-     */
-    private void generateLegalTimesTree() {
-        // Create a quick cache of numbers to their keycodes.
-        final int k0 = KeyEvent.KEYCODE_0;
-        final int k1 = KeyEvent.KEYCODE_1;
-        final int k2 = KeyEvent.KEYCODE_2;
-        final int k3 = KeyEvent.KEYCODE_3;
-        final int k4 = KeyEvent.KEYCODE_4;
-        final int k5 = KeyEvent.KEYCODE_5;
-        final int k6 = KeyEvent.KEYCODE_6;
-        final int k7 = KeyEvent.KEYCODE_7;
-        final int k8 = KeyEvent.KEYCODE_8;
-        final int k9 = KeyEvent.KEYCODE_9;
-
-        // The root of the tree doesn't contain any numbers.
-        mLegalTimesTree = new Node();
-        if (mIs24HourView) {
-            // We'll be re-using these nodes, so we'll save them.
-            Node minuteFirstDigit = new Node(k0, k1, k2, k3, k4, k5);
-            Node minuteSecondDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9);
-            // The first digit must be followed by the second digit.
-            minuteFirstDigit.addChild(minuteSecondDigit);
-
-            // The first digit may be 0-1.
-            Node firstDigit = new Node(k0, k1);
-            mLegalTimesTree.addChild(firstDigit);
-
-            // When the first digit is 0-1, the second digit may be 0-5.
-            Node secondDigit = new Node(k0, k1, k2, k3, k4, k5);
-            firstDigit.addChild(secondDigit);
-            // We may now be followed by the first minute digit. E.g. 00:09, 15:58.
-            secondDigit.addChild(minuteFirstDigit);
-
-            // When the first digit is 0-1, and the second digit is 0-5, the third digit may be 6-9.
-            Node thirdDigit = new Node(k6, k7, k8, k9);
-            // The time must now be finished. E.g. 0:55, 1:08.
-            secondDigit.addChild(thirdDigit);
-
-            // When the first digit is 0-1, the second digit may be 6-9.
-            secondDigit = new Node(k6, k7, k8, k9);
-            firstDigit.addChild(secondDigit);
-            // We must now be followed by the first minute digit. E.g. 06:50, 18:20.
-            secondDigit.addChild(minuteFirstDigit);
-
-            // The first digit may be 2.
-            firstDigit = new Node(k2);
-            mLegalTimesTree.addChild(firstDigit);
-
-            // When the first digit is 2, the second digit may be 0-3.
-            secondDigit = new Node(k0, k1, k2, k3);
-            firstDigit.addChild(secondDigit);
-            // We must now be followed by the first minute digit. E.g. 20:50, 23:09.
-            secondDigit.addChild(minuteFirstDigit);
-
-            // When the first digit is 2, the second digit may be 4-5.
-            secondDigit = new Node(k4, k5);
-            firstDigit.addChild(secondDigit);
-            // We must now be followd by the last minute digit. E.g. 2:40, 2:53.
-            secondDigit.addChild(minuteSecondDigit);
-
-            // The first digit may be 3-9.
-            firstDigit = new Node(k3, k4, k5, k6, k7, k8, k9);
-            mLegalTimesTree.addChild(firstDigit);
-            // We must now be followed by the first minute digit. E.g. 3:57, 8:12.
-            firstDigit.addChild(minuteFirstDigit);
-        } else {
-            // We'll need to use the AM/PM node a lot.
-            // Set up AM and PM to respond to "a" and "p".
-            Node ampm = new Node(getAmOrPmKeyCode(AM), getAmOrPmKeyCode(PM));
-
-            // The first hour digit may be 1.
-            Node firstDigit = new Node(k1);
-            mLegalTimesTree.addChild(firstDigit);
-            // We'll allow quick input of on-the-hour times. E.g. 1pm.
-            firstDigit.addChild(ampm);
-
-            // When the first digit is 1, the second digit may be 0-2.
-            Node secondDigit = new Node(k0, k1, k2);
-            firstDigit.addChild(secondDigit);
-            // Also for quick input of on-the-hour times. E.g. 10pm, 12am.
-            secondDigit.addChild(ampm);
-
-            // When the first digit is 1, and the second digit is 0-2, the third digit may be 0-5.
-            Node thirdDigit = new Node(k0, k1, k2, k3, k4, k5);
-            secondDigit.addChild(thirdDigit);
-            // The time may be finished now. E.g. 1:02pm, 1:25am.
-            thirdDigit.addChild(ampm);
-
-            // When the first digit is 1, the second digit is 0-2, and the third digit is 0-5,
-            // the fourth digit may be 0-9.
-            Node fourthDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9);
-            thirdDigit.addChild(fourthDigit);
-            // The time must be finished now. E.g. 10:49am, 12:40pm.
-            fourthDigit.addChild(ampm);
-
-            // When the first digit is 1, and the second digit is 0-2, the third digit may be 6-9.
-            thirdDigit = new Node(k6, k7, k8, k9);
-            secondDigit.addChild(thirdDigit);
-            // The time must be finished now. E.g. 1:08am, 1:26pm.
-            thirdDigit.addChild(ampm);
-
-            // When the first digit is 1, the second digit may be 3-5.
-            secondDigit = new Node(k3, k4, k5);
-            firstDigit.addChild(secondDigit);
-
-            // When the first digit is 1, and the second digit is 3-5, the third digit may be 0-9.
-            thirdDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9);
-            secondDigit.addChild(thirdDigit);
-            // The time must be finished now. E.g. 1:39am, 1:50pm.
-            thirdDigit.addChild(ampm);
-
-            // The hour digit may be 2-9.
-            firstDigit = new Node(k2, k3, k4, k5, k6, k7, k8, k9);
-            mLegalTimesTree.addChild(firstDigit);
-            // We'll allow quick input of on-the-hour-times. E.g. 2am, 5pm.
-            firstDigit.addChild(ampm);
-
-            // When the first digit is 2-9, the second digit may be 0-5.
-            secondDigit = new Node(k0, k1, k2, k3, k4, k5);
-            firstDigit.addChild(secondDigit);
-
-            // When the first digit is 2-9, and the second digit is 0-5, the third digit may be 0-9.
-            thirdDigit = new Node(k0, k1, k2, k3, k4, k5, k6, k7, k8, k9);
-            secondDigit.addChild(thirdDigit);
-            // The time must be finished now. E.g. 2:57am, 9:30pm.
-            thirdDigit.addChild(ampm);
-        }
-    }
-
-    /**
-     * Simple node class to be used for traversal to check for legal times.
-     * mLegalKeys represents the keys that can be typed to get to the node.
-     * mChildren are the children that can be reached from this node.
-     */
-    private class Node {
-        private int[] mLegalKeys;
-        private ArrayList<Node> mChildren;
-
-        public Node(int... legalKeys) {
-            mLegalKeys = legalKeys;
-            mChildren = new ArrayList<Node>();
-        }
-
-        public void addChild(Node child) {
-            mChildren.add(child);
-        }
-
-        public boolean containsKey(int key) {
-            for (int i = 0; i < mLegalKeys.length; i++) {
-                if (mLegalKeys[i] == key) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        public Node canReach(int key) {
-            if (mChildren == null) {
-                return null;
-            }
-            for (Node child : mChildren) {
-                if (child.containsKey(key)) {
-                    return child;
-                }
-            }
-            return null;
-        }
-    }
-
-    private final View.OnClickListener mClickListener = new View.OnClickListener() {
-        @Override
-        public void onClick(View v) {
-
-            final int amOrPm;
-            switch (v.getId()) {
-                case R.id.am_label:
-                    setAmOrPm(AM);
-                    break;
-                case R.id.pm_label:
-                    setAmOrPm(PM);
-                    break;
-                case R.id.hours:
-                    setCurrentItemShowing(HOUR_INDEX, true, true);
-                    break;
-                case R.id.minutes:
-                    setCurrentItemShowing(MINUTE_INDEX, true, true);
-                    break;
-                default:
-                    // Failed to handle this click, don't vibrate.
-                    return;
-            }
-
-            tryVibrate();
-        }
-    };
-
-    private final View.OnKeyListener mKeyListener = new View.OnKeyListener() {
-        @Override
-        public boolean onKey(View v, int keyCode, KeyEvent event) {
-            if (event.getAction() == KeyEvent.ACTION_UP) {
-                return processKeyUp(keyCode);
-            }
-            return false;
-        }
-    };
-
-    private final View.OnFocusChangeListener mFocusListener = new View.OnFocusChangeListener() {
-        @Override
-        public void onFocusChange(View v, boolean hasFocus) {
-            if (!hasFocus && mInKbMode && isTypedTimeFullyLegal()) {
-                finishKbMode();
-
-                if (mOnTimeChangedListener != null) {
-                    mOnTimeChangedListener.onTimeChanged(mDelegator,
-                            mRadialTimePickerView.getCurrentHour(),
-                            mRadialTimePickerView.getCurrentMinute());
-                }
-            }
-        }
-    };
 }
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index dd165ae..be4cdc1 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -235,6 +235,14 @@
     public int getYOffset() {
         return mTN.mY;
     }
+
+    /**
+     * Gets the LayoutParams for the Toast window.
+     * @hide
+     */
+    public WindowManager.LayoutParams getWindowParams() {
+        return mTN.mParams;
+    }
     
     /**
      * Make a standard toast that just contains a text view.
diff --git a/core/java/com/android/internal/http/multipart/FilePart.java b/core/java/com/android/internal/http/multipart/FilePart.java
index bfcda00..45e4be6 100644
--- a/core/java/com/android/internal/http/multipart/FilePart.java
+++ b/core/java/com/android/internal/http/multipart/FilePart.java
@@ -51,9 +51,14 @@
  * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
  * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
  *   
- * @since 2.0 
+ * @since 2.0
  *
+ * @deprecated Please use {@link java.net.URLConnection} and friends instead.
+ *     The Apache HTTP client is no longer maintained and may be removed in a future
+ *     release. Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
+ *     for further details.
  */
+@Deprecated
 public class FilePart extends PartBase {
 
     /** Default content encoding of file attachments. */
diff --git a/core/java/com/android/internal/http/multipart/MultipartEntity.java b/core/java/com/android/internal/http/multipart/MultipartEntity.java
index 2c5e7f6..5319251 100644
--- a/core/java/com/android/internal/http/multipart/MultipartEntity.java
+++ b/core/java/com/android/internal/http/multipart/MultipartEntity.java
@@ -80,7 +80,13 @@
  * </pre>
  * 
  * @since 3.0
+ *
+ * @deprecated Please use {@link java.net.URLConnection} and friends instead.
+ *     The Apache HTTP client is no longer maintained and may be removed in a future
+ *     release. Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
+ *     for further details.
  */
+@Deprecated
 public class MultipartEntity extends AbstractHttpEntity {
 
     private static final Log log = LogFactory.getLog(MultipartEntity.class);
diff --git a/core/java/com/android/internal/http/multipart/Part.java b/core/java/com/android/internal/http/multipart/Part.java
index cb1b546..1d66dc67 100644
--- a/core/java/com/android/internal/http/multipart/Part.java
+++ b/core/java/com/android/internal/http/multipart/Part.java
@@ -48,7 +48,13 @@
  * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
  *
  * @since 2.0
+ *
+ * @deprecated Please use {@link java.net.URLConnection} and friends instead.
+ *     The Apache HTTP client is no longer maintained and may be removed in a future
+ *     release. Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
+ *     for further details.
  */
+@Deprecated
 public abstract class Part {
 
     /** Log object for this class. */
diff --git a/core/java/com/android/internal/http/multipart/StringPart.java b/core/java/com/android/internal/http/multipart/StringPart.java
index c98257e..73d0f90 100644
--- a/core/java/com/android/internal/http/multipart/StringPart.java
+++ b/core/java/com/android/internal/http/multipart/StringPart.java
@@ -46,7 +46,13 @@
  * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
  *
  * @since 2.0
+ *
+ * @deprecated Please use {@link java.net.URLConnection} and friends instead.
+ *     The Apache HTTP client is no longer maintained and may be removed in a future
+ *     release. Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
+ *     for further details.
  */
+@Deprecated
 public class StringPart extends PartBase {
 
     /** Log object for this class. */
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 8794d31..e6bcea1 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -43,6 +43,7 @@
     void onPanelRevealed();
     void onPanelHidden();
     void onNotificationClick(String key);
+    void onNotificationActionClick(String key, int actionIndex);
     void onNotificationError(String pkg, String tag, int id,
             int uid, int initialPid, String message, int userId);
     void onClearAllNotifications(int userId);
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index 91e5330..b9a85e5 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -19,8 +19,6 @@
 import android.animation.LayoutTransition;
 import android.app.ActionBar;
 import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
@@ -29,9 +27,7 @@
 import android.text.Layout;
 import android.text.TextUtils;
 import android.util.AttributeSet;
-import android.util.TypedValue;
 import android.view.CollapsibleActionView;
-import android.view.ContextThemeWrapper;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -111,10 +107,10 @@
     private int mProgressBarPadding;
     private int mItemPadding;
 
-    private int mTitleStyleRes;
-    private int mSubtitleStyleRes;
-    private int mProgressStyle;
-    private int mIndeterminateProgressStyle;
+    private final int mTitleStyleRes;
+    private final int mSubtitleStyleRes;
+    private final int mProgressStyle;
+    private final int mIndeterminateProgressStyle;
 
     private boolean mUserTitle;
     private boolean mIncludeTabs;
diff --git a/core/java/com/android/internal/widget/SwipeDismissLayout.java b/core/java/com/android/internal/widget/SwipeDismissLayout.java
index 97b1634..99b1bae 100644
--- a/core/java/com/android/internal/widget/SwipeDismissLayout.java
+++ b/core/java/com/android/internal/widget/SwipeDismissLayout.java
@@ -17,6 +17,7 @@
 package com.android.internal.widget;
 
 import android.animation.TimeInterpolator;
+import android.app.Activity;
 import android.content.Context;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -102,6 +103,13 @@
                 android.R.integer.config_shortAnimTime);
         mCancelInterpolator = new DecelerateInterpolator(1.5f);
         mDismissInterpolator = new AccelerateInterpolator(1.5f);
+        // SwipeDismissLayout assumes that the host Activity is translucent
+        // and temporarily disables translucency when it is fully visible.
+        // As soon as the user starts swiping, we will re-enable
+        // translucency.
+        if (context instanceof Activity) {
+            ((Activity) context).convertFromTranslucent();
+        }
     }
 
     public void setOnDismissedListener(OnDismissedListener listener) {
@@ -197,6 +205,9 @@
                 mLastX = ev.getRawX();
                 updateSwiping(ev);
                 if (mSwiping) {
+                    if (getContext() instanceof Activity) {
+                        ((Activity) getContext()).convertToTranslucent(null, null);
+                    }
                     setProgress(ev.getRawX() - mDownX);
                     break;
                 }
@@ -218,6 +229,9 @@
     }
 
     protected void cancel() {
+        if (getContext() instanceof Activity) {
+            ((Activity) getContext()).convertFromTranslucent();
+        }
         if (mProgressListener != null) {
             mProgressListener.onSwipeCancelled(this);
         }
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index e0abc24..a578b5d 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -315,7 +315,8 @@
     }
 
     SkBitmap decodingBitmap;
-    if (!decoder->decode(stream, &decodingBitmap, prefColorType, decodeMode)) {
+    if (decoder->decode(stream, &decodingBitmap, prefColorType, decodeMode)
+                != SkImageDecoder::kSuccess) {
         return nullObjectReturn("decoder->decode returned false");
     }
 
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index b3d9890..a0b2ca8 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -374,6 +374,7 @@
     ContextFactory factory;
     RenderProxy* proxy = new RenderProxy(false, rootNode, &factory);
     proxy->loadSystemProperties();
+    proxy->setSwapBehavior(kSwap_discardBuffer);
     proxy->initialize(surface);
     // Shadows can't be used via this interface, so just set the light source
     // to all 0s. (and width & height are unused, TODO remove them)
diff --git a/core/res/res/values-mcc310-mnc120/config.xml b/core/res/res/values-mcc310-mnc120/config.xml
index 24e55b1..774732d 100644
--- a/core/res/res/values-mcc310-mnc120/config.xml
+++ b/core/res/res/values-mcc310-mnc120/config.xml
@@ -27,4 +27,8 @@
 
     <!-- Sprint need a 70 ms delay for 3way call -->
     <integer name="config_cdma_3waycall_flash_delay">70</integer>
+
+    <!-- If this value is true, The mms content-disposition field is supported correctly.
+         If false, Content-disposition fragments are ignored -->
+    <bool name="config_mms_content_disposition_support">false</bool>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc160/config.xml b/core/res/res/values-mcc310-mnc160/config.xml
new file mode 100644
index 0000000..28cd695
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc160/config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Configure mobile network MTU. Carrier specific value is set here.
+    -->
+    <integer name="config_mobile_mtu">1440</integer>
+
+    <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
+         carrier provisioning. If false: hard disabled. If true: then depends on carrier
+         provisioning, availability etc -->
+    <bool name="config_carrier_volte_vt_available">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc200/config.xml b/core/res/res/values-mcc310-mnc200/config.xml
new file mode 100644
index 0000000..28cd695
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc200/config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Configure mobile network MTU. Carrier specific value is set here.
+    -->
+    <integer name="config_mobile_mtu">1440</integer>
+
+    <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
+         carrier provisioning. If false: hard disabled. If true: then depends on carrier
+         provisioning, availability etc -->
+    <bool name="config_carrier_volte_vt_available">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc210/config.xml b/core/res/res/values-mcc310-mnc210/config.xml
new file mode 100644
index 0000000..28cd695
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc210/config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Configure mobile network MTU. Carrier specific value is set here.
+    -->
+    <integer name="config_mobile_mtu">1440</integer>
+
+    <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
+         carrier provisioning. If false: hard disabled. If true: then depends on carrier
+         provisioning, availability etc -->
+    <bool name="config_carrier_volte_vt_available">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc220/config.xml b/core/res/res/values-mcc310-mnc220/config.xml
new file mode 100644
index 0000000..28cd695
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc220/config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Configure mobile network MTU. Carrier specific value is set here.
+    -->
+    <integer name="config_mobile_mtu">1440</integer>
+
+    <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
+         carrier provisioning. If false: hard disabled. If true: then depends on carrier
+         provisioning, availability etc -->
+    <bool name="config_carrier_volte_vt_available">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc230/config.xml b/core/res/res/values-mcc310-mnc230/config.xml
new file mode 100644
index 0000000..28cd695
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc230/config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Configure mobile network MTU. Carrier specific value is set here.
+    -->
+    <integer name="config_mobile_mtu">1440</integer>
+
+    <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
+         carrier provisioning. If false: hard disabled. If true: then depends on carrier
+         provisioning, availability etc -->
+    <bool name="config_carrier_volte_vt_available">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc240/config.xml b/core/res/res/values-mcc310-mnc240/config.xml
new file mode 100644
index 0000000..28cd695
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc240/config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Configure mobile network MTU. Carrier specific value is set here.
+    -->
+    <integer name="config_mobile_mtu">1440</integer>
+
+    <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
+         carrier provisioning. If false: hard disabled. If true: then depends on carrier
+         provisioning, availability etc -->
+    <bool name="config_carrier_volte_vt_available">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc250/config.xml b/core/res/res/values-mcc310-mnc250/config.xml
new file mode 100644
index 0000000..28cd695
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc250/config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Configure mobile network MTU. Carrier specific value is set here.
+    -->
+    <integer name="config_mobile_mtu">1440</integer>
+
+    <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
+         carrier provisioning. If false: hard disabled. If true: then depends on carrier
+         provisioning, availability etc -->
+    <bool name="config_carrier_volte_vt_available">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc260/config.xml b/core/res/res/values-mcc310-mnc260/config.xml
index 28cd695..6bfc3d1 100644
--- a/core/res/res/values-mcc310-mnc260/config.xml
+++ b/core/res/res/values-mcc310-mnc260/config.xml
@@ -25,8 +25,8 @@
     -->
     <integer name="config_mobile_mtu">1440</integer>
 
-    <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
+    <!-- Flag specifying whether VoLTE should be available for carrier: independent of
          carrier provisioning. If false: hard disabled. If true: then depends on carrier
          provisioning, availability etc -->
-    <bool name="config_carrier_volte_vt_available">true</bool>
+    <bool name="config_carrier_volte_available">true</bool>
 </resources>
diff --git a/core/res/res/values-mcc310-mnc270/config.xml b/core/res/res/values-mcc310-mnc270/config.xml
new file mode 100644
index 0000000..28cd695
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc270/config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Configure mobile network MTU. Carrier specific value is set here.
+    -->
+    <integer name="config_mobile_mtu">1440</integer>
+
+    <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
+         carrier provisioning. If false: hard disabled. If true: then depends on carrier
+         provisioning, availability etc -->
+    <bool name="config_carrier_volte_vt_available">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc300/config.xml b/core/res/res/values-mcc310-mnc300/config.xml
new file mode 100644
index 0000000..28cd695
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc300/config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Configure mobile network MTU. Carrier specific value is set here.
+    -->
+    <integer name="config_mobile_mtu">1440</integer>
+
+    <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
+         carrier provisioning. If false: hard disabled. If true: then depends on carrier
+         provisioning, availability etc -->
+    <bool name="config_carrier_volte_vt_available">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc310/config.xml b/core/res/res/values-mcc310-mnc310/config.xml
new file mode 100644
index 0000000..28cd695
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc310/config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Configure mobile network MTU. Carrier specific value is set here.
+    -->
+    <integer name="config_mobile_mtu">1440</integer>
+
+    <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
+         carrier provisioning. If false: hard disabled. If true: then depends on carrier
+         provisioning, availability etc -->
+    <bool name="config_carrier_volte_vt_available">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc490/config.xml b/core/res/res/values-mcc310-mnc490/config.xml
new file mode 100644
index 0000000..28cd695
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc490/config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Configure mobile network MTU. Carrier specific value is set here.
+    -->
+    <integer name="config_mobile_mtu">1440</integer>
+
+    <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
+         carrier provisioning. If false: hard disabled. If true: then depends on carrier
+         provisioning, availability etc -->
+    <bool name="config_carrier_volte_vt_available">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc530/config.xml b/core/res/res/values-mcc310-mnc530/config.xml
new file mode 100644
index 0000000..28cd695
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc530/config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Configure mobile network MTU. Carrier specific value is set here.
+    -->
+    <integer name="config_mobile_mtu">1440</integer>
+
+    <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
+         carrier provisioning. If false: hard disabled. If true: then depends on carrier
+         provisioning, availability etc -->
+    <bool name="config_carrier_volte_vt_available">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc580/config.xml b/core/res/res/values-mcc310-mnc580/config.xml
new file mode 100644
index 0000000..28cd695
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc580/config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Configure mobile network MTU. Carrier specific value is set here.
+    -->
+    <integer name="config_mobile_mtu">1440</integer>
+
+    <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
+         carrier provisioning. If false: hard disabled. If true: then depends on carrier
+         provisioning, availability etc -->
+    <bool name="config_carrier_volte_vt_available">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc590/config.xml b/core/res/res/values-mcc310-mnc590/config.xml
new file mode 100644
index 0000000..28cd695
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc590/config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Configure mobile network MTU. Carrier specific value is set here.
+    -->
+    <integer name="config_mobile_mtu">1440</integer>
+
+    <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
+         carrier provisioning. If false: hard disabled. If true: then depends on carrier
+         provisioning, availability etc -->
+    <bool name="config_carrier_volte_vt_available">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc640/config.xml b/core/res/res/values-mcc310-mnc640/config.xml
new file mode 100644
index 0000000..28cd695
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc640/config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Configure mobile network MTU. Carrier specific value is set here.
+    -->
+    <integer name="config_mobile_mtu">1440</integer>
+
+    <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
+         carrier provisioning. If false: hard disabled. If true: then depends on carrier
+         provisioning, availability etc -->
+    <bool name="config_carrier_volte_vt_available">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc660/config.xml b/core/res/res/values-mcc310-mnc660/config.xml
new file mode 100644
index 0000000..28cd695
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc660/config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Configure mobile network MTU. Carrier specific value is set here.
+    -->
+    <integer name="config_mobile_mtu">1440</integer>
+
+    <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
+         carrier provisioning. If false: hard disabled. If true: then depends on carrier
+         provisioning, availability etc -->
+    <bool name="config_carrier_volte_vt_available">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc800/config.xml b/core/res/res/values-mcc310-mnc800/config.xml
new file mode 100644
index 0000000..28cd695
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc800/config.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2013, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Configure mobile network MTU. Carrier specific value is set here.
+    -->
+    <integer name="config_mobile_mtu">1440</integer>
+
+    <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
+         carrier provisioning. If false: hard disabled. If true: then depends on carrier
+         provisioning, availability etc -->
+    <bool name="config_carrier_volte_vt_available">true</bool>
+</resources>
diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml
index 820cc2e..d0a57b3 100644
--- a/core/res/res/values-mcc311-mnc480/config.xml
+++ b/core/res/res/values-mcc311-mnc480/config.xml
@@ -38,10 +38,10 @@
         be disabled) but individual Features can be disabled using ImsConfig.setFeatureValue() -->
     <bool name="imsServiceAllowTurnOff">false</bool>
 
-    <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
+    <!-- Flag specifying whether VoLTE should be available for carrier: independent of
          carrier provisioning. If false: hard disabled. If true: then depends on carrier
          provisioning, availability etc -->
-    <bool name="config_carrier_volte_vt_available">true</bool>
+    <bool name="config_carrier_volte_available">true</bool>
 
     <bool name="config_auto_attach_data_on_creation">false</bool>
     <!-- service number convert map in roaming network. -->
diff --git a/core/res/res/values-mcc530-mnc05/config.xml b/core/res/res/values-mcc530-mnc05/config.xml
new file mode 100644
index 0000000..893afe5
--- /dev/null
+++ b/core/res/res/values-mcc530-mnc05/config.xml
@@ -0,0 +1,26 @@
+<?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 my 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for different hardware and product builds. -->
+<resources>
+    <!-- If this value is true, The mms content-disposition field is supported correctly.
+         If false, Content-disposition fragments are ignored -->
+    <bool name="config_mms_content_disposition_support">false</bool>
+</resources>
diff --git a/core/res/res/values/colors_material.xml b/core/res/res/values/colors_material.xml
index 5773b94..46ec838 100644
--- a/core/res/res/values/colors_material.xml
+++ b/core/res/res/values/colors_material.xml
@@ -22,7 +22,7 @@
     <color name="background_floating_material_light">#ffeeeeee</color>
 
     <color name="primary_material_dark">#ff212121</color>
-    <color name="primary_material_light">#ffbdbdbd</color>
+    <color name="primary_material_light">#ffe0e0e0</color>
     <color name="primary_dark_material_dark">#ff000000</color>
     <color name="primary_dark_material_light">#ff757575</color>
 
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 59b4e9c..e50eb0c 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -453,6 +453,26 @@
     <!-- If this is true, key chords can be used to take a screenshot on the device. -->
     <bool name="config_enableScreenshotChord">true</bool>
 
+    <!-- If this is true, allow wake from theater mode when plugged in or unplugged. -->
+    <bool name="config_allowTheaterModeWakeFromUnplug">false</bool>
+    <!-- If this is true, allow wake from theater mode from gesture. -->
+    <bool name="config_allowTheaterModeWakeFromGesture">false</bool>
+    <!-- If this is true, allow wake from theater mode from camera lens cover is switched. -->
+    <bool name="config_allowTheaterModeWakeFromCameraLens">false</bool>
+    <!-- If this is true, allow wake from theater mode from power key press. -->
+    <bool name="config_allowTheaterModeWakeFromPowerKey">true</bool>
+    <!-- If this is true, allow wake from theater mode from regular key press. Setting this value to
+         true implies config_allowTheaterModeWakeFromPowerKey is also true-->
+    <bool name="config_allowTheaterModeWakeFromKey">false</bool>
+    <!-- If this is true, allow wake from theater mode from motion. -->
+    <bool name="config_allowTheaterModeWakeFromMotion">false</bool>
+    <!-- If this is true, allow wake from theater mode from lid switch. -->
+    <bool name="config_allowTheaterModeWakeFromLidSwitch">false</bool>
+    <!-- If this is true, allow wake from theater mode when docked. -->
+    <bool name="config_allowTheaterModeWakeFromDock">false</bool>
+    <!-- If this is true, allow wake from theater mode from window layout flag. -->
+    <bool name="config_allowTheaterModeWakeFromWindowLayout">false</bool>
+
     <!-- Auto-rotation behavior -->
 
     <!-- If true, enables auto-rotation features using the accelerometer.
@@ -1767,13 +1787,21 @@
         be disabled) but individual Features can be disabled using ImsConfig.setFeatureValue() -->
     <bool name="imsServiceAllowTurnOff">true</bool>
 
-    <!-- Flag specifying whether VoLTE & VT is availasble on device -->
-    <bool name="config_device_volte_vt_available">false</bool>
+    <!-- Flag specifying whether VoLTE is available on device -->
+    <bool name="config_device_volte_available">false</bool>
 
-    <!-- Flag specifying whether VoLTE & VT should be available for carrier: independent of
+    <!-- Flag specifying whether VoLTE should be available for carrier: independent of
          carrier provisioning. If false: hard disabled. If true: then depends on carrier
          provisioning, availability etc -->
-    <bool name="config_carrier_volte_vt_available">false</bool>
+    <bool name="config_carrier_volte_available">false</bool>
+
+    <!-- Flag specifying whether VT is available on device -->
+    <bool name="config_device_vt_available">false</bool>
+
+    <!-- Flag specifying whether VT should be available for carrier: independent of
+         carrier provisioning. If false: hard disabled. If true: then depends on carrier
+         provisioning, availability etc -->
+    <bool name="config_carrier_vt_available">false</bool>
 
     <bool name="config_networkSamplingWakesDevice">true</bool>
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 3d30792..56cf56d 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1449,9 +1449,8 @@
     <string name="permlab_bodySensors">body sensors (like heart rate monitors)
     </string>
     <!-- Description of the body sensors permission, listed so the user can decide whether to allow the application to access data from body sensors. [CHAR LIMIT=NONE] -->
-    <string name="permdesc_bodySensors" product="default">Allows the app to
-      access data from sensors you use to measure what’s happening inside your
-      body, such as heart rate.</string>
+    <string name="permdesc_bodySensors" product="default">Allows the app to access data from sensors
+    that monitor your physical condition, such as your heart rate.</string>
 
     <!-- Title of the read social stream permission, listed so the user can decide whether to allow the application to read information from the user's social stream. [CHAR LIMIT=30] -->
     <string name="permlab_readSocialStream" product="default">read your social stream</string>
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index f9fca00..6e03b3d 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -320,49 +320,47 @@
         <item name="textColor">?attr/textColorPrimaryDisableOnly</item>
     </style>
 
-    <style name="TextAppearance.Material.Widget.ActionMode"/>
-    <style name="TextAppearance.Material.Widget.ActionMode.Title"
-           parent="TextAppearance.Material.Title">
-        <item name="textSize">@dimen/text_size_title_material_toolbar</item>
-    </style>
-    <style name="TextAppearance.Material.Widget.ActionMode.Title.Inverse"
-           parent="TextAppearance.Material.Title.Inverse">
-        <item name="textSize">@dimen/text_size_title_material_toolbar</item>
-    </style>
-    <style name="TextAppearance.Material.Widget.ActionMode.Subtitle"
-           parent="TextAppearance.Material.Subhead">
-        <item name="textSize">@dimen/text_size_subtitle_material_toolbar</item>
-    </style>
-    <style name="TextAppearance.Material.Widget.ActionMode.Subtitle.Inverse"
-           parent="TextAppearance.Material.Subhead.Inverse">
-        <item name="textSize">@dimen/text_size_subtitle_material_toolbar</item>
-    </style>
     <style name="TextAppearance.Material.Widget.ActionBar.Title"
            parent="TextAppearance.Material.Title">
         <item name="textSize">@dimen/text_size_title_material_toolbar</item>
+        <item name="textColor">?attr/textColorPrimary</item>
     </style>
     <style name="TextAppearance.Material.Widget.ActionBar.Title.Inverse"
            parent="TextAppearance.Material.Title.Inverse">
         <item name="textSize">@dimen/text_size_title_material_toolbar</item>
+        <item name="textColor">?attr/textColorPrimaryInverse</item>
     </style>
     <style name="TextAppearance.Material.Widget.ActionBar.Subtitle"
            parent="TextAppearance.Material.Subhead">
         <item name="textSize">@dimen/text_size_subtitle_material_toolbar</item>
+        <item name="textColor">?attr/textColorSecondary</item>
     </style>
     <style name="TextAppearance.Material.Widget.ActionBar.Subtitle.Inverse"
            parent="TextAppearance.Material.Subhead.Inverse">
         <item name="textSize">@dimen/text_size_subtitle_material_toolbar</item>
+        <item name="textColor">?attr/textColorSecondaryInverse</item>
     </style>
 
-    <style name="TextAppearance.Material.Widget.ActionBar.Menu" parent="TextAppearance.Material.Menu">
+    <style name="TextAppearance.Material.Widget.ActionBar.Menu"
+           parent="TextAppearance.Material.Menu">
+        <item name="textColor">?attr/actionMenuTextColor</item>
+        <item name="textAllCaps">@bool/config_actionMenuItemAllCaps</item>
+    </style>
+    <style name="TextAppearance.Material.Widget.ActionBar.Menu.Inverse"
+           parent="TextAppearance.Material.Menu.Inverse">
         <item name="textColor">?attr/actionMenuTextColor</item>
         <item name="textAllCaps">@bool/config_actionMenuItemAllCaps</item>
     </style>
 
-    <style name="TextAppearance.Material.Widget.ActionBar.Menu.Inverse" parent="TextAppearance.Material.Menu.Inverse">
-        <item name="textColor">?attr/actionMenuTextColor</item>
-        <item name="textAllCaps">@bool/config_actionMenuItemAllCaps</item>
-    </style>
+    <style name="TextAppearance.Material.Widget.ActionMode"/>
+    <style name="TextAppearance.Material.Widget.ActionMode.Title"
+           parent="TextAppearance.Material.Widget.ActionBar.Title" />
+    <style name="TextAppearance.Material.Widget.ActionMode.Title.Inverse"
+           parent="TextAppearance.Material.Widget.ActionBar.Title.Inverse" />
+    <style name="TextAppearance.Material.Widget.ActionMode.Subtitle"
+           parent="TextAppearance.Material.Widget.ActionBar.Subtitle" />
+    <style name="TextAppearance.Material.Widget.ActionMode.Subtitle.Inverse"
+           parent="TextAppearance.Material.Widget.ActionBar.Subtitle.Inverse" />
 
     <style name="TextAppearance.Material.Widget.Toolbar.Title"
            parent="TextAppearance.Material.Widget.ActionBar.Title" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 71f0642..a11fdbc 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1571,6 +1571,15 @@
   <java-symbol type="bool" name="config_enableNetworkLocationOverlay" />
   <java-symbol type="bool" name="config_sf_limitedAlpha" />
   <java-symbol type="bool" name="config_unplugTurnsOnScreen" />
+  <java-symbol type="bool" name="config_allowTheaterModeWakeFromUnplug" />
+  <java-symbol type="bool" name="config_allowTheaterModeWakeFromGesture" />
+  <java-symbol type="bool" name="config_allowTheaterModeWakeFromCameraLens" />
+  <java-symbol type="bool" name="config_allowTheaterModeWakeFromPowerKey" />
+  <java-symbol type="bool" name="config_allowTheaterModeWakeFromKey" />
+  <java-symbol type="bool" name="config_allowTheaterModeWakeFromMotion" />
+  <java-symbol type="bool" name="config_allowTheaterModeWakeFromLidSwitch" />
+  <java-symbol type="bool" name="config_allowTheaterModeWakeFromDock" />
+  <java-symbol type="bool" name="config_allowTheaterModeWakeFromWindowLayout" />
   <java-symbol type="bool" name="config_wifi_background_scan_support" />
   <java-symbol type="bool" name="config_wifi_dual_band_support" />
   <java-symbol type="bool" name="config_wimaxEnabled" />
@@ -2031,8 +2040,10 @@
   <java-symbol type="attr" name="preferenceFragmentStyle" />
   <java-symbol type="bool" name="skipHoldBeforeMerge" />
   <java-symbol type="bool" name="imsServiceAllowTurnOff" />
-  <java-symbol type="bool" name="config_device_volte_vt_available" />
-  <java-symbol type="bool" name="config_carrier_volte_vt_available" />
+  <java-symbol type="bool" name="config_device_volte_available" />
+  <java-symbol type="bool" name="config_carrier_volte_available" />
+  <java-symbol type="bool" name="config_device_vt_available" />
+  <java-symbol type="bool" name="config_carrier_vt_available" />
   <java-symbol type="bool" name="useImsAlwaysForEmergencyCall" />
   <java-symbol type="attr" name="touchscreenBlocksFocus" />
   <java-symbol type="layout" name="resolver_list_with_default" />
diff --git a/core/res/res/values/themes_micro.xml b/core/res/res/values/themes_micro.xml
index 7e0467b..f1bc5da 100644
--- a/core/res/res/values/themes_micro.xml
+++ b/core/res/res/values/themes_micro.xml
@@ -24,6 +24,8 @@
         <item name="windowBackground">@color/black</item>
         <item name="windowContentOverlay">@null</item>
         <item name="windowIsFloating">false</item>
+        <!-- We need the windows to be translucent for SwipeToDismiss layout
+             to work properly. -->
         <item name="windowIsTranslucent">true</item>
         <item name="windowSwipeToDismiss">true</item>
     </style>
@@ -38,6 +40,8 @@
         <item name="windowBackground">@color/white</item>
         <item name="windowContentOverlay">@null</item>
         <item name="windowIsFloating">false</item>
+        <!-- We need the windows to be translucent for SwipeToDismiss layout
+             to work properly. -->
         <item name="windowIsTranslucent">true</item>
         <item name="windowSwipeToDismiss">true</item>
     </style>
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
index 80d5668..64fed7f 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestBase.java
@@ -49,7 +49,8 @@
  */
 public class ConnectivityManagerTestBase extends InstrumentationTestCase {
 
-    private static final String PING_IP_ADDR = "8.8.8.8";
+    private static final String[] PING_HOST_LIST = {
+        "www.google.com", "www.yahoo.com", "www.bing.com", "www.facebook.com", "www.ask.com"};
 
     protected static final int WAIT_FOR_SCAN_RESULT = 10 * 1000; //10 seconds
     protected static final int WIFI_SCAN_TIMEOUT = 50 * 1000; // 50 seconds
@@ -281,22 +282,14 @@
     }
 
     /**
-     * @param pingServerList a list of servers that can be used for ping test, can be null
      * @return true if the ping test is successful, false otherwise.
      */
-    protected boolean pingTest(String[] pingServerList) {
-        String[] hostList = {"www.google.com", "www.yahoo.com",
-                "www.bing.com", "www.facebook.com", "www.ask.com"};
-        if (pingServerList != null) {
-            hostList = pingServerList;
-        }
-
+    protected boolean pingTest() {
         long startTime = System.currentTimeMillis();
         while ((System.currentTimeMillis() - startTime) < PING_TIMER) {
             try {
                 // assume the chance that all servers are down is very small
-                for (int i = 0; i < hostList.length; i++ ) {
-                    String host = hostList[i];
+                for (String host : PING_HOST_LIST) {
                     logv("Start ping test, ping " + host);
                     Process p = Runtime.getRuntime().exec("ping -c 10 -w 100 " + host);
                     int status = p.waitFor();
@@ -312,6 +305,7 @@
             } catch (InterruptedException e) {
                 logv("Ping test Fail: InterruptedException");
             }
+            SystemClock.sleep(SHORT_TIMEOUT);
         }
         // ping test timeout
         return false;
@@ -458,14 +452,7 @@
     // use ping request against Google public DNS to verify connectivity
     protected boolean checkNetworkConnectivity() {
         assertTrue("no active network connection", waitForActiveNetworkConnection(LONG_TIMEOUT));
-        try {
-            Process proc = Runtime.getRuntime().exec(new String[]{
-                    "/system/bin/ping", "-W", "30", "-c", "1", PING_IP_ADDR});
-            return proc.waitFor() == 0;
-        } catch (InterruptedException | IOException e) {
-            Log.e(mLogTag, "Ping failed", e);
-        }
-        return false;
+        return pingTest();
     }
 
     @Override
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
index d5051df..2d291ff 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/functional/ConnectivityManagerMobileTest.java
@@ -72,16 +72,6 @@
         super.tearDown();
     }
 
-    // help function to verify 3G connection
-    public void verifyCellularConnection() {
-        NetworkInfo extraNetInfo = mCm.getActiveNetworkInfo();
-        assertEquals("network type is not MOBILE", ConnectivityManager.TYPE_MOBILE,
-                extraNetInfo.getType());
-        assertTrue("not connected to cellular network", extraNetInfo.isConnected());
-    }
-
-
-
     // Test case 1: Test enabling Wifi without associating with any AP, no broadcast on network
     //              event should be expected.
     @LargeTest
@@ -336,4 +326,12 @@
         assertTrue("wifi state not disabled", waitForWifiState(
                 WifiManager.WIFI_STATE_DISABLED, LONG_TIMEOUT));
     }
+
+    // help function to verify 3G connection
+    private void verifyCellularConnection() {
+        NetworkInfo extraNetInfo = mCm.getActiveNetworkInfo();
+        assertEquals("network type is not MOBILE", ConnectivityManager.TYPE_MOBILE,
+                extraNetInfo.getType());
+        assertTrue("not connected to cellular network", extraNetInfo.isConnected());
+    }
 }
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
index 41f01e6..de934b9 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiApStress.java
@@ -112,7 +112,7 @@
             } catch (Exception e) {
                 // ignore
             }
-            assertTrue("no uplink data connection after Wi-Fi tethering", pingTest(null));
+            assertTrue("no uplink data connection after Wi-Fi tethering", pingTest());
             // disable wifi hotspot
             assertTrue("failed to disable wifi hotspot",
                     mWifiManager.setWifiApEnabled(config, false));
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
index fbd4669..f3d5c87 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/stress/WifiStressTest.java
@@ -216,7 +216,7 @@
         assertTrue("wifi not connected", waitForNetworkState(ConnectivityManager.TYPE_WIFI,
                 State.CONNECTED, WIFI_CONNECTION_TIMEOUT));
         // Run ping test to verify the data connection
-        assertTrue("Wi-Fi is connected, but no data connection.", pingTest(null));
+        assertTrue("Wi-Fi is connected, but no data connection.", pingTest());
 
         long i, sum = 0, avgReconnectTime = 0;
         for (i = 1; i <= mReconnectIterations; i++) {
@@ -264,7 +264,7 @@
             } else {
                 assertEquals("mobile not connected", State.CONNECTED,
                         mCm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState());
-                assertTrue("no connectivity over mobile", pingTest(null));
+                assertTrue("no connectivity over mobile", pingTest());
             }
 
             // Turn screen on again
@@ -281,7 +281,7 @@
             avgReconnectTime = sum / i;
             logv("average reconnection time is: " + avgReconnectTime);
 
-            assertTrue("Reconnect to Wi-Fi network, but no data connection.", pingTest(null));
+            assertTrue("Reconnect to Wi-Fi network, but no data connection.", pingTest());
         }
         Bundle result = new Bundle();
         result.putLong("actual-iterations", i - 1);
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index b524177..226717e 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -1252,6 +1252,13 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="android.content.res.ResourceCacheActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
     </application>
 
     <instrumentation android:name="android.test.InstrumentationTestRunner"
diff --git a/core/tests/coretests/res/anim/reset_state_anim.xml b/core/tests/coretests/res/anim/reset_state_anim.xml
index 918d0a3..4bbbe62 100644
--- a/core/tests/coretests/res/anim/reset_state_anim.xml
+++ b/core/tests/coretests/res/anim/reset_state_anim.xml
@@ -1,4 +1,18 @@
 <?xml version="1.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.
+-->
 <set xmlns:android="http://schemas.android.com/apk/res/android">
     <objectAnimator android:propertyName="x" android:duration="100" android:valueTo="0" android:valueType="floatType"/>
     <objectAnimator android:propertyName="y" android:duration="100" android:valueTo="0" android:valueType="floatType"/>
diff --git a/core/tests/coretests/res/anim/test_animator.xml b/core/tests/coretests/res/anim/test_animator.xml
new file mode 100644
index 0000000..49afc3f
--- /dev/null
+++ b/core/tests/coretests/res/anim/test_animator.xml
@@ -0,0 +1,22 @@
+<?xml version="1.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.
+-->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+    <!-- if you change this, you should also change AnimatorInflaterTest#testLoadAnimator-->
+    <objectAnimator android:propertyName="x" android:duration="100" android:valueTo="0" android:valueType="floatType"/>
+    <objectAnimator android:propertyName="y" android:duration="100" android:valueTo="1" android:valueType="floatType"/>
+    <objectAnimator android:propertyName="left" android:duration="100" android:valueTo="2" android:valueType="intType"/>
+</set>
\ No newline at end of file
diff --git a/core/tests/coretests/res/anim/test_state_anim.xml b/core/tests/coretests/res/anim/test_state_anim.xml
index 9e08f68..b6a4822 100644
--- a/core/tests/coretests/res/anim/test_state_anim.xml
+++ b/core/tests/coretests/res/anim/test_state_anim.xml
@@ -1,4 +1,18 @@
 <?xml version="1.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.
+-->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:state_pressed="true">
         <set>
diff --git a/core/tests/coretests/res/values-land/dimens.xml b/core/tests/coretests/res/values-land/dimens.xml
new file mode 100644
index 0000000..1ee9f1d
--- /dev/null
+++ b/core/tests/coretests/res/values-land/dimens.xml
@@ -0,0 +1,18 @@
+<?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.
+-->
+<resources>
+    <dimen name="resource_cache_test_orientation_dependent">3dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/core/tests/coretests/res/values/dimens.xml b/core/tests/coretests/res/values/dimens.xml
new file mode 100644
index 0000000..00fc414
--- /dev/null
+++ b/core/tests/coretests/res/values/dimens.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+<resources>
+    <dimen name="resource_cache_test_generic">10dp</dimen>
+    <dimen name="resource_cache_test_orientation_dependent">20dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/core/tests/coretests/src/android/animation/AnimatorInflaterTest.java b/core/tests/coretests/src/android/animation/AnimatorInflaterTest.java
new file mode 100644
index 0000000..3c81853
--- /dev/null
+++ b/core/tests/coretests/src/android/animation/AnimatorInflaterTest.java
@@ -0,0 +1,61 @@
+/*
+* 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.animation;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import com.android.frameworks.coretests.R;
+
+public class AnimatorInflaterTest extends ActivityInstrumentationTestCase2<BasicAnimatorActivity>  {
+    Set<Integer> identityHashes = new HashSet<Integer>();
+
+    public AnimatorInflaterTest() {
+        super(BasicAnimatorActivity.class);
+    }
+
+    private void assertUnique(Object object) {
+        assertUnique(object, "");
+    }
+
+    private void assertUnique(Object object, String msg) {
+        final int code = System.identityHashCode(object);
+        assertTrue("object should be unique " + msg + ", obj:" + object, identityHashes.add(code));
+
+    }
+
+    public void testLoadStateListAnimator() {
+        StateListAnimator sla1 = AnimatorInflater.loadStateListAnimator(getActivity(),
+                R.anim.test_state_anim);
+        sla1.setTarget(getActivity().mAnimatingButton);
+        StateListAnimator sla2 = AnimatorInflater.loadStateListAnimator(getActivity(),
+                R.anim.test_state_anim);
+        assertNull(sla2.getTarget());
+        for (StateListAnimator sla : new StateListAnimator[]{sla1, sla2}) {
+            assertUnique(sla);
+            assertEquals(3, sla.getTuples().size());
+            for (StateListAnimator.Tuple tuple : sla.getTuples()) {
+                assertUnique(tuple);
+                assertUnique(tuple.getAnimator());
+            }
+        }
+    }
+
+}
diff --git a/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java b/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java
index 93808d9..6bcf8fc 100644
--- a/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java
+++ b/core/tests/coretests/src/android/animation/BasicAnimatorActivity.java
@@ -19,11 +19,14 @@
 
 import android.app.Activity;
 import android.os.Bundle;
+import android.widget.Button;
 
 public class BasicAnimatorActivity extends Activity {
+    public Button mAnimatingButton;
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.animator_basic);
+        mAnimatingButton = (Button) findViewById(R.id.animatingButton);
     }
 }
diff --git a/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java b/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
new file mode 100644
index 0000000..e9fd5fb
--- /dev/null
+++ b/core/tests/coretests/src/android/content/res/ConfigurationBoundResourceCacheTest.java
@@ -0,0 +1,224 @@
+/*
+ * 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.content.res;
+
+import android.test.ActivityInstrumentationTestCase2;
+import android.util.TypedValue;
+
+import com.android.frameworks.coretests.R;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class ConfigurationBoundResourceCacheTest
+        extends ActivityInstrumentationTestCase2<ResourceCacheActivity> {
+
+    ConfigurationBoundResourceCache<Float> mCache;
+
+    Method mCalcConfigChanges;
+
+    public ConfigurationBoundResourceCacheTest() {
+        super(ResourceCacheActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mCache = new ConfigurationBoundResourceCache<Float>(getActivity().getResources());
+    }
+
+    public void testGetEmpty() {
+        assertNull(mCache.get(-1, null));
+    }
+
+    public void testSetGet() {
+        mCache.put(1, null, new DummyFloatConstantState(5f));
+        assertEquals(5f, mCache.get(1, null));
+        assertNotSame(5f, mCache.get(1, null));
+        assertEquals(null, mCache.get(1, getActivity().getTheme()));
+    }
+
+    public void testSetGetThemed() {
+        mCache.put(1, getActivity().getTheme(), new DummyFloatConstantState(5f));
+        assertEquals(null, mCache.get(1, null));
+        assertEquals(5f, mCache.get(1, getActivity().getTheme()));
+        assertNotSame(5f, mCache.get(1, getActivity().getTheme()));
+    }
+
+    public void testMultiThreadPutGet() {
+        mCache.put(1, getActivity().getTheme(), new DummyFloatConstantState(5f));
+        mCache.put(1, null, new DummyFloatConstantState(10f));
+        assertEquals(10f, mCache.get(1, null));
+        assertNotSame(10f, mCache.get(1, null));
+        assertEquals(5f, mCache.get(1, getActivity().getTheme()));
+        assertNotSame(5f, mCache.get(1, getActivity().getTheme()));
+    }
+
+    public void testVoidConfigChange()
+            throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+        TypedValue staticValue = new TypedValue();
+        long key = 3L;
+        final Resources res = getActivity().getResources();
+        res.getValue(R.dimen.resource_cache_test_generic, staticValue, true);
+        float staticDim = TypedValue.complexToDimension(staticValue.data, res.getDisplayMetrics());
+        mCache.put(key, getActivity().getTheme(),
+                new DummyFloatConstantState(staticDim, staticValue.changingConfigurations));
+        final Configuration cfg = res.getConfiguration();
+        Configuration newCnf = new Configuration(cfg);
+        newCnf.orientation = cfg.orientation == Configuration.ORIENTATION_LANDSCAPE ?
+                Configuration.ORIENTATION_PORTRAIT
+                : Configuration.ORIENTATION_LANDSCAPE;
+        int changes = calcConfigChanges(res, newCnf);
+        assertEquals(staticDim, mCache.get(key, getActivity().getTheme()));
+        mCache.onConfigurationChange(changes);
+        assertEquals(staticDim, mCache.get(key, getActivity().getTheme()));
+    }
+
+    public void testEffectiveConfigChange()
+            throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+        TypedValue changingValue = new TypedValue();
+        long key = 4L;
+        final Resources res = getActivity().getResources();
+        res.getValue(R.dimen.resource_cache_test_orientation_dependent, changingValue, true);
+        float changingDim = TypedValue.complexToDimension(changingValue.data,
+                res.getDisplayMetrics());
+        mCache.put(key, getActivity().getTheme(),
+                new DummyFloatConstantState(changingDim, changingValue.changingConfigurations));
+
+        final Configuration cfg = res.getConfiguration();
+        Configuration newCnf = new Configuration(cfg);
+        newCnf.orientation = cfg.orientation == Configuration.ORIENTATION_LANDSCAPE ?
+                Configuration.ORIENTATION_PORTRAIT
+                : Configuration.ORIENTATION_LANDSCAPE;
+        int changes = calcConfigChanges(res, newCnf);
+        assertEquals(changingDim, mCache.get(key, getActivity().getTheme()));
+        mCache.onConfigurationChange(changes);
+        assertNull(mCache.get(key, getActivity().getTheme()));
+    }
+
+    public void testConfigChangeMultipleResources()
+            throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+        TypedValue staticValue = new TypedValue();
+        TypedValue changingValue = new TypedValue();
+        final Resources res = getActivity().getResources();
+        res.getValue(R.dimen.resource_cache_test_generic, staticValue, true);
+        res.getValue(R.dimen.resource_cache_test_orientation_dependent, changingValue, true);
+        float staticDim = TypedValue.complexToDimension(staticValue.data, res.getDisplayMetrics());
+        float changingDim = TypedValue.complexToDimension(changingValue.data,
+                res.getDisplayMetrics());
+        mCache.put(R.dimen.resource_cache_test_generic, getActivity().getTheme(),
+                new DummyFloatConstantState(staticDim, staticValue.changingConfigurations));
+        mCache.put(R.dimen.resource_cache_test_orientation_dependent, getActivity().getTheme(),
+                new DummyFloatConstantState(changingDim, changingValue.changingConfigurations));
+        final Configuration cfg = res.getConfiguration();
+        Configuration newCnf = new Configuration(cfg);
+        newCnf.orientation = cfg.orientation == Configuration.ORIENTATION_LANDSCAPE ?
+                Configuration.ORIENTATION_PORTRAIT
+                : Configuration.ORIENTATION_LANDSCAPE;
+        int changes = calcConfigChanges(res, newCnf);
+        assertEquals(staticDim, mCache.get(R.dimen.resource_cache_test_generic,
+                getActivity().getTheme()));
+        assertEquals(changingDim, mCache.get(R.dimen.resource_cache_test_orientation_dependent,
+                getActivity().getTheme()));
+        mCache.onConfigurationChange(changes);
+        assertEquals(staticDim, mCache.get(R.dimen.resource_cache_test_generic,
+                getActivity().getTheme()));
+        assertNull(mCache.get(R.dimen.resource_cache_test_orientation_dependent,
+                getActivity().getTheme()));
+    }
+
+    public void testConfigChangeMultipleThemes()
+            throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+        TypedValue[] staticValues = new TypedValue[]{new TypedValue(), new TypedValue()};
+        TypedValue[] changingValues = new TypedValue[]{new TypedValue(), new TypedValue()};
+        float staticDim = 0;
+        float changingDim = 0;
+        final Resources res = getActivity().getResources();
+        for (int i = 0; i < 2; i++) {
+            res.getValue(R.dimen.resource_cache_test_generic, staticValues[i], true);
+            staticDim = TypedValue
+                    .complexToDimension(staticValues[i].data, res.getDisplayMetrics());
+
+            res.getValue(R.dimen.resource_cache_test_orientation_dependent, changingValues[i],
+                    true);
+            changingDim = TypedValue.complexToDimension(changingValues[i].data,
+                    res.getDisplayMetrics());
+            final Resources.Theme theme = i == 0 ? getActivity().getTheme() : null;
+            mCache.put(R.dimen.resource_cache_test_generic, theme,
+                    new DummyFloatConstantState(staticDim, staticValues[i].changingConfigurations));
+            mCache.put(R.dimen.resource_cache_test_orientation_dependent, theme,
+                    new DummyFloatConstantState(changingDim,
+                            changingValues[i].changingConfigurations));
+        }
+        final Configuration cfg = res.getConfiguration();
+        Configuration newCnf = new Configuration(cfg);
+        newCnf.orientation = cfg.orientation == Configuration.ORIENTATION_LANDSCAPE ?
+                Configuration.ORIENTATION_PORTRAIT
+                : Configuration.ORIENTATION_LANDSCAPE;
+        int changes = calcConfigChanges(res, newCnf);
+        for (int i = 0; i < 2; i++) {
+            final Resources.Theme theme = i == 0 ? getActivity().getTheme() : null;
+            assertEquals(staticDim, mCache.get(R.dimen.resource_cache_test_generic, theme));
+            assertEquals(changingDim,
+                    mCache.get(R.dimen.resource_cache_test_orientation_dependent, theme));
+        }
+        mCache.onConfigurationChange(changes);
+        for (int i = 0; i < 2; i++) {
+            final Resources.Theme theme = i == 0 ? getActivity().getTheme() : null;
+            assertEquals(staticDim, mCache.get(R.dimen.resource_cache_test_generic, theme));
+            assertNull(mCache.get(R.dimen.resource_cache_test_orientation_dependent, theme));
+        }
+    }
+
+    private int calcConfigChanges(Resources resources, Configuration configuration)
+            throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+        if (mCalcConfigChanges == null) {
+            mCalcConfigChanges = Resources.class.getDeclaredMethod("calcConfigChanges",
+                    Configuration.class);
+            mCalcConfigChanges.setAccessible(true);
+        }
+        return (Integer) mCalcConfigChanges.invoke(resources, configuration);
+
+    }
+
+    static class DummyFloatConstantState extends
+            ConstantState<Float> {
+
+        final Float mObj;
+
+        int mChangingConf = 0;
+
+        DummyFloatConstantState(Float obj) {
+            mObj = obj;
+        }
+
+        DummyFloatConstantState(Float obj, int changingConf) {
+            mObj = obj;
+            mChangingConf = changingConf;
+        }
+
+        @Override
+        public int getChangingConfigurations() {
+            return mChangingConf;
+        }
+
+        @Override
+        public Float newInstance() {
+            return new Float(mObj);
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/content/res/ResourceCacheActivity.java b/core/tests/coretests/src/android/content/res/ResourceCacheActivity.java
new file mode 100644
index 0000000..f37e549
--- /dev/null
+++ b/core/tests/coretests/src/android/content/res/ResourceCacheActivity.java
@@ -0,0 +1,37 @@
+/*
+* 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.content.res;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.os.Bundle;
+
+import java.lang.ref.WeakReference;
+
+public class ResourceCacheActivity extends Activity {
+    static WeakReference<ResourceCacheActivity> lastCreatedInstance;
+
+    @Override
+    protected void onCreate(@Nullable Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        lastCreatedInstance = new WeakReference<ResourceCacheActivity>(this);
+    }
+
+    public static ResourceCacheActivity getLastCreatedInstance() {
+        return lastCreatedInstance == null ? null : lastCreatedInstance.get();
+    }
+}
diff --git a/docs/html/about/versions/android-5.0.jd b/docs/html/about/versions/android-5.0.jd
index f8d8ab6..a438420 100644
--- a/docs/html/about/versions/android-5.0.jd
+++ b/docs/html/about/versions/android-5.0.jd
@@ -23,6 +23,7 @@
 <li><a href="#BehaviorGetRecentTasks">If your app uses getRecentTasks()...</a></li>
 <li><a href="#64BitSupport">If you are using the Android Native Development Kit (NDK)...</a></li>
 <li><a href="#BindService">If your app binds to a Service...</a></li>
+<li><a href="#BehaviorWebView">If your app uses a WebView...</a></li>
     </ol>
   </li>
   <li><a href="#UI">User Interface</a>
@@ -234,8 +235,8 @@
 vibration.</p>
 
 <p>Setting the device to
-{@link android.media.AudioManager#RINGER_MODE_SILENT RINGER_MODE_SILENT} now
-causes the device to enter the new priority mode. The device leaves priority
+{@link android.media.AudioManager#RINGER_MODE_SILENT RINGER_MODE_SILENT} causes
+the device to enter the new priority mode. The device leaves priority
 mode if you set it to
 {@link android.media.AudioManager#RINGER_MODE_NORMAL RINGER_MODE_NORMAL} or
 {@link android.media.AudioManager#RINGER_MODE_NORMAL RINGER_MODE_VIBRATE}.</p>
@@ -366,6 +367,31 @@
 To ensure your app is secure, use an explicit intent when starting or binding
 your {@link android.app.Service}, and do not declare intent filters for the service.</p>
 
+<h3 id="BehaviorWebView">If your app uses WebView...</h3>
+
+<p>Android 5.0 changes the default behavior for your app.</p>
+<ul>
+<li><strong>If your app targets API level 21 or higher:</strong>
+  <ul>
+    <li>The system
+  blocks <a href="https://developer.mozilla.org/en-US/docs/Security/MixedContent"
+  class="external-link">mixed content</a> and third party cookies by default. To allow mixed
+  content and third party cookies, use the
+  {@link android.webkit.WebSettings#setMixedContentMode(int) setMixedContentMode()}
+and {@link android.webkit.CookieManager#setAcceptThirdPartyCookies(android.webkit.WebView, boolean) setAcceptThirdPartyCookies()}
+methods respectively.</li>
+    <li>The system now intelligently chooses portions of the HTML
+      document to draw. This new default behavior helps to reduce memory
+      footprint and increase performance. If you want to
+      render the whole document at once, disable this optimization by calling
+      {@link android.webkit.WebView#enableSlowWholeDocumentDraw()}.</li>
+  </ul>
+</li>
+<li><strong>If your app targets API levels lower than 21:</strong> The system
+  allows mixed content and third party cookies, and always renders the whole
+  document at once.</li>
+</ul>
+
 <h2 id="UI">User Interface</h2>
 
 <h3 id="MaterialDesign">Material design support</h3>
@@ -470,7 +496,7 @@
 method.</p>
 
 <p>For an example of how to use the new APIs, see the {@code MediaProjectionDemo}
-class in the {@code ApiDemos} sample project.</p>
+class in the sample project.</p>
 
 <h2 id="Notifications">Notifications</h2>
 
diff --git a/docs/html/about/versions/lollipop.jd b/docs/html/about/versions/lollipop.jd
index 085dc24..3ee0a86 100644
--- a/docs/html/about/versions/lollipop.jd
+++ b/docs/html/about/versions/lollipop.jd
@@ -206,15 +206,16 @@
 <p>Android 5.0 also adds support for <strong>multimedia tunneling</strong> to provide the best experience for ultra-high definition (4K) content and the ability to play compressed audio and video data together. </p>
 
 
-<!--
+
 <div class="figure" style="width:320px; margin:1em 0 0 20px;padding-left:2em;">
 <img style="float:right; margin:0 1em 1em 2em"
     src="{@docRoot}images/android-5.0/managed_apps_launcher@2x.png"
     srcset="{@docRoot}images/android-5.0/managed_apps_launcher@2x.png 2x"
     alt="" width="300" />
-<p class="img-caption">Android Work users have a unified view of their personal and work apps, which are badged for easy identification.</p>
+<p class="img-caption">Users have a unified view of their personal and work apps, which are
+badged for easy identification.</p>
 </div>
--->
+
 
 <h2 id="Work">Android in the workplace</h2>
 
diff --git a/docs/html/distribute/essentials/essentials_toc.cs b/docs/html/distribute/essentials/essentials_toc.cs
index 4e53468..a1c9575 100644
--- a/docs/html/distribute/essentials/essentials_toc.cs
+++ b/docs/html/distribute/essentials/essentials_toc.cs
@@ -17,6 +17,12 @@
     </div>
   </li>
   <li class="nav-section">
+    <div class="nav-section empty" style="font-weight:normal"><a href="<?cs var:toroot?>distribute/essentials/quality/wear.html">
+            <span class="en">Wear App Quality</span>
+          </a>
+    </div>
+  </li>
+  <li class="nav-section">
     <div class="nav-section empty" style="font-weight:normal"><a href="<?cs var:toroot?>distribute/essentials/optimizing-your-app.html">
           <span class="en">Optimize Your App</span>
         </a>
diff --git a/docs/html/distribute/essentials/quality/tv.jd b/docs/html/distribute/essentials/quality/tv.jd
index 8e17157..b13307e 100644
--- a/docs/html/distribute/essentials/quality/tv.jd
+++ b/docs/html/distribute/essentials/quality/tv.jd
@@ -234,7 +234,7 @@
   </td>
   <td>
     <p style="margin-bottom:.5em;">
-      App does not depend on a remote controller having a menu button to access user interface
+      App does not depend on a remote controller having a Menu button to access user interface
       controls.
       (<a href="{@docRoot}training/tv/start/navigation.html#d-pad-navigation">Learn how</a>)
     </p>
@@ -291,8 +291,8 @@
   </td>
   <td>
     <p style="margin-bottom:.5em;">
-      App manifest sets an intent type of {@code ACTION_MAIN} with category
-      {@code CATEGORY_LEANBACK_LAUNCHER}.
+      App manifest sets an intent type of {@link android.content.Intent#ACTION_MAIN} with category
+      {@link android.content.Intent#CATEGORY_LEANBACK_LAUNCHER}.
       (<a href="{@docRoot}training/tv/start/start.html#tv-activity">Learn how</a>)
     </p>
   </td>
@@ -321,8 +321,9 @@
   </td>
   <td>
     <p style="margin-bottom:.5em;">
-      If the app requires a game controller, the app manifest sets the {@code uses-feature} setting
-      {@code android.hardware.gamepad} to {@code required="true"}.
+      If the app uses a game controller as it's primary input method, it declares the appropriate
+      requirement with the <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html"
+      >{@code &lt;uses-feature>}</a> manifest tag.
       (<a href="{@docRoot}training/tv/games/index.html#gamepad">Learn how</a>)
     </p>
   </td>
@@ -334,9 +335,9 @@
   </td>
   <td>
     <p style="margin-bottom:.5em;">
-      If the app provides user instructions for use of game controllers, the instructions
-      do not include a controller with any branding.
-      (<a href="{@docRoot}training/tv/games/index.html#generic-controllers">Learn how</a>)
+      If the app provides visual instructions for using game controllers, the instructions should
+      be free of branding and show a compatible button layout.
+      (<a href="{@docRoot}training/tv/games/index.html#ControllerHelp">Learn how</a>)
     </p>
   </td>
 </tr>
@@ -351,7 +352,7 @@
   </td>
   <td>
     <p style="margin-bottom:.5em;">
-      App enables interaction with any advertising using D-pad controls.
+      App allows interaction with advertising using D-pad controls.
       (<a href="{@docRoot}training/tv/start/navigation.html#d-pad-navigation">Learn how</a>)
     </p>
   </td>
@@ -363,7 +364,7 @@
   </td>
   <td>
     <p style="margin-bottom:.5em;">
-      For advertising that uses full-screen, non-video ads, the app allows the user to
+      For advertising that uses fullscreen, non-video ads, the app allows the user to
       immediately dismiss the ad with D-pad controls.
     </p>
   </td>
@@ -375,7 +376,7 @@
   </td>
   <td>
     <p style="margin-bottom:.5em;">
-      For advertising that uses clickable, non-full screen, non-video ads, the app does not allow
+      For advertising that uses clickable, non-fullscreen, non-video ads, the app does not allow
       ads to link to a web URL.
     </p>
   </td>
@@ -387,7 +388,7 @@
   </td>
   <td>
     <p style="margin-bottom:.5em;">
-      For advertising that uses clickable, non-full screen, non-video ads, the app does not allow
+      For advertising that uses clickable, non-fullscreen, non-video ads, the app does not allow
       ads to link to another app that is not available on TV devices.
     </p>
   </td>
diff --git a/docs/html/distribute/essentials/quality/wear.jd b/docs/html/distribute/essentials/quality/wear.jd
new file mode 100644
index 0000000..667e945
--- /dev/null
+++ b/docs/html/distribute/essentials/quality/wear.jd
@@ -0,0 +1,387 @@
+page.title=Wear App Quality
+page.tags="wear","wearables","quality","guidelines"
+page.metaDescription=Wearables are small factor devices that are built for glanceability and require unique design and functionality.
+page.image=/distribute/images/gp-wear-quality.png
+@jd:body
+
+<div id="qv-wrapper"><div id="qv">
+<h2>Quality Criteria</h2>
+  <ol>
+    <li><a href="#ux">Design and Interaction</a></li>
+    <li><a href="#fn">Functionality</a></li>
+    <li><a href="#faq">Frequently Asked Questions</a></li>
+  </ol>
+
+  <h2>You Should Also Read</h2>
+  <ol>
+    <li><a href="{@docRoot}distribute/essentials/quality/core.html">
+      Core App Quality</a></li>
+    <li><a href="{@docRoot}distribute/essentials/optimizing-your-app.html">
+      Optimize Your App</a></li>
+    <li><a href="{@docRoot}design/patterns/notifications.html">
+      Notifications</a></li>
+  </ol>
+</div>
+</div>
+
+<img src="{@docRoot}distribute/images/gp-wear-quality.png" style="width:480px;">
+
+<p>
+  Android Wear aims to provide users with just the right information at just the right time. Great
+  Android Wear experiences are launched automatically, glanceable, and require zero or low user
+  interaction. Designing apps for wearables is substantially different than designing for phones or
+  tablets. There are different strengths and weaknesses, different use cases, and different
+  ergonomics to take into consideration.
+</p>
+
+<p>
+  The first step toward creating a great experience for users on Wear is to read the
+  <a href="{@docRoot}design/wear/index.html">Android Wear design guidelines</a>, which provides
+  instructions on how to build the best user experience for Wear apps. You should also review the
+  <a href="{@docRoot}training/building-wearables.html">Building Apps for Wearables</a> training, to
+  understand the basic implementation requirements for a Wear app.
+</p>
+
+<p class="caution">
+  <strong>Important:</strong> To ensure a great user experience, apps for wearables must meet
+  specific requirements for usability. Only apps that meet the following quality criteria will
+  qualify as an Android Wear app on Google Play. Qualifying as a Wear app will make it easier for
+  Android Wear users to discover your app on Google Play.
+</p>
+
+<p class="note">
+ <strong>Note:</strong> You will be able to submit your apps for Android Wear review when the
+ public release of Android 5.0 launches on November 3. Stay tuned for more information about how to
+ submit your apps for Android Wear review through the <a href="https://play.google.com/apps/publish/signup/">Google Play Developer Console</a>.
+</p>
+
+<div class="headerLine">
+  <h2 id="fn">
+  Functionality
+  </h2>
+
+
+</div>
+
+<p>
+  These criteria ensure that your app is configured correctly and provides the expected
+  functional behavior.
+</p>
+
+
+<table>
+<tr>
+  <th style="width:2px;">
+    Type
+  </th>
+  <th style="width:54px;">
+    ID
+  </th>
+  <th>
+    Description
+  </th>
+</tr>
+
+<tr>
+  <td rowspan="1" id="general">
+   General
+  </td>
+
+  <td id="WR-GL">
+    WR-GL
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+      Handheld app includes either notifications with wearable-specific functionality or a wearable
+      app that runs directly on the Wear device.
+      (<a href="{@docRoot}training/building-wearables.html">Learn how</a>)
+    </p>
+  </td>
+</tr>
+
+<tr>
+  <td rowspan="1" id="packaging">
+   Packaging
+  </td>
+
+  <td id="WR-PK">
+    WR-PK
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+      Wearable apps that run directly on the device are packaged inside the primary handheld app.
+      (<a href="{@docRoot}training/wearables/apps/packaging.html">Learn how</a>)
+    </p>
+  </td>
+</tr>
+
+
+<tr>
+  <td rowspan="3" id="functional-notifications">
+    Notifications
+  </td>
+
+  <td id="WR-FW">
+    WR-FW
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+      Notifications with wearable-specific functionality use a {@code RemoteInput} or
+      {@code WearableExtender}.
+      (<a href="{@docRoot}training/wearables/notifications/index.html">Learn how</a>)
+    </p>
+  </td>
+</tr>
+
+<tr>
+  <td id="WR-FR">
+    WR-FR
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+      Notifications for messaging apps allow users to reply via voice input or quick responses.
+      (<a href="{@docRoot}training/wearables/notifications/voice-input.html">Learn how</a>)
+    </p>
+  </td>
+</tr>
+
+<tr>
+  <td id="WR-FG">
+    WR-FG
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+      Similar notifications are grouped together in a stack.
+      (<a href="{@docRoot}training/wearables/notifications/stacks.html">Learn how</a>)
+    </p>
+  </td>
+</tr>
+
+<tr>
+  <td rowspan="1" id="gestures">
+    Gestures
+  </td>
+
+  <td id="WR-GP">
+    WR-GP
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+      Full-screen activities use long press for the sole purpose of prompting to quit.
+      <br/>
+      (<a href="{@docRoot}training/wearables/ui/exit.html">Learn how</a>)
+    </p>
+  </td>
+</tr>
+
+</table>
+
+
+<h3 class="rel-resources clearfloat">Related resources</h3>
+
+<div class="resource-widget resource-flow-layout col-13" data-query=
+"collection:distribute/essentials/wearqualityguidelines/functionality"
+data-sortorder="-timestamp" data-cardsizes="6x2" data-maxresults="6">
+</div>
+
+<div class="headerLine">
+  <h2 id="ux">
+  Visual Design and User Interaction
+  </h2>
+
+
+</div>
+
+<p>
+  These criteria ensure that your app follows critical design and interaction patterns to provide a
+  consistent, intuitive, and enjoyable user experience on wearables.
+</p>
+
+<table>
+
+<tr>
+  <th style="width:2px;">
+    Type
+  </th>
+  <th style="width:54px;">
+    ID
+  </th>
+  <th>
+    Description
+  </th>
+</tr>
+
+<tr>
+  <td rowspan="2" id="layout">
+    Layout
+  </td>
+
+  <td id="WR-LL">
+    WR-LL
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+      App user interface is formatted appropriately for both square and round displays.
+      (<a href="{@docRoot}training/wearables/ui/layouts.html">Learn how</a>)
+    </p>
+  </td>
+</tr>
+
+<tr>
+  <td id="WR-TC">
+    WR-TC
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+      App text is large and glanceable with a suggested minimum size of 16sp.
+      (<a href="{@docRoot}design/wear/style.html#Typography">Learn how</a>)
+    </p>
+  </td>
+</tr>
+
+<tr>
+  <td rowspan="1" id="launcher">
+    Launcher
+  </td>
+
+  <td id="WR-LN">
+    WR-LN
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+      App launcher string is the app name, not a command phrase.
+      (<a href="{@docRoot}guide/topics/manifest/intent-filter-element.html">Learn how</a>)
+    </p>
+  </td>
+</tr>
+
+<tr>
+  <td rowspan="5" id="notifications">
+    Notifications
+  </td>
+
+  <td id="WR-NC">
+    WR-NC
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+      App displays confirmation animations when appropriate.
+      (<a href="{@docRoot}design/wear/patterns.html#Countdown">Learn how</a>)
+    </p>
+  </td>
+</tr>
+
+<tr>
+  <td id="WR-NR">
+    WR-NR
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+      Notification cards have the app icon visible at the top right edge. The one exception is if the
+      notification card has single-action controls, for example a media playback card.
+      <br/>
+      (<a href="{@docRoot}design/wear/style.html#Assets">Learn how</a>)
+    </p>
+  </td>
+</tr>
+
+<tr>
+  <td id="WR-WI">
+    WR-WI
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+      Notification actions have a white icon, action title, and transparent background.
+      <br/>
+      (<a href="{@docRoot}training/wearables/notifications/creating.html#ActionButtons">Learn how</a>)
+    </p>
+  </td>
+</tr>
+
+<tr>
+  <td id="WR-PB">
+    WR-PB
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+      Notification photo backgrounds are used only to convey information, not to brand a card.
+      (<a href="{@docRoot}design/wear/style.html#Branding">Learn how</a>)
+    </p>
+  </td>
+</tr>
+
+<tr>
+  <td id="WR-PR">
+    WR-PR
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+      Notification photo backgrounds have a resolution of at least 400x400.
+      (<a href="{@docRoot}training/wearables/notifications/creating.html#AddWearableFeatures">Learn how</a>)
+    </p>
+  </td>
+</tr>
+
+<tr>
+  <td rowspan="1" id="googleplay">
+    Google Play
+  </td>
+
+  <td id="WR-GS">
+    WR-GS
+  </td>
+  <td>
+    <p style="margin-bottom:.5em;">
+      App includes at least one Wear screenshot in its Play Store Listing.
+      (<a href="https://support.google.com/googleplay/android-developer/answer/1078870?hl=en">Learn how</a>)
+    </p>
+  </td>
+</tr>
+
+</table>
+
+
+<h3 class="rel-resources clearfloat">Related resources</h3>
+
+<div class="resource-widget resource-flow-layout col-13" data-query=
+"collection:distribute/essentials/wearqualityguidelines/visualdesign"
+data-sortorder="-timestamp" data-cardsizes="6x2" data-maxresults="6">
+</div>
+
+<div class="headerLine">
+  <h2 id="faq">
+  Frequently Asked Questions
+  </h2>
+</div>
+
+<p style="margin-top:30px;">
+  <strong>After I submit my app for Android Wear review, how will I find out if my app does not meet
+  all the requirements for Wear?</strong>
+</p>
+<p>
+  If your app does not meet the usability requirements described on this page, the Play Store team
+  will contact you through the email address specified in the <a href=
+  "https://play.google.com/apps/publish/">Google Play Developer Console</a> account associated with
+  the app.
+</p>
+<p class="caution">
+  <strong>Caution:</strong> Make sure your app meets the <a href="#fn">functionality
+  requirements</a>, otherwise your app will not be considered a Wear app and will not be reviewed
+  for Wear <a href="#ux">design and interaction</a>.
+</p>
+<p class="note">
+ <strong>Note:</strong> You will be able to submit your apps for additional Android Wear review when
+ the public release of Android 5.0 launches on November 3.
+</p>
+
+
+<p style="margin-top:30px;">
+  <strong>If my app does not meet the Wear requirements, will my new or updated app still appear on
+  Google Play for phones and tablets and still be installable on wearables?</strong>
+</p>
+<p>
+  Yes. The requirements described above only determine whether your app will be identified as an
+  Android Wear app on Google Play and easier for Android Wear users to discover. If your app is not
+  accepted as a Wear app, it will still be available to other device types, such as phones and
+  tablets, and it will still be installable on wearables.
+</p>
diff --git a/docs/html/distribute/images/gp-wear-quality.png b/docs/html/distribute/images/gp-wear-quality.png
new file mode 100644
index 0000000..a51a32c
--- /dev/null
+++ b/docs/html/distribute/images/gp-wear-quality.png
Binary files differ
diff --git a/docs/html/images/android-5.0/managed_apps_launcher.png b/docs/html/images/android-5.0/managed_apps_launcher.png
index 8184556..46e4c74 100644
--- a/docs/html/images/android-5.0/managed_apps_launcher.png
+++ b/docs/html/images/android-5.0/managed_apps_launcher.png
Binary files differ
diff --git a/docs/html/images/android-5.0/managed_apps_launcher@2x.png b/docs/html/images/android-5.0/managed_apps_launcher@2x.png
index 66b7be9..d7fdbce 100644
--- a/docs/html/images/android-5.0/managed_apps_launcher@2x.png
+++ b/docs/html/images/android-5.0/managed_apps_launcher@2x.png
Binary files differ
diff --git a/docs/html/images/games/game-controller-buttons.png b/docs/html/images/games/game-controller-buttons.png
new file mode 100644
index 0000000..b3e458a
--- /dev/null
+++ b/docs/html/images/games/game-controller-buttons.png
Binary files differ
diff --git a/docs/html/images/games/game-controller-buttons_2x.png b/docs/html/images/games/game-controller-buttons_2x.png
new file mode 100644
index 0000000..7a0ad0b
--- /dev/null
+++ b/docs/html/images/games/game-controller-buttons_2x.png
Binary files differ
diff --git a/docs/html/jd_collections.js b/docs/html/jd_collections.js
index c49f8cc..08c0090 100644
--- a/docs/html/jd_collections.js
+++ b/docs/html/jd_collections.js
@@ -67,9 +67,9 @@
       "distribute/essentials/quality/core.html",
       "distribute/essentials/quality/tablets.html",
       "distribute/essentials/quality/tv.html",
+      "distribute/essentials/quality/wear.html",
       "https://developers.google.com/edu/guidelines",
-      "distribute/essentials/optimizing-your-app.html",
-      "distribute/essentials/best-practices/games.html"
+      "distribute/essentials/optimizing-your-app.html"
     ]
   },
   "distribute/users": {
@@ -332,6 +332,22 @@
       "training/tv/games/index.html"
     ]
   },
+  "distribute/essentials/wearqualityguidelines/visualdesign": {
+    "title": "",
+    "resources": [
+      "design/wear/index.html",
+      "training/building-wearables.html",
+      "training/wearables/ui/index.html"
+    ]
+  },
+  "distribute/essentials/wearqualityguidelines/functionality": {
+    "title": "",
+    "resources": [
+      "training/wearables/notifications/index.html",
+      "training/wearables/apps/index.html",
+      "training/wearables/notifications/voice-input.html"
+    ]
+  },
   "distribute/essentials/core/performance": {
     "title": "",
     "resources": [
diff --git a/docs/html/samples/new/index.jd b/docs/html/samples/new/index.jd
index 523b922..330caa3 100644
--- a/docs/html/samples/new/index.jd
+++ b/docs/html/samples/new/index.jd
@@ -348,3 +348,18 @@
 </p>
 
 <p><a href="http://github.com/googlesamples/android-AppRestrictionSchema">Get it on GitHub</a></p>
+
+<h3 id="SpeedTracker">Speed Tracker (Wear)</h3>
+
+<p>
+This sample uses the FusedLocation APIs of Google Play Services on Android Wear 
+devices that have a hardware GPS built in. In those cases, this sample provides
+a simple screen that shows the current speed of the wearable device. User can
+set a speed limit and if the speed approaches that limit, it changes the color
+to yellow and if it exceeds the limit, it turns red. User can also enable
+recording of coordinates and when it pairs back with the phone, this data
+is synced with the phone component of the app and user can see a track
+made of those coordinates on a map on the phone.
+</p>
+
+<p><a href="http://github.com/googlesamples/android-SpeedTracker">Get it on GitHub</a></p>
diff --git a/docs/html/samples/wearable.jd b/docs/html/samples/wearable.jd
new file mode 100644
index 0000000..3114374
--- /dev/null
+++ b/docs/html/samples/wearable.jd
@@ -0,0 +1,11 @@
+page.title=Wearable
+@jd:body
+
+
+<div id="samples" class="wearable">
+</div>
+
+
+<script>
+  $(document).ready(showSamples);
+</script>
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index 3d9ef21..a646795 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -243,7 +243,7 @@
 <h1 style="margin-top:0">Get the Android SDK</h1>
 
 
-<p>The Android SDK provides you the API libraries and developer tools necessary to build, test,
+<p>The Android SDK provides the API libraries and developer tools necessary to build, test,
   and debug apps for Android.</p>
 
 <p>Download the ADT Bundle to quickly start developing apps. It includes the essential Android
diff --git a/docs/html/sdk/installing/adding-packages.jd b/docs/html/sdk/installing/adding-packages.jd
index e6c0118..22d055c 100644
--- a/docs/html/sdk/installing/adding-packages.jd
+++ b/docs/html/sdk/installing/adding-packages.jd
@@ -1,5 +1,8 @@
 page.title=Adding SDK Packages
 
+page.tags=studio, sdk tools, eclipse adt, sdk manager, google play services, support library
+helpoutsWidget=true
+
 @jd:body
 
 <style>
diff --git a/docs/html/sdk/installing/index.jd b/docs/html/sdk/installing/index.jd
index ec0e2f8..6a99952 100644
--- a/docs/html/sdk/installing/index.jd
+++ b/docs/html/sdk/installing/index.jd
@@ -1,5 +1,8 @@
 page.title=Installing the Android SDK
 
+page.tags=studio, sdk tools, eclipse adt
+helpoutsWidget=true
+
 @jd:body
 
 <style>
diff --git a/docs/html/support.jd b/docs/html/support.jd
index 4271eee..bbed7df 100644
--- a/docs/html/support.jd
+++ b/docs/html/support.jd
@@ -3,6 +3,7 @@
 fullpage=1
 page.metaDescription=Resources available to help you report and resolve issues while you are developing apps for Android.
 page.image=/images/android-support-card.png
+
 @jd:body
 
 <div class="wrap" style="width:940px;">
@@ -28,13 +29,20 @@
   <a href="http://webchat.freenode.net/?channels=android">#android</a>, <a href="http://webchat.freenode.net/?channels=android-dev">#android-dev</a> <span style="color:#888">(IRC via irc.freenode.net)</span><br />
 </p>
 
+<p><b>
+<a target="_blank"
+href="https://helpouts.google.com/partner/ask?vertical=programming&tags=android&origin=http:%2F%2Fdeveloper.android.com%2Fsupport.html">Ask a question in Google Helpouts</a>
+</b></p>
+
 
 <h5>Send Feedback</h5>
 <p>
   <a href="http://code.google.com/p/android/issues/entry?template=Developer%20Documentation">Report documentation bug</a><br />
   <a href="https://code.google.com/p/android/issues/entry?template=User%20bug%20report">Report device bug</a><br />
   <a href="https://code.google.com/p/android/issues/entry?template=Developer%20bug%20report">Report platform bug</a><br />
-  
+</p>
+
+
   </div>
 
   
diff --git a/docs/html/tools/debugging/debugging-memory.jd b/docs/html/tools/debugging/debugging-memory.jd
index fccb67e..ae67b3c 100644
--- a/docs/html/tools/debugging/debugging-memory.jd
+++ b/docs/html/tools/debugging/debugging-memory.jd
@@ -243,7 +243,7 @@
    Other mmap    107       0       8       8     324      68
       Unknown   6994(4)    0     252    6992(4)    0       0
         TOTAL  24358(1) 4188    9724   17972(2)16388    4260(2)16968   16595     336
- 
+
  Objects
                Views:    426         ViewRootImpl:        3(8)
          AppContexts:      6(7)        Activities:        2(7)
@@ -251,7 +251,7 @@
        Local Binders:     64        Proxy Binders:       34
     Death Recipients:      0
      OpenSSL Sockets:      1
- 
+
  SQL
          MEMORY_USED:   1739
   PAGECACHE_OVERFLOW:   1164          MALLOC_SIZE:       62
@@ -374,7 +374,7 @@
 <p>To analyze your heap dump, you can use a standard tool like jhat or the <a href=
 "http://www.eclipse.org/mat/downloads.php">Eclipse Memory Analyzer Tool</a> (MAT). However, first
 you'll need to convert the HPROF file from Android's format to the J2SE HPROF format. You can do
-this using the <code>hprof-conv</code> tool provided in the <code>&lt;sdk&gt;/tools/</code>
+this using the <code>hprof-conv</code> tool provided in the <code>&lt;sdk&gt;/platform-tools/</code>
 directory. Simply run the <code>hprof-conv</code> command with two arguments: the original HPROF
 file and the location to write the converted HPROF file. For example:</p>
 
diff --git a/docs/html/tools/revisions/build-tools.jd b/docs/html/tools/revisions/build-tools.jd
index fe78ce9..6f07755 100644
--- a/docs/html/tools/revisions/build-tools.jd
+++ b/docs/html/tools/revisions/build-tools.jd
@@ -77,6 +77,28 @@
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>Build Tools, Revision 21.0.2</a> <em>(October 2014)</em>
+  </p>
+  <div class="toggle-content-toggleme">
+    <p>Complete updates for Eclipse ADT to solve instability issues on Windows platforms.</p>
+  </div>
+</div>
+
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
+      alt=""/>Build Tools, Revision 21.0.1</a> <em>(October 2014)</em>
+  </p>
+  <div class="toggle-content-toggleme">
+    <p>Initial updates for Eclipse ADT on Windows. Please use Revision 21.0.2.</p>
+  </div>
+</div>
+
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>Build Tools, Revision 21.0.0</a> <em>(October 2014)</em>
   </p>
   <div class="toggle-content-toggleme">
@@ -96,6 +118,7 @@
   </div>
 </div>
 
+
 <div class="toggle-content closed">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
diff --git a/docs/html/tools/revisions/platforms.jd b/docs/html/tools/revisions/platforms.jd
index 3fa1b9b..85b9c5e 100644
--- a/docs/html/tools/revisions/platforms.jd
+++ b/docs/html/tools/revisions/platforms.jd
@@ -80,6 +80,23 @@
 
 <h2 id="4.4">Android 4.4W</h2>
 
+<div class="toggle-content open">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-open.png"
+class="toggle-content-img" alt="" />Revision 2</a> <em>(October 2014)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+
+    <p>Added location APIs support for Wear.</p>
+
+    <p>Dependencies:</p>
+    <ul>
+      <li>Android SDK Platform-tools r20 or higher is required.</li>
+      <li>Android SDK Tools 23.0 or higher is required.</li>
+    </ul>
+  </div>
+
 <div class="toggle-content closed">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-closed.png"
diff --git a/docs/html/tools/sdk/tools-notes.jd b/docs/html/tools/sdk/tools-notes.jd
index 20388be..3e3cb4b 100644
--- a/docs/html/tools/sdk/tools-notes.jd
+++ b/docs/html/tools/sdk/tools-notes.jd
@@ -13,7 +13,7 @@
 of the SDK Tools, use the <em>Android SDK Manager</em> to get the
 update, rather than downloading a new SDK starter package. For more information
 about how to update, see <a
-href="{@docRoot}sdk/exploring.html#UpdatingComponents">Exploring the SDK</a>.</p>
+href="{@docRoot}tools/help/sdk-manager.html">SDK Manager</a>.</p>
 
 
 <h2 id="notes">Revisions</h2>
diff --git a/docs/html/tools/support-library/features.jd b/docs/html/tools/support-library/features.jd
index 8311097..44c5045 100644
--- a/docs/html/tools/support-library/features.jd
+++ b/docs/html/tools/support-library/features.jd
@@ -139,10 +139,10 @@
 <p>The Gradle build script dependency identifier for this library is as follows:</p>
 
 <pre>
-com.android.support:support-v4:18.0.+
+com.android.support:support-v4:21.0.+
 </pre>
 
-<p>This dependency notation specifies the release version 18.0.0 or higher.</p>
+<p>This dependency notation specifies the release version 21.0.0 or higher.</p>
 
 
 <h2 id="v7">v7 Support Libraries</h2>
@@ -237,10 +237,10 @@
 <p>The Gradle build script dependency identifier for this library is as follows:</p>
 
 <pre>
-com.android.support:gridlayout-v7:18.0.+
+com.android.support:gridlayout-v7:21.0.+
 </pre>
 
-<p>This dependency notation specifies the release version 18.0.0 or higher.</p>
+<p>This dependency notation specifies the release version 21.0.0 or higher.</p>
 
 
 <h3 id="v7-mediarouter">v7 mediarouter library</h3>
@@ -271,10 +271,10 @@
 
 <p>If you are using Android Studio, all you need to do is specify the Gradle build
 script dependency identifier <code>com.android.support:support-v7-mediarouter:&lt;revision&gt;</code>,
-where "18.0.0" is the minimum revision at which the library is available. For example:</p>
+where "&lt;revision&gt;" is the minimum revision at which the library is available. For example:</p>
 
 <pre>
-com.android.support:mediarouter-v7:18.0.+
+com.android.support:mediarouter-v7:21.0.+
 </pre>
 
 <p class="caution">The v7 mediarouter library APIs introduced in Support Library
diff --git a/docs/html/training/articles/wear-location-detection.jd b/docs/html/training/articles/wear-location-detection.jd
new file mode 100644
index 0000000..b0d9755
--- /dev/null
+++ b/docs/html/training/articles/wear-location-detection.jd
@@ -0,0 +1,375 @@
+page.title=Detecting Location on Android Wear
+page.tags="gps"
+
+page.article=true
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+<h2>In this document</h2>
+<ol class="nolist">
+  <li><a href="#Connect">Connect to Google Play Services</a></li>
+  <li><a href="#Request">Request Location Updates</a></li>
+  <li><a href="#DetectGPS">Detect On-Board GPS</a></li>
+  <li><a href="#Disconnection">Handle Disconnection Events</a></li>
+  <li><a href="#Notify">Handle Location Not Found</a></li>
+  <li><a href="#Synchronize">Synchronize Data</a></li>
+</ol>
+<!-- Required platform, tools, add-ons, devices, knowledge, etc. -->
+<h2>Dependencies and prerequisites</h2>
+<ul>
+  <li>Android 4.3 (API Level 18) or higher on the handset device</li>
+  <li><a href="{@docRoot}google/play-services/index.html">Google Play services</a> 6.1 or higher</li>
+  <li>An Android Wear device</li>
+</ul>
+<h2>See also</h2>
+<ul>
+  <li><a href="{@docRoot}training/location/index.html">Making Your App Location-Aware
+  </a></li>
+</ul>
+</div></div>
+
+<p>Location awareness on wearable devices enables you to create apps that give users a better
+understanding of their geographic position, movement and what's around them. With the small form
+factor and glanceable nature of a wearable device, you can build low-friction apps that record and
+respond to location data.</p>
+
+<p>Some wearable devices include a GPS sensor that can retrieve location data without another
+tethered device. However, when you request location data in a wearable app, you don't have to worry
+about where the location data originates; the system retrieves the location updates using the most
+power-efficient method. Your app should be able to handle loss of location data, in case the wear
+device loses connection with its paired device and does not have a built-in GPS sensor.</p>
+
+<p>This document shows you how to check for on-device location sensors, receive location data, and
+monitor tethered data connections.</p>
+
+<p class="note"><b>Note:</b> The article assumes that you know how to use the Google Play services
+API to retrieve location data. For more information, see <a href="{@docRoot}training/
+location/index.html">Making Your App Location-Aware</a>.</p>
+
+<h2 id="Connect">Connect to Google Play Services</h2>
+
+<p>Location data on wearable devices is obtained though the Google Play services location APIs. You
+use the <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html">
+<code>FusedLocationProviderApi</code></a> and its accompanying classes to obtain this data.
+To access location services, create an instance of
+<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">
+<code>GoogleApiClient</code></a>, which is
+the main entry point for any of the Google Play services APIs.
+</p>
+
+<p class="caution"><b>Caution:</b> Do not use the existing <a href="{@docRoot}reference/android/location/package-summary.html">Location</a>
+APIs in the Android framework. The best practice for retrieving location updates is through the
+Google Play services API as outlined in this article.</p>
+
+<p>To connect to Google Play services, configure your app to create an instance of
+<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html">
+<code>GoogleApiClient</code></a>:</p>
+
+<ol>
+  <li>Create an activity that specifies an implementation for the interfaces <a
+href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html"
+>{@code ConnectionCallbacks}</a>, <a href="{@docRoot}reference/com/google/android/gms/common/api/
+GoogleApiClient.OnConnectionFailedListener.html">{@code OnConnectionFailedListener}</a>, and <a
+href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">{@code
+LocationListener}</a>.</li>
+  <li>In your activity's {@link android.app.Activity#onCreate onCreate()} method, create an instance
+of <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html"><code>
+GoogleApiClient</code></a> and add the Location service.
+  </li>
+  <li>To gracefully manage the lifecycle of the connection, call  <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#connect()">
+  {@code connect()}</a> in the {@link android.app.Activity#onResume onResume()} method and
+  <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#disconnect()">
+  {@code disconnect()}</a> in the {@link android.app.Activity#onPause onPause()} method.
+  </li>
+</ol>
+
+<p>The following code example shows an implementation of an activity that implements the
+<a href="{@docRoot}reference/com/google/android/gms/location/LocationListener.html">
+{@code LocationListener}</a> interface:</p>
+
+<pre>
+public class WearableMainActivity extends Activity implements
+    GoogleApiClient.ConnectionCallbacks,
+    GoogleApiClient.OnConnectionFailedListener,
+    LocationListener {
+
+    private GoogleApiClient mGoogleApiClient;
+    ...
+
+    &#64;Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        ...
+        mGoogleApiClient = new GoogleApiClient.Builder(this)
+                .addApi(LocationServices.API)
+                .addApi(Wearable.API)  // used for data layer API
+                .addConnectionCallbacks(this)
+                .addOnConnectionFailedListener(this)
+                .build();
+    }
+
+    &#64;Override
+    protected void onResume() {
+        super.onResume();
+        mGoogleApiClient.connect();
+        ...
+    }
+
+    &#64;Override
+    protected void onPause() {
+        super.onPause();
+        ...
+        mGoogleApiClient.disconnect();
+    }
+}
+</pre>
+
+<p>For more information on connecting to Google Play services, see <a href="{@docRoot}google/auth
+/api-client.html">Accessing Google APIs</a>.</p>
+
+<h2 id="Request">Request Location Updates</h2>
+
+<p>After your app has connected to the Google Play services API, it is ready to start receiving
+location updates. When the system invokes the
+<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)">
+<code>onConnected()</code></a> callback for your client, you build the location data request as
+follows:</p>
+
+<ol>
+  <li>Create a <a
+href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html"
+>{@code LocationRequest}</a> object and set any options using methods like <a
+href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#setPriority(int)"
+>{@code setPriority()}</a>.
+  </li>
+  <li>Request location updates using <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#requestLocationUpdates(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.location.LocationRequest, com.google.android.gms.location.LocationListener)">
+  <code>requestLocationUpdates()</code></a>.
+  </li>
+  <li>Remove location updates using <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#removeLocationUpdates(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.location.LocationListener)">
+  <code>removeLocationUpdates()</code></a> in the {@link android.app.Activity#onPause
+  onPause()} method.
+  </li>
+</ol>
+
+<p>The following example shows how to retrieve and remove location updates:</p>
+
+<pre>
+&#64;Override
+public void onConnected(Bundle bundle) {
+    LocationRequest locationRequest = LocationRequest.create()
+            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
+            .setInterval(UPDATE_INTERVAL_MS)
+            .setFastestInterval(FASTEST_INTERVAL_MS);
+
+    LocationServices.FusedLocationApi
+            .requestLocationUpdates(mGoogleApiClient, locationRequest, this)
+            .setResultCallback(new ResultCallback<Status>() {
+
+                &#64;Override
+                public void onResult(Status status) {
+                    if (status.getStatus().isSuccess()) {
+                        if (Log.isLoggable(TAG, Log.DEBUG)) {
+                            Log.d(TAG, "Successfully requested location updates");
+                        }
+                    } else {
+                        Log.e(TAG,
+                                "Failed in requesting location updates, "
+                                        + "status code: "
+                                        + status.getStatusCode()
+                                        + ", message: "
+                                        + status.getStatusMessage());
+                    }
+                }
+            });
+}
+
+&#64;Override
+protected void onPause() {
+    super.onPause();
+    if (mGoogleApiClient.isConnected()) {
+        LocationServices.FusedLocationApi
+             .removeLocationUpdates(mGoogleApiClient, this);
+    }
+    mGoogleApiClient.disconnect();
+}
+
+&#64;Override
+public void onConnectionSuspended(int i) {
+    if (Log.isLoggable(TAG, Log.DEBUG)) {
+        Log.d(TAG, "connection to location client suspended");
+    }
+}
+
+</pre>
+
+<p>Now that you have enabled location updates, the system calls the {@link android.location.LocationListener#onLocationChanged
+onLocationChanged()} method with the updated location at the interval specified in <a
+href="{@docRoot}reference/com/google/android/gms/location/LocationRequest.html#setInterval(long)">
+{@code setInterval()}</a>
+</p>
+
+<h2 id="DetectGPS">Detect On-Board GPS</h2>
+
+<p>Not all wearables have a GPS sensor. If your user goes out for a run and leaves their phone at
+home, your wearable app cannot receive location data through a tethered connection. If the
+wearable device does not have a sensor, you should detect this situation and warn the user that
+location functionality is not available.
+
+<p>To determine whether your Android Wear device has a built-in GPS sensor, use the
+{@link android.content.pm.PackageManager#hasSystemFeature hasSystemFeature()}
+method. The following code detects whether the device has built-in GPS when you start an activity:
+</p>
+
+<pre>
+
+protected void onCreate(Bundle savedInstanceState) {
+    super.onCreate(savedInstanceState);
+
+    setContentView(R.layout.main_activity);
+    if (!hasGps()) {
+        Log.d(TAG, "This hardware doesn't have GPS.");
+        // Fall back to functionality that does not use location or
+        // warn the user that location function is not available.
+    }
+
+    ...
+}
+
+private boolean hasGps() {
+    return getPackageManager().hasSystemFeature(PackageManager.FEATURE_LOCATION_GPS);
+}
+</pre>
+
+<h2 id="Disconnection">Handle Disconnection Events</h2>
+
+<p>Wearable devices relying on a tethered connection for location data may lose their connections
+abruptly. If your wearable app expects a constant stream of data, you must handle the
+disconnection based upon where that data is interrupted or unavailable. On a wearable device with no
+onboard GPS sensor, loss of location data occurs when the device loses its tethered data connection.
+</p>
+
+<p>In cases where your app depends on a tethered data connection for location data and the wear
+device does not have a GPS sensor, you should detect the loss of that connection, warn the user, and
+gracefully degrade the functionality of your app.</p>
+
+<p>To detect the loss of a tethered data connection:</p>
+
+<ol>
+  <li>Extend a <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html">
+  <code>WearableListenerService</code></a> that lets you listen for important data layer events.
+  </li>
+  <li>Declare an intent filter in your Android manifest to notify the system about your
+  <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>
+  WearableListenerService</code></a>.
+  This filter allows the system to bind your service as needed.
+<pre>
+&lt;service android:name=".NodeListenerService"&gt;
+    &lt;intent-filter&gt;
+        &lt;action android:name="com.google.android.gms.wearable.BIND_LISTENER" /&gt;
+    &lt;/intent-filter&gt;
+&lt;/service>
+</pre>
+  </li>
+  <li>Implement the <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html#onPeerDisconnected(com.google.android.gms.wearable.Node)">
+  <code>onPeerDisconnected()</code></a> method and handle cases of whether or not the device has
+  built-in
+  GPS.
+<pre>
+public class NodeListenerService extends WearableListenerService {
+
+    private static final String TAG = "NodeListenerService";
+
+    &#64;Override
+    public void onPeerDisconnected(Node peer) {
+        Log.d(TAG, "You have been disconnected.");
+        if(!hasGPS()) {
+            // Notify user to bring tethered handset
+            // Fall back to functionality that does not use location
+        }
+    }
+    ...
+}
+</pre>
+  </li>
+</ol>
+
+For more information, read the <a href="{@docRoot}training/wearables/data-layer/events.html#Listen">
+Listen for Data Layer Events</a> guide.
+
+<h2 id="Notify">Handle Location Not Found</h2>
+
+<p>When the GPS signal is lost, you can still retrieve the last known location using
+<a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#getLastLocation(com.google.android.gms.common.api.GoogleApiClient)">
+<code>getLastLocation()</code></a>. This method can be helpful in situations where you are unable to
+get a GPS fix, or when your wearable doesn't have built-in GPS and loses its connection with the
+phone.</p>
+
+<p>The following code uses <a href="{@docRoot}reference/com/google/android/gms/location/FusedLocationProviderApi.html#getLastLocation(com.google.android.gms.common.api.GoogleApiClient)">
+<code>getLastLocation()</code></a> to retrieve the last known location if available:
+</p>
+
+<pre>
+Location location = LocationServices.FusedLocationApi
+                .getLastLocation(mGoogleApiClient);
+</pre>
+
+<h2 id="Synchronize">Synchronize Data</h2>
+
+<p>If your wearable app records data using the built-in GPS, you may want to synchronize
+the location data with the handset. With the {@link android.location.LocationListener}, you
+implement the {@link android.location.LocationListener#onLocationChanged onLocationChanged()}
+method to detect and record the location as it changes.
+
+<p>The following code for wearable apps detects when the location changes and uses the data layer
+API to store the data for later retrieval by your phone app:</p>
+
+<pre>
+&#64;Override
+public void onLocationChanged(Location location) {
+    ...
+    addLocationEntry(location.getLatitude(), location.getLongitude());
+
+}
+
+private void addLocationEntry(double latitude, double longitude) {
+    if (!mSaveGpsLocation || !mGoogleApiClient.isConnected()) {
+        return;
+    }
+
+    mCalendar.setTimeInMillis(System.currentTimeMillis());
+
+    // Set the path of the data map
+    String path = Constants.PATH + "/" + mCalendar.getTimeInMillis();
+    PutDataMapRequest putDataMapRequest = PutDataMapRequest.create(path);
+
+    // Set the location values in the data map
+    putDataMapRequest.getDataMap()
+            .putDouble(Constants.KEY_LATITUDE, latitude);
+    putDataMapRequest.getDataMap()
+            .putDouble(Constants.KEY_LONGITUDE, longitude);
+    putDataMapRequest.getDataMap()
+            .putLong(Constants.KEY_TIME, mCalendar.getTimeInMillis());
+
+    // Prepare the data map for the request
+    PutDataRequest request = putDataMapRequest.asPutDataRequest();
+
+    // Request the system to create the data item
+    Wearable.DataApi.putDataItem(mGoogleApiClient, request)
+            .setResultCallback(new ResultCallback<DataApi.DataItemResult>() {
+                &#64;Override
+                public void onResult(DataApi.DataItemResult dataItemResult) {
+                    if (!dataItemResult.getStatus().isSuccess()) {
+                        Log.e(TAG, "Failed to set the data, "
+                                + "status: " + dataItemResult.getStatus()
+                                .getStatusCode());
+                    }
+                }
+            });
+}
+</pre>
+
+<p>For more information on how to use the Data Layer API, see the <a href="{@docRoot}training/
+wearables/data-layer/index.html">Sending and Syncing Data</a>
+guide.</p>
diff --git a/docs/html/training/basics/firstapp/building-ui.jd b/docs/html/training/basics/firstapp/building-ui.jd
index 179b3ac..c082642 100644
--- a/docs/html/training/basics/firstapp/building-ui.jd
+++ b/docs/html/training/basics/firstapp/building-ui.jd
@@ -1,12 +1,8 @@
 page.title=Building a Simple User Interface
-parent.title=Building Your First App
-parent.link=index.html
-
 trainingnavtop=true
-previous.title=Running Your App
-previous.link=running-app.html
-next.title=Starting Another Activity
-next.link=starting-activity.html
+
+page.tags=ui, views, layouts, widgets, string resources
+helpoutsWidget=true
 
 @jd:body
 
diff --git a/docs/html/training/basics/firstapp/creating-project.jd b/docs/html/training/basics/firstapp/creating-project.jd
index c4cb362..418eb68 100644
--- a/docs/html/training/basics/firstapp/creating-project.jd
+++ b/docs/html/training/basics/firstapp/creating-project.jd
@@ -1,6 +1,7 @@
 page.title=Creating an Android Project
-parent.title=Building Your First App
-parent.link=index.html
+
+page.tags=eclipse adt, sdk tools, project setup
+helpoutsWidget=true
 
 trainingnavtop=true
 next.title=Running Your App
diff --git a/docs/html/training/basics/firstapp/index.jd b/docs/html/training/basics/firstapp/index.jd
index 1b49096..ac8e64a 100644
--- a/docs/html/training/basics/firstapp/index.jd
+++ b/docs/html/training/basics/firstapp/index.jd
@@ -3,8 +3,9 @@
 
 trainingnavtop=true
 startpage=true
-next.title=Creating an Android Project
-next.link=creating-project.html
+
+page.tags=sdk tools
+helpoutsWidget=true
 
 @jd:body
 
@@ -47,6 +48,3 @@
 <p>This class uses a tutorial format that incrementally builds a small Android app that teaches
 you some fundamental concepts about Android development, so it's important that you follow each
 step.</p>
-
-<p><strong><a href="creating-project.html">Start the first lesson &rsaquo;</a></strong></p>
-
diff --git a/docs/html/training/basics/firstapp/running-app.jd b/docs/html/training/basics/firstapp/running-app.jd
index 23cedba..96b7172 100644
--- a/docs/html/training/basics/firstapp/running-app.jd
+++ b/docs/html/training/basics/firstapp/running-app.jd
@@ -3,10 +3,9 @@
 parent.link=index.html
 
 trainingnavtop=true
-previous.title=Creating a Project
-previous.link=creating-project.html
-next.title=Building a Simple User Interface
-next.link=building-ui.html
+
+page.tags=emulator
+helpoutsWidget=true
 
 @jd:body
 
diff --git a/docs/html/training/basics/firstapp/starting-activity.jd b/docs/html/training/basics/firstapp/starting-activity.jd
index 27d2c10..f9dcba4 100644
--- a/docs/html/training/basics/firstapp/starting-activity.jd
+++ b/docs/html/training/basics/firstapp/starting-activity.jd
@@ -3,8 +3,9 @@
 parent.link=index.html
 
 trainingnavtop=true
-previous.title=Building a Simpler User Interface
-previous.link=building-ui.html
+
+page.tags=input events, intents, activity lifecycle
+helpoutsWidget=true
 
 @jd:body
 
diff --git a/docs/html/training/building-wearables.jd b/docs/html/training/building-wearables.jd
index 0745c93..d751a81 100644
--- a/docs/html/training/building-wearables.jd
+++ b/docs/html/training/building-wearables.jd
@@ -1,6 +1,6 @@
 page.title=Building Apps for Wearables
 page.trainingcourse=true
-page.image=wear/images/notifications.png
+page.image=wear/images/02_create.png
 page.metaDescription=Learn how to build notifications, send and sync data, and use voice actions.
 
 @jd:body
diff --git a/docs/html/training/material/compatibility.jd b/docs/html/training/material/compatibility.jd
index 5e03450..49ef7f7 100644
--- a/docs/html/training/material/compatibility.jd
+++ b/docs/html/training/material/compatibility.jd
@@ -131,9 +131,9 @@
 
 <pre>
 dependencies {
-    compile 'com.android.support:appcompat-v7:+'
-    compile 'com.android.support:cardview-v7:+'
-    compile 'com.android.support:recyclerview-v7:+'
+    compile 'com.android.support:appcompat-v7:21.0.+'
+    compile 'com.android.support:cardview-v7:21.0.+'
+    compile 'com.android.support:recyclerview-v7:21.0.+'
 }
 </pre>
 
diff --git a/docs/html/training/material/drawables.jd b/docs/html/training/material/drawables.jd
index 8d7f453..fd21e3d 100644
--- a/docs/html/training/material/drawables.jd
+++ b/docs/html/training/material/drawables.jd
@@ -73,7 +73,7 @@
 <pre>
 dependencies {
     ...
-    compile 'com.android.support:palette-v7:+'
+    compile 'com.android.support:palette-v7:21.0.+'
 }
 </pre>
 
diff --git a/docs/html/training/material/lists-cards.jd b/docs/html/training/material/lists-cards.jd
index eb45f0d..e7bdfe0 100644
--- a/docs/html/training/material/lists-cards.jd
+++ b/docs/html/training/material/lists-cards.jd
@@ -260,7 +260,7 @@
 <pre>
 dependencies {
     ...
-    compile 'com.android.support:cardview-v7:+'
-    compile 'com.android.support:recyclerview-v7:+'
+    compile 'com.android.support:cardview-v7:21.0.+'
+    compile 'com.android.support:recyclerview-v7:21.0.+'
 }
 </pre>
diff --git a/docs/html/training/search/index.jd b/docs/html/training/search/index.jd
index 612e8e8..66874bb 100644
--- a/docs/html/training/search/index.jd
+++ b/docs/html/training/search/index.jd
@@ -49,5 +49,5 @@
 
     <dt><b><a href="backward-compat.html">Remaining Backward Compatible</a></b></dt>
 
-    <dd>Learn how to keep search features backward compatible with older devices by using.</dd>
+    <dd>Learn how to keep search features backward compatible with older devices.</dd>
   </dl>
diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs
index 0fee771..9f06666 100644
--- a/docs/html/training/training_toc.cs
+++ b/docs/html/training/training_toc.cs
@@ -834,6 +834,12 @@
           </li>
         </ul>
       </li>
+      <li>
+        <a href="<?cs var:toroot ?>training/articles/wear-location-detection.html"
+           description=
+           "How to detect location data on Android Wear devices."
+          >Detecting Location</a>
+      </li>
     </ul>
   </li>
   <!-- End Building for wearables -->
diff --git a/docs/html/training/tv/games/index.jd b/docs/html/training/tv/games/index.jd
index 29b055b..2f510a9 100644
--- a/docs/html/training/tv/games/index.jd
+++ b/docs/html/training/tv/games/index.jd
@@ -31,7 +31,7 @@
 </p>
 
 
-<h3 id="shared-display">Shared display</h3>
+<h3 id="shared-display">Consider the shared display</h3>
 
 <p>
   A living-room TV poses design challenges for multiplayer games, in that all players can see
@@ -57,7 +57,7 @@
 </ul>
 
 
-<h3 id="landscape-display">Landscape display</h3>
+<h3 id="landscape-display">Support landscape display</h3>
 
 <p>
   A TV is always sideways: You can’t turn it, and there is no portrait orientation. Always design
@@ -69,19 +69,19 @@
 
 <p>
   TVs don't have touch interfaces, so it's even more important to get your controls right and make
-  sure 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'
+  sure players find them intuitive and fun to use. Handling controllers
+  also introduces some other issues to pay attention to, like keeping track of multiple
   controllers, and handling disconnects gracefully.
 </p>
 
-<h3 id="d-pad">D-pad</h3>
+<h3 id="d-pad">Support D-pad controls</h3>
 
 <p>
   Plan your control scheme around a directional pad (D-pad) control, since this control set is the
   default for Android TV devices. The player needs to be able to use a D-Pad in all aspects of the
-  game–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 should not tell a player to <strong>Tap here to skip</strong>.
+  game&mdash;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 should not tell a player to "<em>Tap</em> here to continue."
 </p>
 
 <p>
@@ -91,35 +91,35 @@
 
 <ul>
   <li>
-    <strong>Communicate Controller Requirements up Front</strong> - Use your Play Store description
+    <strong>Communicate Controller Requirements up Front</strong>. Use your Google Play 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, make this fact clear. A player who uses
-    an ill-suited controller for a game is likely to have a subpar experience–and penalize your
+    an ill-suited controller for a game is likely to have a subpar experience and penalize your
     game in the ratings.
   </li>
   <li>
-    <strong>Use Consistent Button Mapping</strong> - Intuitive and flexible button mapping is key
-    to a good user experience. 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=
+    <strong>Use Consistent Button Mapping</strong>. Intuitive and flexible button mapping is key
+    to a good user experience. For example, you should adhere to accepted customs by using the A button
+    to <em>Accept</em>, and the B button to <em>Cancel</em>. You can also offer flexibility
+    in the form of remappability. For more information about button mapping, see <a href=
     "http://developer.android.com/training/game-controllers/controller-input.html">Handling
     Controller Actions</a>.
   </li>
   <li>
-    <strong>Detect Controller Capabilities and Adjust Accordingly</strong> - Query the controller
+    <strong>Detect Controller Capabilities and Adjust Accordingly</strong>. Query the controller
     about its capabilities in order to optimize the match between controller and game. 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.
-    When, however, your game queries the controller and discovers that motion detection is not
-    supported, it can switch over to an alternative, available control scheme. For more information
-    on querying controller capabilities, see <a href=
+    So, your game should query the controller and if motion detection is not
+    supported, switch over to an alternative, available control scheme. For more information
+    about querying controller capabilities, see <a href=
     "http://developer.android.com/training/game-controllers/compatibility.html">Supporting
     Controllers Across Android Versions</a>.
   </li>
 </ul>
 
 
-<h3 id="back-button">Back-button behavior</h3>
+<h3 id="back-button">Provide appropriate 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
@@ -139,18 +139,18 @@
 </p>
 
 
-<h3 id="multiple-controllers">Handling multiple controllers</h3>
+<h3 id="multiple-controllers">Handle 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
+  map each player-controller pair. For information about how to implement controller-number
   identification, see <a href=
   "http://developer.android.com/reference/android/view/InputDevice.html#getControllerNumber">Input
   Devices</a>.
 </p>
 
 
-<h3 id="handle-disconnect">Handling disconnects</h3>
+<h3 id="handle-disconnect">Handle controller disconnects</h3>
 
 <p>
   When a controller is disconnected in the middle of gameplay, the game should pause, and a dialog
@@ -159,7 +159,7 @@
 
 <p>
   The dialog should also offer troubleshooting tips (for example, a pop-up dialog telling the
-  player to "Check your Bluetooth connection"). For more information on implementing input-device
+  player to "Check your Bluetooth connection"). For more information about implementing input-device
   support, see <a href=
   "http://developer.android.com/training/game-controllers/controller-input.html">Handling Controller
   Actions</a>. Specific information about Bluetooth connections is at <a href=
@@ -167,25 +167,53 @@
 </p>
 
 
+<h3 id="ControllerHelp">Show controller instructions</h3>
+
+<p>If your game provides visual game control instructions, the
+controller image should be free of branding and include only <a
+href="{@docRoot}training/game-controllers/controller-input.html#button"
+>buttons compatible with Android</a>.</p>
+
+<p>For sample images of an Android-compatible controller, download the
+<a href="http://storage.googleapis.com/androiddevelopers/design/android_tv_gamepad_template-2014-10.zip"
+>Android TV Gamepad Template (ZIP)</a>.
+It includes a white controller on black background and a black controller on white background
+(shown in figure 1), as a PNG file and an Adobe&reg; Illustrator&reg; file.</p>
+
+<img src="{@docRoot}images/games/game-controller-buttons_2x.png" width="700"
+     srcset="{@docRoot}images/games/game-controller-buttons_2x.png 2x,
+             {@docRoot}images/games/game-controller-buttons.png 1x" />
+<p class="img-caption"><b>Figure 1.</b> Example controller instructions using the
+<a href="http://storage.googleapis.com/androiddevelopers/design/android_tv_gamepad_template-2014-10.zip"
+>Android TV Gamepad Template (ZIP)</a>.
+
+
+
+
 <h2 id="manifest">Manifest</h2>
 
+<p>There are a some special things games should include in the Android manifest.</p>
+
+<h3 id="Launcher">Show your game in the launcher</h3>
 <p>
-  The Android TV launcher home screen displays games in a separate row from regular apps. The TV
-  framework uses the <code>android:isGame</code> manifest attribute to differentiate games from
-  non-game apps. Set this value to <code>true</code> in your game's app manifest, as shown in the
-  following code example:
+  The Android TV launcher home screen displays games in a separate row from regular apps.
+  To make your game appear in the list of games, add the
+  <a href="{@docRoot}guide/topics/manifest/meta-data-element.html"
+  ><code>&lt;meta-data></code></a> tag in your app manifest with <code>android:name</code>
+  set to <code>"isGame"</code> and <code>android:value</code>
+  set to <code>"true"</code>. For example:
 </p>
 
 <pre class="fragment">
 &lt;application&gt;
   ...
-  &lt; meta-data android:name="isGame" android:value="true" &gt;
+  &lt;meta-data android:name="isGame" android:value="true" &gt;
   ...
 &lt;/application&gt;
 </pre>
 
 
-<h3 id="gamepad">Game Controllers</h3>
+<h3 id="gamepad">Declare support for game controllers</h3>
 
 <p>
   Games controllers may not be available or active for users of a TV device. In order to properly
@@ -215,7 +243,9 @@
 <h2 id="gpgs">Google Play Game Services</h2>
 
 <p>
-  If your game integrates Google Play Game Services, you should keep in mind a number of
+  If your game integrates <a
+  href="https://developers.google.com/games/services/">Google Play Game services</a>,
+  you should keep in mind a number of
   considerations pertaining to achievements, sign-in, saving games, and multiplayer play.
 </p>
 
@@ -224,7 +254,7 @@
 
 <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. For more information on
+  from a supported input device should be able to earn achievements. For more information about
   achievements and how to implement them, see <a href=
   "https://developers.google.com/games/services/android/achievements">Achievements in Android</a>.
 </p>
@@ -262,7 +292,7 @@
 
 <p>
   A game offering a multiplayer experience must allow at least two players to enter a room. For
-  further information on multiplayer games in Android, see the <a href=
+  further information about multiplayer games in Android, see the <a href=
   "https://developers.google.com/games/services/android/realtimeMultiplayer">Real-time
   Multiplayer</a> and <a href="">Turn-based Multiplayer</a> documentation on the Android developer
   site.
diff --git a/docs/html/training/wearables/apps/index.jd b/docs/html/training/wearables/apps/index.jd
index 7d961b7..256205b 100644
--- a/docs/html/training/wearables/apps/index.jd
+++ b/docs/html/training/wearables/apps/index.jd
@@ -1,5 +1,6 @@
 page.title=Creating Wearable Apps
-page.image=wear/images/notifications.png
+page.tags="wear","wearable","app"
+page.image=wear/images/01_create.png
 
 @jd:body
 
diff --git a/docs/html/training/wearables/notifications/index.jd b/docs/html/training/wearables/notifications/index.jd
index 17f3cb3..a7b6733 100644
--- a/docs/html/training/wearables/notifications/index.jd
+++ b/docs/html/training/wearables/notifications/index.jd
@@ -1,4 +1,6 @@
 page.title=Adding Wearable Features to Notifications
+page.tags="wear","notifications","wearables"
+page.image=wear/images/01_notifications.png
 @jd:body
 
 <div id="tb-wrapper">
diff --git a/docs/html/training/wearables/notifications/stacks.jd b/docs/html/training/wearables/notifications/stacks.jd
index e71e74c..9a528a4 100644
--- a/docs/html/training/wearables/notifications/stacks.jd
+++ b/docs/html/training/wearables/notifications/stacks.jd
@@ -45,7 +45,7 @@
 Notification notif = new NotificationCompat.Builder(mContext)
          .setContentTitle("New mail from " + sender1)
          .setContentText(subject1)
-         .setSmallIcon(R.drawable.new_mail);
+         .setSmallIcon(R.drawable.new_mail)
          .setGroup(GROUP_KEY_EMAILS)
          .build();
 
@@ -65,7 +65,7 @@
 Notification notif2 = new NotificationCompat.Builder(mContext)
          .setContentTitle("New mail from " + sender2)
          .setContentText(subject2)
-         .setSmallIcon(R.drawable.new_mail);
+         .setSmallIcon(R.drawable.new_mail)
          .setGroup(GROUP_KEY_EMAILS)
          .build();
 
diff --git a/docs/html/training/wearables/ui/index.jd b/docs/html/training/wearables/ui/index.jd
index 8ef6fe7..5d97490 100644
--- a/docs/html/training/wearables/ui/index.jd
+++ b/docs/html/training/wearables/ui/index.jd
@@ -1,4 +1,5 @@
 page.title=Creating Custom UIs for Wear Devices
+page.image=wear/images/10_uilib.png
 
 @jd:body
 
diff --git a/docs/html/wear/images/01_create.png b/docs/html/wear/images/01_create.png
new file mode 100644
index 0000000..5a39dde
--- /dev/null
+++ b/docs/html/wear/images/01_create.png
Binary files differ
diff --git a/docs/html/wear/images/02_create.png b/docs/html/wear/images/02_create.png
new file mode 100644
index 0000000..e722df1
--- /dev/null
+++ b/docs/html/wear/images/02_create.png
Binary files differ
diff --git a/docs/html/wear/images/10_uilib.png b/docs/html/wear/images/10_uilib.png
new file mode 100644
index 0000000..de7be57
--- /dev/null
+++ b/docs/html/wear/images/10_uilib.png
Binary files differ
diff --git a/docs/image_sources/distribute/gp-wear-quality.svg b/docs/image_sources/distribute/gp-wear-quality.svg
new file mode 100644
index 0000000..2acf81a
--- /dev/null
+++ b/docs/image_sources/distribute/gp-wear-quality.svg
@@ -0,0 +1,2268 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   version="1.1"
+   width="2824.887"
+   height="1419.8136"
+   id="svg3004"
+   xml:space="preserve"
+   inkscape:version="0.48.1 "
+   sodipodi:docname="wear_app_quality.svg"><sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1280"
+     inkscape:window-height="1002"
+     id="namedview125"
+     showgrid="false"
+     inkscape:zoom="0.23675905"
+     inkscape:cx="1735.4152"
+     inkscape:cy="-51.97425"
+     inkscape:window-x="1272"
+     inkscape:window-y="-8"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="layer8"
+     showguides="true"
+     inkscape:guide-bbox="true"
+     fit-margin-top="50"
+     fit-margin-left="200"
+     fit-margin-right="200"
+     fit-margin-bottom="200"><sodipodi:guide
+       orientation="0,1"
+       position="1543.7834,1150.3523"
+       id="guide3963" /><sodipodi:guide
+       orientation="0,1"
+       position="1978.6428,757.82274"
+       id="guide9681" /></sodipodi:namedview><metadata
+     id="metadata3010"><rdf:RDF><cc:Work
+         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
+     id="defs3008"><clipPath
+       id="clipPath3020"><path
+         d="m 0,1080 1920,0 L 1920,0 0,0 0,1080 z"
+         id="path3022"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3044"><path
+         d="m 391.754,758.654 452.495,0 0,-452.496 -452.495,0 0,452.496 z"
+         id="path3046"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3060"><path
+         d="m 362.683,787.727 510.637,0 0,-510.638 -510.637,0 0,510.638 z"
+         id="path3062"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3086"><path
+         d="m 1058,722 374,0 0,-374 -374,0 0,374 z"
+         id="path3088"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3100"><path
+         d="m 1029,344 432,0 0,-32 -432,0 0,32 z"
+         id="path3102"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3116"><path
+         d="m 1029,756 432,0 0,-32 -432,0 0,32 z"
+         id="path3118"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3060-8"><path
+         d="m 362.683,787.727 510.637,0 0,-510.638 -510.637,0 0,510.638 z"
+         id="path3062-8"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3044-8"><path
+         d="m 391.754,758.654 452.495,0 0,-452.496 -452.495,0 0,452.496 z"
+         id="path3046-8"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3116-3"><path
+         d="m 1029,756 432,0 0,-32 -432,0 0,32 z"
+         id="path3118-0"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3100-0"><path
+         d="m 1029,344 432,0 0,-32 -432,0 0,32 z"
+         id="path3102-0"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3086-0"><path
+         d="m 1058,722 374,0 0,-374 -374,0 0,374 z"
+         id="path3088-4"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3086-0-0"><path
+         d="m 1058,722 374,0 0,-374 -374,0 0,374 z"
+         id="path3088-4-2"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3100-0-7"><path
+         d="m 1029,344 432,0 0,-32 -432,0 0,32 z"
+         id="path3102-0-2"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3116-3-2"><path
+         d="m 1029,756 432,0 0,-32 -432,0 0,32 z"
+         id="path3118-0-6"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3060-8-2"><path
+         d="m 362.683,787.727 510.637,0 0,-510.638 -510.637,0 0,510.638 z"
+         id="path3062-8-4"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3044-8-3"><path
+         d="m 391.754,758.654 452.495,0 0,-452.496 -452.495,0 0,452.496 z"
+         id="path3046-8-8"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3086-4"><path
+         inkscape:connector-curvature="0"
+         d="m 1058,722 374,0 0,-374 -374,0 0,374 z"
+         id="path3088-8" /></clipPath><clipPath
+       id="clipPath3100-8"><path
+         inkscape:connector-curvature="0"
+         d="m 1029,344 432,0 0,-32 -432,0 0,32 z"
+         id="path3102-2" /></clipPath><clipPath
+       id="clipPath3116-4"><path
+         inkscape:connector-curvature="0"
+         d="m 1029,756 432,0 0,-32 -432,0 0,32 z"
+         id="path3118-5" /></clipPath><clipPath
+       id="clipPath3044-8-1"><path
+         inkscape:connector-curvature="0"
+         d="m 391.754,758.654 452.495,0 0,-452.496 -452.495,0 0,452.496 z"
+         id="path3046-8-5" /></clipPath><clipPath
+       id="clipPath3060-8-27"><path
+         inkscape:connector-curvature="0"
+         d="m 362.683,787.727 510.637,0 0,-510.638 -510.637,0 0,510.638 z"
+         id="path3062-8-6" /></clipPath><clipPath
+       id="clipPath3086-0-0-4"><path
+         inkscape:connector-curvature="0"
+         d="m 1058,722 374,0 0,-374 -374,0 0,374 z"
+         id="path3088-4-2-1" /></clipPath><clipPath
+       id="clipPath3100-0-7-1"><path
+         inkscape:connector-curvature="0"
+         d="m 1029,344 432,0 0,-32 -432,0 0,32 z"
+         id="path3102-0-2-5" /></clipPath><clipPath
+       id="clipPath3116-3-2-9"><path
+         inkscape:connector-curvature="0"
+         d="m 1029,756 432,0 0,-32 -432,0 0,32 z"
+         id="path3118-0-6-5" /></clipPath><clipPath
+       id="clipPath3044-8-3-2"><path
+         inkscape:connector-curvature="0"
+         d="m 391.754,758.654 452.495,0 0,-452.496 -452.495,0 0,452.496 z"
+         id="path3046-8-8-2" /></clipPath><clipPath
+       id="clipPath3060-8-2-1"><path
+         inkscape:connector-curvature="0"
+         d="m 362.683,787.727 510.637,0 0,-510.638 -510.637,0 0,510.638 z"
+         id="path3062-8-4-5" /></clipPath><clipPath
+       id="clipPath3942"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3944"
+         d="m 1337.7,554.569 67.31,0 0,-64.569 -67.31,0 0,64.569 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3912"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3914"
+         d="m 1404.777,549.002 12,0 0,11.998 -12,0 0,-11.998 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3908"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3910"
+         d="m 1404.78,561 12,0 0,-12 -12,0 0,12 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3886"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3888"
+         d="m 1363,547.865 32,0 0,12 -32,0 0,-12 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3882"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3884"
+         d="m 1363,559.865 32,0 0,-12.002 -32,0 0,12.002 z"
+         inkscape:connector-curvature="0" /></clipPath><mask
+       id="mask3852"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3854"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHEAAABECAAAAACTooUSAAAAAXNCSVQI5gpbmQAAAXhJREFUWIXt2T9v3DAMBfBHWj4Fzh2CXjsEaZd+/+8VZGiN+v4Y1cni6+ADmqUjnQ7kqEE/ULQXPgEAQLBB8S8lAnE3SZCrKFBVVd8+CTMzA5EAaOr7PrmShC211sWABNGUh8fHnNRTtKVcrzMWY4JoPxw/Hw+585sl2cp5/AkzMgm033/59nIcevUCAavz+Cq3Upvce3z5/nzY+T0r7XZ+w/zrpMJ1jvvj89enB0/x94Rpn5PK/VvNw+HpU+78xFZwGnJSAAkQ0a7f5fzgKSLv+k5FgAQAoqJd1zmK6DqVdWppPZK1vES8u93xj/hHhRhiiCGGGGKIIYYYYoghhhhiiCGGGOL/Jt73ciRJuinvr08AQKO11vzCALbWjMa7SFqrt1LgutEtt9qMXHu0pcznCc5b6/NcFgOQQFvKZXzDyXszP17KYkQCrc7jKyb/9GGcqxGJYvXyg9ctEpZLNXDtEWXaJEWqRgggWyZl/IA08EMST2DTVPcPY4fdi0eNNAgAAAAASUVORK5CYII="
+         height="1"
+         width="1" /></mask><mask
+       id="mask3840"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><g
+         id="g3842"><g
+           id="g3844"
+           clip-path="url(#clipPath3836)"><g
+             id="g3846"><g
+               id="g3848"
+               transform="matrix(113,0,0,68,1351,505)"><image
+                 id="image3850"
+                 xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHEAAABECAYAAAC2ydrOAAAABHNCSVQICAgIfAhkiAAAA1NJREFUeJztnc1uozAURj8HjCMCikq7iNJu+v7vVXXRovJn1RDiWUztMQnttIuQmat7pKugAFn4yDZk8V0BwGIGIcTc18wVsXZWFQROJAohvMDwmLke1lovMDx2xO7AyVqtVmcVnmeWw8k6Ho9nFZ6Pw5tWqxXiOIaU0lccxyzyCoQCD4cDhmHwdTgcvEjgQ6IQwgtUSiFNU2w2G2w2GyilvEiWuBzWWi/QGIOu69B1HbTWAOBFWmunEqWUSNMURVHg9vYWRVEgz3MopRBFEe+RC+H2vXEcYYxB0zQoyxKvr68A/iyv7ro43AullMiyDHd3d3h4eMB+v0dRFEjTFFJKv6wyl+d4PGIYBmitUZYlnp6eIIRA3/cwxmAYBozjCCHE5zNxv9/j8fERu90OeZ4jSRJeUhfCLaV936NpGjw/PwMAtNZ4e3tDXdfexdly6vbELMtQFAV2ux3u7++x3W6xXq9Z4kI4ie/v76iqCgBQVRWyLJt9Rpl9OnUPN3meY7vd4ubmZrIvMpcl3A8BoK5rpGk6ERgyeU90MzKKIkgpkSQJlFJQSmG9XrPEhXASAUAphSRJIKVEFEV+BoYe4tMfcCJDoWGxxMvj3hHdmIc+5sb/TKLD2Z4r5vL8ZNz5nYEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEAn2a7uWji02Iuz0/H/kyiC0x1n+M4+gI4kX8JXFSmq9DHnMw4vDEUNwyDz5t24akclbkMYWitMQZ93/vM7zDA3TGZiWGEv9YaTdP4+GKOj16O0/jopmmgtYYx5qwnBvAh8bQHQ9u2KMvSB4jXdc1B7gsyF+ReliXatp2InHSocTedRvgDvwPEuaXC8sz5KMsSWmsMwzCVaK2FEMLf1LYtXl5eYK1F13Xc3OQKfNXcpG1bL9FdOzsTAcAYg6qquM3QlfiqzdDpTPSt98LeGNzw6/p8p+HXrESAW+/9S3y39R43wfwP+FsTzDOJ/gTL++f47K+3XyWNnXDxB1SBAAAAAElFTkSuQmCC"
+                 transform="matrix(1,0,0,-1,0,1)"
+                 height="1"
+                 width="1" /></g></g></g></g></mask><clipPath
+       id="clipPath3836"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3838"
+         d="m 1351,573 113,0 0,-68 -113,0 0,68 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3832"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3834"
+         d="m 1351,573 113,0 0,-68 -113,0 0,68 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3824"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3826"
+         d="m 0,1080 1920,0 L 1920,0 0,0 0,1080 z"
+         inkscape:connector-curvature="0" /></clipPath><mask
+       id="mask3798"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3800"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHEAAABECAAAAACTooUSAAAAAXNCSVQI5gpbmQAAAZ9JREFUWIXt2U9v1DAQBfA348lmyXa1FdBSgRDf/4tVe4CI7J+oXtvzOKQIOCOnF8/Ft/lpZCeHeQIAgGCF4h9KBFLdJEEuokBVVevOSbi7OwiDiIZN14WqJOE5pZQdMEBtO+yGPmhN0XO8Xmdkp4mEfv/+w/2u13p3SZZ4Hn/AnTRo2B6evjwd3lnFGT3N47PcYipiIrY9PH77+nHotBpIv52PmH+eVGiQsBnuHz5/2m1qii8TprveVJa3av2wP9xt6j0dlojT0JsCMJAk1LptVRH9pgsqAhjoJedC0YqfBxGCytLfCJZcsgM1/3Qi8ru7gnQv7mQ17t9SgEutBEIBYEXvVVy1mtjEJjaxiU1sYhOb2MQmNrGJTWxiE5v4P2XLUXlt9Xd7AwA6vZRSLwxgKcXpfBVJL+kWI0LNjW68peLkMqPnOJ8nbCvuV/1lOs8xO5aNbo6X8YhTzR2y387H8RKzEwZ6msdnTDWzgCV9GOfkhFE8Xb7zuu9D9YTlkhxcZkScelshRUpOCCBqXdfZOkkZ3yANfJPEE1g11f0FocoCRBRb0tkAAAAASUVORK5CYII="
+         height="1"
+         width="1" /></mask><mask
+       id="mask3786"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><g
+         id="g3788"><g
+           id="g3790"
+           clip-path="url(#clipPath3782)"><g
+             id="g3792"><g
+               id="g3794"
+               transform="matrix(113,0,0,68,1351,444)"><image
+                 id="image3796"
+                 xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHEAAABECAYAAAC2ydrOAAAABHNCSVQICAgIfAhkiAAAA59JREFUeJztnclurDoURTdgmkAhSmlLiaL8/49FGSQodFZM5zd4sstUkdsMQnKPzpKsQgVMWDo2ZrCPB0BjBc/z1v5mvhGtV1XBw4lEz/OsQPeY+T601lage2wQ5sDI8n3/bLjnme0wsuZ5PhvueQEcK873fQRBgCiKEIYhwjBEEAQs8htwBY7jiGEY7BjH0YoEnEr0fR9CCCRJgjRNkWUZ0jRFHMdWJEvcDq21FaiUQtd16LoOUkoAsCK11hCmCoMgQBzHyPMcl5eXuLq6wn6/R5ZliOPYSmSRX49Z96ZpglIKTdOgLEu8vb0BOE6v5joBwE6jSZKgKAocDgc8PDzgcDigKApcXFxACMECN2SeZwzDACklyrLE8/MzPM9D3/dQSmEYBkzTBM/zjpVoptKiKHB7e4unpyc8Pj7i+voaaZoiDEO7NjJfi5lK+75H0zR4eXkBAEgp8f7+jrqu7cxoK9FMp1EUIU1T7Pd73Nzc4P7+Hnd3d8iyDFEUscSNMBI/Pj5QVRUAoKoq7HY7xHEMIcTiHeXs7VQIgTiOkaYp8jxHURTY7XZWIk+pX4+7HgJAXdf2JdMIdBHmJncAx7fVMAyRJAlL3BAjEQDiOLZbPneX4HqwEud5xjRNGMcR4zhimiZorRf7R5a4DaaQgiBYPPfPnr9wP+cYiebX3VAC/BluS8yzdsdn+MBxOjX7j2mazvYizM/FrpCn6+LpGsn8XM72DCzv34M3fgRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQQQn53gdKnv42+f/ZlEk/HmJi+aAXAi/xaYsEQzXB9rMoV7oytuGAabN23CU4MgYIkb4IbWKqXQ973N/F4LTVxUohvhL6VE0zQ2vjhJEs473YjT+OimaSClhFJqNcJ0EVprBLZti7IsbYB4XdecPLwha0HuZVmibduFyEWHGnPTaYQ/8H+AOKfxb8+aj7IsIaXEMAxLiSYi2tzUti1eX1+htUbXdcjz3Hap4eThbfhVc5O2ba1Ec+1qJQKAUgpVVa1G+DNfz6/aDJ1Wom2957ZUMM2+wjBcRPizxO34k4ZfqxIBbr33k/jT1nvcBPMf4HdNMM8k2hMs78fx2ae3/wBR6gt9OOvm0AAAAABJRU5ErkJggg=="
+                 transform="matrix(1,0,0,-1,0,1)"
+                 height="1"
+                 width="1" /></g></g></g></g></mask><clipPath
+       id="clipPath3782"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3784"
+         d="m 1351,512 113,0 0,-68 -113,0 0,68 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3778"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3780"
+         d="m 1351,512 113,0 0,-68 -113,0 0,68 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3770"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3772"
+         d="m 1341,490 129,0 0,89 -129,0 0,-89 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3748"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3750"
+         d="m 1214,628 270,0 0,-182 -270,0 0,182 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3726"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3728"
+         d="m 652.002,520.002 12,0 0,11.998 -12,0 0,-11.998 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3722"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3724"
+         d="m 652,532 12.002,0 0,-12 -12.002,0 0,12 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3700"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3702"
+         d="m 592,518.865 32,0 0,12 -32,0 0,-12 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3696"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3698"
+         d="m 592,530.865 32,0 0,-12.002 -32,0 0,12.002 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3688"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3690"
+         d="m 0,1080 1920,0 L 1920,0 0,0 0,1080 z"
+         inkscape:connector-curvature="0" /></clipPath><mask
+       id="mask3662"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3664"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIwAAABPCAAAAAAc13L4AAAAAXNCSVQI5gpbmQAAAdJJREFUaIHt2rFu2zAUheFDirICJUZQt0OQdun7v1fgwRHqylJMkbyng1S0He5aarj/C/gDLWnhcQAAONSNfxTOwdXkkCBXjIP33vtqp0OIiAiIAMCHtm1DLQ0hJaWlCBjgfOj6x8cu+EoYKXGe5nsuCHC+7U+fT8euqfLckBKnH+8DKQgOvn368u311Le+ggVg/rie27KkUraTef3+cjzU+Z8kzZcu3caP5NZn5un08vX5oRJmmQ73S39o3PY2df3x+VPXVHlmZAlz3wXvHALgnG/aQ9c9VML4GDxIrt8ZOO980zR1MM47lpyLbBjArVXAAIDkkgvBOq/zP5EiRYTEDjDgGnaBAUgCe8FsGUbLMFqG0TKMlmG0DKNlGC3DaBlGyzBahtEyjJZhtAyjZRgtw2gZRsswWobRMoyWYbQMo2UYLcNoGUZru0r+fWX5//v7lwMAUCillCprHpZShMINQ0pJS4yoc+NfYlxSEXI9GclxHq+osxKh3K/jHLMACKDkeBvO+FlnP0NZxvNwi1mIAEqahzdcay2LJM3D2zAnIQKdpNuFU73NVYnj8H5LAq4ng3ituEbLcZrmJIQDXPWdXk4p5Q2zmwXj3radwF5Wr78ATrQFVxEFtwQAAAAASUVORK5CYII="
+         height="1"
+         width="1" /></mask><mask
+       id="mask3650"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><g
+         id="g3652"><g
+           id="g3654"
+           clip-path="url(#clipPath3646)"><g
+             id="g3656"><g
+               id="g3658"
+               transform="matrix(139.35082,0,0,78.633677,558.31445,465.31115)"><image
+                 id="image3660"
+                 xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIwAAABPCAYAAAA5vC0kAAAABHNCSVQICAgIfAhkiAAABCJJREFUeJzt3UFvskwYheEDAmNQYkq7MLab/v//1bhQUgqMwjDMt3gzBJTmy7Ol50omNSLdcAcfcEEAwGFBEARLb9Mf4dxiFgjwEEwQBGMs09f0Nzjnxlimr73Iv/BhhGH4tKbbaZ18GMMwPK3p9mi6UxiGiKIIcRyPK4oiRrNy01istTDGwBiDrutgrZ1FEwH/QvCxKKWQpil2ux12ux2UUmM0DGadnHNjLG3bQmuNpmmgtcb9fkff97DWAsA8mDiOkaYp8jzH6+sr8jxHlmVQSmGz2XCmWSE/pwzDgLZt0TQNvr+/cb1eURTFbDsARNPZJY5j7Pd7vL294ePjA6fTCXmeI01TxHE8fjXRujjn0Pc9brcbyrLE+XxGHMew1qLrOhhjYK2Ftfb3M8zpdMLn5yeOxyOyLEOSJPxaWqlhGGCMgdYal8sFSikYY1DXNaqqwu12gzEGQRAszzD7/R55nuN4POL9/R2HwwHb7ZbBrNQwDOi6Dk3TIEkS3O93XC4XpGmKJEnGcQT45SrJD75ZluFwOODl5WU2x9B6+Pmk6zpEUQStNdI0fbrYeQrGvxmGITabDeI4RpIkUEpBKYXtdstgVsgHE4Yh2rad3UbxA+/0Bl70+A98NNN4povBrItzbnbMnXOw1qLv+/FyehiG34Px/BlnadF6DcMwhuL/Tn8q4HUyAZjfj/E38fzr6VcSg6HR48zyOL8ADIYWLIXiMRgSYTAkwmBIhMGQCIMhEQZDIgyGRBgMiTAYEmEwJMJgSITBkAiDIREGQyIMhkQYDIkwGBJhMCTCYEiEwZAIgyERBkMiDIZEGAyJMBgSYTAkwmBIhMGQCIMhEQZDIgyGRBgMiTAYEmEwJMJgSITBkAiDIREGQyIMhkQYDIkwGBJhMCTCYEiEwZAIgyERBkMiDIZEGAyJMBgSYTAkwmBI5NfHEP/fwyJpHaTH+SkY/yha/9daOy4AfG71yvgHm/s1PfZL4UTTHaeRGGPQdR3atkXbtgCAzWbDYFbGB+OPc9d1MMbM4pmGMzvD+Keit20LrTWqqkJZlgCA7XaLMAwZzMr4k8T9fkdZlqiqClprtG2Lvu8xDMPs89F0Jx9LXdcoigLn8xkA8PPzgyRJGMwK+WPfdR2qqsL5fEZRFKjrehaNP8vMgjHGQGuNoijw9fUFACjLEmmaIo5jhCEvqtZo6dgXRQGtNYwx82CccwiCYNyprmtcLhc459A0DbIsg1JqnF94hlkXP6P4OaaqKhRFgev1irqux2D8ZxfPMADQti3KsoRSClEU8etoxR5HkqZp0DTN4hkmAOCAf5fLYRgiiiLEcTwuH4v/DK2Pj8FHY4wZ1+MMMwsGAMIwfFrT7bRO02ge13T7GIw3nVM4s/w90/suS3d9n4IZNzCUP+23nwf+AzNnFIrywW/wAAAAAElFTkSuQmCC"
+                 transform="matrix(1,0,0,-1,0,1)"
+                 height="1"
+                 width="1" /></g></g></g></g></mask><clipPath
+       id="clipPath3646"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3648"
+         d="m 558.314,543.945 139.351,0 0,-78.634 -139.351,0 0,78.634 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3642"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3644"
+         d="m 558.314,543.945 139.351,0 0,-78.633 -139.351,0 0,78.633 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3634"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3636"
+         d="m 570.26,532 c 0,-30.785 24.955,-55.742 55.74,-55.742 l 0,0 c 30.784,0 55.74,24.957 55.74,55.742 l 0,0 c 0,30.784 -24.956,55.74 -55.74,55.74 l 0,0 c -30.785,0 -55.74,-24.956 -55.74,-55.74"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3610"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3612"
+         d="m 652.333,574.333 101,0 0,-79.333 -101,0 0,79.333 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3592"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3594"
+         d="m 730.778,549 12,0 0,-12 -12,0 0,12 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3570"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3572"
+         d="m 679,535.865 32,0 0,12 -32,0 0,-12 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3566"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3568"
+         d="m 679,547.865 32,0 0,-12.002 -32,0 0,12.002 z"
+         inkscape:connector-curvature="0" /></clipPath><mask
+       id="mask3540"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3542"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF0AAABECAAAAADGw2ZMAAAAAXNCSVQI5gpbmQAAAZJJREFUWIXt2DFv2zAQhuHvTlTkyDaMuBmCtEv//+9q0KKuAtWWZJnkfR0UAwY69jyVXAhoeEQcyOUVAAAEvos3rAjE0ydBfugCVVV1Oz9hZmYgEABoqOs6ePGE5Rgv2UAEiIamXa+boE665Xkch3PKQIBo3e4/7bdN5TJ70i7De6ckjUGg9eb5y+u+rdUBB5jO/Y/G4s3ZX7++bB98RmNp6lpOwzkal7lv9i+fdysvfVzb8XCoVWS5M0273T01lYvOtMJxt2kqBQIgolX90DQrLx1T+9jUlQgCAIiKVlXlpKOqQwgqsrwmALIsDx2iqioqAHxu4V8/+DjoffTrKnrRi170ohe96EUvetGLXvSiF/3/0bkkvWsnIHn98u+ymRmNV51Gyzn7RD2mHFNKxqUYkpbjZZ7h1WfGaZzmmEkEAJbm8djDr1z96vrTnA0IoKX51H3Hb8fq9u1nP0UjA2hx7N7QuxbDt26IRgSKxdOBg3PtfJ8Sl8nEEXPvXWrnbIQAcqfKTN65kN+97t9sfv6y/QG64fFP78GtbgAAAABJRU5ErkJggg=="
+         height="1"
+         width="1" /></mask><mask
+       id="mask3528"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><g
+         id="g3530"><g
+           id="g3532"
+           clip-path="url(#clipPath3524)"><g
+             id="g3534"><g
+               id="g3536"
+               transform="matrix(93,0,0,68,667,493)"><image
+                 id="image3538"
+                 xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF0AAABECAYAAADjqDmQAAAABHNCSVQICAgIfAhkiAAAA51JREFUeJztnEtv4koQRo/BpokBoThZIJJN/v/vCkoUYuSAbYwfPYu57duOzWPm3lEvpo5UwqLbXhyXihaLzwM0A3ieN/S1cCNaD2oFwOObdM/zWuH2tXAbWutWuH1t45sLI3c0GvXKXheGMXKbpumVvQ6WdPgp3Pd9giBoy/d9EX8FW3hd15RlSVmWnE4n6rruiffhp0wjXClFGIbMZjNmsxlKqVa8SB9Ga90KL4qCLMvIsow0TTkej1RVRV3X7f6O9CAICMOQKIp4eHggiiIWiwVKKcbjscz4AczcbpqG0+lEmqbsdjviOGY0GrXrZo/WGt+e5UEQMJ/PeXx85Pn5mfV6TRRFhGFIEATtmBG6aK2pqorj8UiSJLy/v6OUomkayrK8vdPX6zUvLy+sVisWiwWTyURGzBmapqGqKvI8J45jwjBEa02e5+2IKcvy306H/kyfz+dEUcRqteLp6Ynlcsl0OhXpZzDSsyxjNpvRNA37/Z7tdst2u22nhBnPg6cX82O6WCxYLpfc39935rrQxYyX6XQKwH6/Z7lcMp/PW2/2aO6c003Hj8djgiBgMpmglEIpxXQ6FelnMNIB8jwnDEPu7u5QShEEQe8Q4n9/gBFvvwC7RHofc/42zer7flv2WDH0pBvMxqES+pgmtctuYBs5A/4BrjWoSHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASP8D2GlGQ5zNBrBvvPaQvx07LsouO0LKpifd3mjCwEyBJNYNYaJHTFJdVVVtGZeDEYH22zI3n04niqKgKAoAiR45g5GeZRl5nrefRVFQliV1XXfEdzrdxCKZmLv9fk+SJAASJ3UBO07q8/OTOI5JkoTD4UBRFJ1sRvhHuulwI/xwOBDHMW9vbwB8fX1JcNoFvgenvb6+8vHxQZIk5HneCU1rg9OM9LIsybKMOI7ZbDYAJEkiEYFXGIoI3Gw2xHFMmqYd6QC+1hrP81rph8OB7XaL1po0TSUM8wqXwjB3ux15nlNVVf+H9HunAxRFQZIkEvt6A5diX+2ZbsS3Ud52NqMEHP8atwQc26eXjnSQKO/f5VeivCW0/n/mltD6nvR2QWT/Jy79ZfIDbR7YvKqk0OoAAAAASUVORK5CYII="
+                 transform="matrix(1,0,0,-1,0,1)"
+                 height="1"
+                 width="1" /></g></g></g></g></mask><clipPath
+       id="clipPath3524"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3526"
+         d="m 667,561 93,0 0,-68 -93,0 0,68 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3520"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3522"
+         d="m 667,561 93,0 0,-68 -93,0 0,68 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3498"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3500"
+         d="m 560,628 270,0 0,-182 -270,0 0,182 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3490"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3492"
+         d="m 0,1080 1920,0 L 1920,0 0,0 0,1080 z"
+         inkscape:connector-curvature="0" /></clipPath><mask
+       id="mask3476"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3478"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABHcAAAK/CAAAAADGr34kAAAAAXNCSVQI5gpbmQAACLFJREFUeJzt1DEBACAMwDDAv+fhohwkCnp1zwJIndcBwHd8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4DaBSkuBn0AocgUAAAAAElFTkSuQmCC"
+         height="1"
+         width="1" /></mask><clipPath
+       id="clipPath3470"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3472"
+         d="m 538,215 954,0 0,118 -954,0 0,-118 z"
+         inkscape:connector-curvature="0" /></clipPath><mask
+       id="mask3460"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3462"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABHcAAAK/CAAAAADGr34kAAAAAXNCSVQI5gpbmQAACLFJREFUeJzt1DEBACAMwDDAv+fhohwkCnp1zwJIndcBwHd8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4DaBSkuBn0AocgUAAAAAElFTkSuQmCC"
+         height="1"
+         width="1" /></mask><clipPath
+       id="clipPath3454"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3456"
+         d="m 554,720 958,0 0,204 -958,0 0,-204 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3432"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3434"
+         d="m 904,587 32,0 0,12 -32,0 0,-12 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3428"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3430"
+         d="m 904,599 32,0 0,-12.002 -32,0 0,12.002 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3420"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3422"
+         d="m 0,1080 1920,0 L 1920,0 0,0 0,1080 z"
+         inkscape:connector-curvature="0" /></clipPath><mask
+       id="mask3396"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3398"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFwAAACdCAAAAAAcMECVAAAAAXNCSVQI5gpbmQAAAZdJREFUaIHt27tu20AQheEzy6Vo0BKMKCkMJ03e/70MFzYR3YisljsnBQXETZpg1J0pt/gwGGz7GwAAhtjhX9UMFsmTIFfckFJKKWx7wt3dQWQAKfd9n6N0wpda6+JAhqU8jI+PQ05BuC/lcpmxODMs9eP+6343dCF3J1s5TR9wJ7Mh9dtvP172Y58CbMDrPL3atdRmt81ffj7vNiF3oV9Pb5h/HZNxvfl2//z96SEI/33AYTvkZLffMoy7py9DF4K3guM45AQgA2ap6zfD8BCEY9j0XTIDMgBYstR1XQyOrku2XjivT7ZOAI5PUMz3+8cIFy5cuHDhwoULFy5cuHDhwoULFy5cuHDhwoULFy5cuHDhwoULFy5cuHDhwoULFy5cuHDhwv97bkEBSZIR4GcpAwCd3loLaX7YWnM6bzjprV5LQVQhUq61Oblu7kuZTwfEtS2nuSwOIIO+lPP0hmNglTOdy+JEBr3O0ysOoT3RNFcnMs3r+Z2X4BLqXB1cN0c5RDdc1QkD7E71Ge/bzd27+APu1Sr+ATqP3j0zgxPtAAAAAElFTkSuQmCC"
+         height="1"
+         width="1" /></mask><mask
+       id="mask3384"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><g
+         id="g3386"><g
+           id="g3388"
+           clip-path="url(#clipPath3380)"><g
+             id="g3390"><g
+               id="g3392"
+               transform="matrix(92,0,0,157,888,469)"><image
+                 id="image3394"
+                 xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFwAAACdCAYAAAA5Wx9JAAAABHNCSVQICAgIfAhkiAAABIZJREFUeJzt111rs0gYxvHL92AipbYHIe1Jv//3CjlopMYXMmqcPdgdH03s7lOWvWDh+sPQUDWUX4c7Ew+AxUqe5639Wv1m1q6ywsMduOd5E/b8tfq9rLUT9vy1K3QvHKzv+w9rfl2t52DHcXxY8+vh/CHf9xGGIaIomlYYhkL/h+bYwzCg7/tpDcMwoQN/gXueN2EnSYI0TbHdbrHdbpEkyYQu8PWstRO2MQZN06BpGrRtCwATurV2CR5FEdI0RZ7neHl5QZ7nyLIMSZIgCALN9JXcnL7dbjDGoKoqFEWB8/kM4NeIcfeF89kdRRF2ux1eX1/x/v6Ow+GAPM+RpimiKJpGi1o2jiP6vkfbtiiKAsfjEZ7noes6GGPQ9z1utxs8z/t+hx8OB3x8fGC/3yPLMsRxrLGykhsnXdehqiqcTicAQNu2+Pr6wuVymdweRoqb4bvdDnmeY7/f4+3tDU9PT9hsNgJfyYFfr1eUZQkAKMsSu91u9fNv9ZTiPjizLMPT0xOen58Xc1z9aj6/AeByuSBN0wX2vMU53O30IAgQRRHiOEaSJEiSBJvNRuArOXAASJIEcRwjiiIEQTDt7LlZeP8GDn2OP18CX+bO4M5nbrdm9QDucv+ZtaWW/cRI5zxyAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInF353wVq7utSynzo9gFtrMY7j9PN2u00LADzP++/++v9h1tqF0dxuDT6cPzhH7vseXdfBGANjDAAgCAKB3+XAnVPXdej7foE/h1/s8HEcMQwDjDFo2xZVVaEsSwDAZrOB7/sCv8tt0uv1irIsUVUV2raFMQbDMGAcx8X94fwhh13XNYqiwOl0AgBcLhfEcSzwlZxd13Woqgqn0wlFUaCu6wW62+UL8L7v0bYtiqLA8XgEAJRliTRNEUURfF+HmrXW7IqiQNu26Pt+CW6thed500N1XePz8xPWWjRNgyzLkCTJNL+1w5e5Ge3meFVVKIoC5/MZdV1P4O7e1R0OAMYYlGWJJEkQhqHGyd90P5KbpkHTNKs73ANggT+Pe77vIwxDRFE0LYft7lGPOUyH3vf9tO5n+AIcAHzff1jz62q9Ofr9ml+fwF3zOa2Z/fPm5+61b50P4NMFQf+rvvt6/we8Kp4iURf8WgAAAABJRU5ErkJggg=="
+                 transform="matrix(1,0,0,-1,0,1)"
+                 height="1"
+                 width="1" /></g></g></g></g></mask><clipPath
+       id="clipPath3380"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3382"
+         d="m 888,626 92,0 0,-157 -92,0 0,157 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3376"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3378"
+         d="m 888,626 92,0 0,-157 -92,0 0,157 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3354"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3356"
+         d="m 1116,527 26.006,0 0,3 -26.006,0 0,-3 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3350"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3352"
+         d="m 1116,530 26.01,0 0,-3 -26.01,0 0,3 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3328"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3330"
+         d="m 1057.994,527 11.006,0 0,3 -11.006,0 0,-3 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3324"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3326"
+         d="m 1057.99,530 26,0 0,-3 -26,0 0,3 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3302"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3304"
+         d="m 1000,527 26.006,0 0,3 -26.006,0 0,-3 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3298"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3300"
+         d="m 1000,530 26.01,0 0,-3 -26.01,0 0,3 z"
+         inkscape:connector-curvature="0" /></clipPath><mask
+       id="mask3272"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3274"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD4AAABUCAAAAAD/xdukAAAAAXNCSVQI5gpbmQAAAZZJREFUWIXt2L1u3DAQBOBZijoZsg9GLikMO03e/72MK85CLvrxUeTuuJCCJB0lA6m4tT4tl6x2BAAAwdbiHycC2fYDEuTCBc455zacgDAzMxAegPN1Xft8T5jGOKuBHuJ8097fN95lc9MwjdMtKTzE1e3p6+nYVJnzkxbGn28dafACVz98+/58amuX2z29X8+1zlF17f784+l4yD29xenSxKF/j7LM/nB6enm8y+bzeLhd2kMl68037fHxS1Nlzm6zn9rGOxF4QMRV9aFp7rK5C96B5PLuECeuqqpcLk6oKamtHJClsjgAWNKkBHMf69/+NFMzErs4uBR2coAksJ+vVXjhhRdeeOGFF1544YUXXvh/5usO+3srzKm/v/UAQKOpamZ0QlU1GldOmsY5BOQu4BrCHNXIpbulMPVX5IYPtNu1n0IyAB60FIbujF+50Qdt7s/dEJIRHrQ4da+45gcvFqfutZuiEZ5icbhw3BL7aOi7tyEauHRHuG4KnVIYxykaIYDsiLxSjDGt/BOB2+fjPmB/2PgBJp8FYb3sImYAAAAASUVORK5CYII="
+         height="1"
+         width="1" /></mask><mask
+       id="mask3260"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><g
+         id="g3262"><g
+           id="g3264"
+           clip-path="url(#clipPath3256)"><g
+             id="g3266"><g
+               id="g3268"
+               transform="matrix(62,0,0,84,1107,495)"><image
+                 id="image3270"
+                 xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD4AAABUCAYAAADaroR4AAAABHNCSVQICAgIfAhkiAAAA1pJREFUeJztnMtuqzoYRheES0QSRaUdRGknff/3qjJIUCmXYIzhDI6MTC5765wR1F6SFQvHESvmByb+PGDgAZ7nPTq8OIbhoR4eN+Ke543SZn9pDMMwSpt9TaA7WtD3/btmjs8dLdj3/V0zxwNzku/7BEFAGIZjC4JgMfKmtFIKKSVSStq2RSk1kQ/gXyEtHccxSZKw2WzYbDbEcTzKL0FcSwshqOuaqqqo65qmaei6DqUUwFQ8DEOSJCFNU15fX0nTlN1uRxzHrFarWde8ruO+7xFCUFUV39/fXC4XsiybjAMEZm2HYch2u+Xt7Y2Pjw+OxyNpmpIkCWEYjpf8XBmGga7ruF6v5HnO6XQiDEOUUrRti5QSpRRKqecrfjwe+fz85HA4sNvtiKJo9pd73/dIKanrmvP5TBzHSCkpy5KiKLher0gp8TzvcY1vt1vSNOVwOPD+/s5+v2e9Xi9CvG1bqqoiiiKapuF8PpMkCVEUjeUKT+7q+ga32+3Y7/e8vLxM6nyO6Ppt25YgCKjrmiRJ7m7Od+L6oO/7rFYrwjAkiiLiOCaOY9br9SLEfd9HCDF5DOsbm/kiE9z+gJY3/wSzzVncPPdhGFBK0XXd+Bjr+/65uEZfAY/aEuj7fhTWn+Yr7LyfT/8D83mtX2Z037zUf5043Nf0bX3DLxXXPBLW/GrxP+HEbcOJ24YTtw0nbhtO3DacuG04cdtw4rbhxG3DiduGE7cNJ24bTtw2nLhtOHHbcOK24cRtw4nbhhO3DSduG07cNpy4bThx23DituHEbcOJ24YTtw1rxZ/uLf3bTr258V/P905c78s0gyZ0g/kmg+jdw7qZDo/+gMCcaMrqGBEhBEIIgNlvo9ZpIEKISSbE7YZauFlxvfVYR4kURUGe5wCzj0rQi9Y0DXmeUxQFdV0jhKDrujENRBOYk7R0WZZkWcbpdALg5+dn9uEYZlRCURScTieyLKMsy4n8ZOO8nqQTNbIs4+vrC4A8zxcTh/LIIcsy6rpGSjkV1xEDelJZlpzPZ4ZhoKqqxQXg6DovioIsy7hcLpRlOYrr7z5ccQAhBHmeLzLySJdsVVVj5NHtio+xZmYWzG8Iueq6bgy5klLe1fhEHOyJNbM2yO5OfBxYqPAtz15b/wHsvBSUT5t0gwAAAABJRU5ErkJggg=="
+                 transform="matrix(1,0,0,-1,0,1)"
+                 height="1"
+                 width="1" /></g></g></g></g></mask><clipPath
+       id="clipPath3256"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3258"
+         d="m 1107,579 62,0 0,-84 -62,0 0,84 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3252"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3254"
+         d="m 1107,579 62,0 0,-84 -62,0 0,84 z"
+         inkscape:connector-curvature="0" /></clipPath><mask
+       id="mask3226"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3228"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD4AAABUCAAAAAD/xdukAAAAAXNCSVQI5gpbmQAAAZZJREFUWIXt2L1u3DAQBOBZijoZsg9GLikMO03e/72MK85CLvrxUeTuuJCCJB0lA6m4tT4tl6x2BAAAwdbiHycC2fYDEuTCBc455zacgDAzMxAegPN1Xft8T5jGOKuBHuJ8097fN95lc9MwjdMtKTzE1e3p6+nYVJnzkxbGn28dafACVz98+/58amuX2z29X8+1zlF17f784+l4yD29xenSxKF/j7LM/nB6enm8y+bzeLhd2kMl68037fHxS1Nlzm6zn9rGOxF4QMRV9aFp7rK5C96B5PLuECeuqqpcLk6oKamtHJClsjgAWNKkBHMf69/+NFMzErs4uBR2coAksJ+vVXjhhRdeeOGFF1544YUXXvh/5usO+3srzKm/v/UAQKOpamZ0QlU1GldOmsY5BOQu4BrCHNXIpbulMPVX5IYPtNu1n0IyAB60FIbujF+50Qdt7s/dEJIRHrQ4da+45gcvFqfutZuiEZ5icbhw3BL7aOi7tyEauHRHuG4KnVIYxykaIYDsiLxSjDGt/BOB2+fjPmB/2PgBJp8FYb3sImYAAAAASUVORK5CYII="
+         height="1"
+         width="1" /></mask><mask
+       id="mask3214"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><g
+         id="g3216"><g
+           id="g3218"
+           clip-path="url(#clipPath3210)"><g
+             id="g3220"><g
+               id="g3222"
+               transform="matrix(62,0,0,84,1049,495)"><image
+                 id="image3224"
+                 xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD4AAABUCAYAAADaroR4AAAABHNCSVQICAgIfAhkiAAAA1pJREFUeJztnMtuqzoYRheES0QSRaUdRGknff/3qjJIUCmXYIzhDI6MTC5765wR1F6SFQvHESvmByb+PGDgAZ7nPTq8OIbhoR4eN+Ke543SZn9pDMMwSpt9TaA7WtD3/btmjs8dLdj3/V0zxwNzku/7BEFAGIZjC4JgMfKmtFIKKSVSStq2RSk1kQ/gXyEtHccxSZKw2WzYbDbEcTzKL0FcSwshqOuaqqqo65qmaei6DqUUwFQ8DEOSJCFNU15fX0nTlN1uRxzHrFarWde8ruO+7xFCUFUV39/fXC4XsiybjAMEZm2HYch2u+Xt7Y2Pjw+OxyNpmpIkCWEYjpf8XBmGga7ruF6v5HnO6XQiDEOUUrRti5QSpRRKqecrfjwe+fz85HA4sNvtiKJo9pd73/dIKanrmvP5TBzHSCkpy5KiKLher0gp8TzvcY1vt1vSNOVwOPD+/s5+v2e9Xi9CvG1bqqoiiiKapuF8PpMkCVEUjeUKT+7q+ga32+3Y7/e8vLxM6nyO6Ppt25YgCKjrmiRJ7m7Od+L6oO/7rFYrwjAkiiLiOCaOY9br9SLEfd9HCDF5DOsbm/kiE9z+gJY3/wSzzVncPPdhGFBK0XXd+Bjr+/65uEZfAY/aEuj7fhTWn+Yr7LyfT/8D83mtX2Z037zUf5043Nf0bX3DLxXXPBLW/GrxP+HEbcOJ24YTtw0nbhtO3DacuG04cdtw4rbhxG3DiduGE7cNJ24bTtw2nLhtOHHbcOK24cRtw4nbhhO3DSduG07cNpy4bThx23DituHEbcOJ24YTtw1rxZ/uLf3bTr258V/P905c78s0gyZ0g/kmg+jdw7qZDo/+gMCcaMrqGBEhBEIIgNlvo9ZpIEKISSbE7YZauFlxvfVYR4kURUGe5wCzj0rQi9Y0DXmeUxQFdV0jhKDrujENRBOYk7R0WZZkWcbpdALg5+dn9uEYZlRCURScTieyLKMsy4n8ZOO8nqQTNbIs4+vrC4A8zxcTh/LIIcsy6rpGSjkV1xEDelJZlpzPZ4ZhoKqqxQXg6DovioIsy7hcLpRlOYrr7z5ccQAhBHmeLzLySJdsVVVj5NHtio+xZmYWzG8Iueq6bgy5klLe1fhEHOyJNbM2yO5OfBxYqPAtz15b/wHsvBSUT5t0gwAAAABJRU5ErkJggg=="
+                 transform="matrix(1,0,0,-1,0,1)"
+                 height="1"
+                 width="1" /></g></g></g></g></mask><clipPath
+       id="clipPath3210"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3212"
+         d="m 1049,579 62,0 0,-84 -62,0 0,84 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3206"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3208"
+         d="m 1049,579 62,0 0,-84 -62,0 0,84 z"
+         inkscape:connector-curvature="0" /></clipPath><mask
+       id="mask3180"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3182"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD4AAABUCAAAAAD/xdukAAAAAXNCSVQI5gpbmQAAAZZJREFUWIXt2L1u3DAQBOBZijoZsg9GLikMO03e/72MK85CLvrxUeTuuJCCJB0lA6m4tT4tl6x2BAAAwdbiHycC2fYDEuTCBc455zacgDAzMxAegPN1Xft8T5jGOKuBHuJ8097fN95lc9MwjdMtKTzE1e3p6+nYVJnzkxbGn28dafACVz98+/58amuX2z29X8+1zlF17f784+l4yD29xenSxKF/j7LM/nB6enm8y+bzeLhd2kMl68037fHxS1Nlzm6zn9rGOxF4QMRV9aFp7rK5C96B5PLuECeuqqpcLk6oKamtHJClsjgAWNKkBHMf69/+NFMzErs4uBR2coAksJ+vVXjhhRdeeOGFF1544YUXXvh/5usO+3srzKm/v/UAQKOpamZ0QlU1GldOmsY5BOQu4BrCHNXIpbulMPVX5IYPtNu1n0IyAB60FIbujF+50Qdt7s/dEJIRHrQ4da+45gcvFqfutZuiEZ5icbhw3BL7aOi7tyEauHRHuG4KnVIYxykaIYDsiLxSjDGt/BOB2+fjPmB/2PgBJp8FYb3sImYAAAAASUVORK5CYII="
+         height="1"
+         width="1" /></mask><mask
+       id="mask3168"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><g
+         id="g3170"><g
+           id="g3172"
+           clip-path="url(#clipPath3164)"><g
+             id="g3174"><g
+               id="g3176"
+               transform="matrix(62,0,0,84,991,495)"><image
+                 id="image3178"
+                 xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD4AAABUCAYAAADaroR4AAAABHNCSVQICAgIfAhkiAAAA1pJREFUeJztnMtuqzoYRheES0QSRaUdRGknff/3qjJIUCmXYIzhDI6MTC5765wR1F6SFQvHESvmByb+PGDgAZ7nPTq8OIbhoR4eN+Ke543SZn9pDMMwSpt9TaA7WtD3/btmjs8dLdj3/V0zxwNzku/7BEFAGIZjC4JgMfKmtFIKKSVSStq2RSk1kQ/gXyEtHccxSZKw2WzYbDbEcTzKL0FcSwshqOuaqqqo65qmaei6DqUUwFQ8DEOSJCFNU15fX0nTlN1uRxzHrFarWde8ruO+7xFCUFUV39/fXC4XsiybjAMEZm2HYch2u+Xt7Y2Pjw+OxyNpmpIkCWEYjpf8XBmGga7ruF6v5HnO6XQiDEOUUrRti5QSpRRKqecrfjwe+fz85HA4sNvtiKJo9pd73/dIKanrmvP5TBzHSCkpy5KiKLher0gp8TzvcY1vt1vSNOVwOPD+/s5+v2e9Xi9CvG1bqqoiiiKapuF8PpMkCVEUjeUKT+7q+ga32+3Y7/e8vLxM6nyO6Ppt25YgCKjrmiRJ7m7Od+L6oO/7rFYrwjAkiiLiOCaOY9br9SLEfd9HCDF5DOsbm/kiE9z+gJY3/wSzzVncPPdhGFBK0XXd+Bjr+/65uEZfAY/aEuj7fhTWn+Yr7LyfT/8D83mtX2Z037zUf5043Nf0bX3DLxXXPBLW/GrxP+HEbcOJ24YTtw0nbhtO3DacuG04cdtw4rbhxG3DiduGE7cNJ24bTtw2nLhtOHHbcOK24cRtw4nbhhO3DSduG07cNpy4bThx23DituHEbcOJ24YTtw1rxZ/uLf3bTr258V/P905c78s0gyZ0g/kmg+jdw7qZDo/+gMCcaMrqGBEhBEIIgNlvo9ZpIEKISSbE7YZauFlxvfVYR4kURUGe5wCzj0rQi9Y0DXmeUxQFdV0jhKDrujENRBOYk7R0WZZkWcbpdALg5+dn9uEYZlRCURScTieyLKMsy4n8ZOO8nqQTNbIs4+vrC4A8zxcTh/LIIcsy6rpGSjkV1xEDelJZlpzPZ4ZhoKqqxQXg6DovioIsy7hcLpRlOYrr7z5ccQAhBHmeLzLySJdsVVVj5NHtio+xZmYWzG8Iueq6bgy5klLe1fhEHOyJNbM2yO5OfBxYqPAtz15b/wHsvBSUT5t0gwAAAABJRU5ErkJggg=="
+                 transform="matrix(1,0,0,-1,0,1)"
+                 height="1"
+                 width="1" /></g></g></g></g></mask><clipPath
+       id="clipPath3164"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3166"
+         d="m 991,579 62,0 0,-84 -62,0 0,84 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3160"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3162"
+         d="m 991,579 62,0 0,-84 -62,0 0,84 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3152"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3154"
+         d="m 897,482 239.999,0 0,135 -239.999,0 0,-135 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3126"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3128"
+         d="m 887,628 270,0 0,-182 -270,0 0,182 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3118"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3120"
+         d="m 0,1080 1920,0 L 1920,0 0,0 0,1080 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3634-8"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3636-7"
+         d="m 570.26,532 c 0,-30.785 24.955,-55.742 55.74,-55.742 l 0,0 c 30.784,0 55.74,24.957 55.74,55.742 l 0,0 c 0,30.784 -24.956,55.74 -55.74,55.74 l 0,0 c -30.785,0 -55.74,-24.956 -55.74,-55.74" /></clipPath><clipPath
+       id="clipPath3642-3"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3644-4"
+         d="m 558.314,543.945 139.351,0 0,-78.633 -139.351,0 0,78.633 z" /></clipPath><mask
+       id="mask3650-5"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><g
+         id="g3652-7"><g
+           id="g3654-7"
+           clip-path="url(#clipPath3646-3)"><g
+             id="g3656-5"><g
+               id="g3658-1"
+               transform="matrix(139.35082,0,0,78.633677,558.31445,465.31115)"><image
+                 id="image3660-3"
+                 xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIwAAABPCAYAAAA5vC0kAAAABHNCSVQICAgIfAhkiAAABCJJREFUeJzt3UFvskwYheEDAmNQYkq7MLab/v//1bhQUgqMwjDMt3gzBJTmy7Ol50omNSLdcAcfcEEAwGFBEARLb9Mf4dxiFgjwEEwQBGMs09f0Nzjnxlimr73Iv/BhhGH4tKbbaZ18GMMwPK3p9mi6UxiGiKIIcRyPK4oiRrNy01istTDGwBiDrutgrZ1FEwH/QvCxKKWQpil2ux12ux2UUmM0DGadnHNjLG3bQmuNpmmgtcb9fkff97DWAsA8mDiOkaYp8jzH6+sr8jxHlmVQSmGz2XCmWSE/pwzDgLZt0TQNvr+/cb1eURTFbDsARNPZJY5j7Pd7vL294ePjA6fTCXmeI01TxHE8fjXRujjn0Pc9brcbyrLE+XxGHMew1qLrOhhjYK2Ftfb3M8zpdMLn5yeOxyOyLEOSJPxaWqlhGGCMgdYal8sFSikYY1DXNaqqwu12gzEGQRAszzD7/R55nuN4POL9/R2HwwHb7ZbBrNQwDOi6Dk3TIEkS3O93XC4XpGmKJEnGcQT45SrJD75ZluFwOODl5WU2x9B6+Pmk6zpEUQStNdI0fbrYeQrGvxmGITabDeI4RpIkUEpBKYXtdstgVsgHE4Yh2rad3UbxA+/0Bl70+A98NNN4povBrItzbnbMnXOw1qLv+/FyehiG34Px/BlnadF6DcMwhuL/Tn8q4HUyAZjfj/E38fzr6VcSg6HR48zyOL8ADIYWLIXiMRgSYTAkwmBIhMGQCIMhEQZDIgyGRBgMiTAYEmEwJMJgSITBkAiDIREGQyIMhkQYDIkwGBJhMCTCYEiEwZAIgyERBkMiDIZEGAyJMBgSYTAkwmBIhMGQCIMhEQZDIgyGRBgMiTAYEmEwJMJgSITBkAiDIREGQyIMhkQYDIkwGBJhMCTCYEiEwZAIgyERBkMiDIZEGAyJMBgSYTAkwmBI5NfHEP/fwyJpHaTH+SkY/yha/9daOy4AfG71yvgHm/s1PfZL4UTTHaeRGGPQdR3atkXbtgCAzWbDYFbGB+OPc9d1MMbM4pmGMzvD+Keit20LrTWqqkJZlgCA7XaLMAwZzMr4k8T9fkdZlqiqClprtG2Lvu8xDMPs89F0Jx9LXdcoigLn8xkA8PPzgyRJGMwK+WPfdR2qqsL5fEZRFKjrehaNP8vMgjHGQGuNoijw9fUFACjLEmmaIo5jhCEvqtZo6dgXRQGtNYwx82CccwiCYNyprmtcLhc459A0DbIsg1JqnF94hlkXP6P4OaaqKhRFgev1irqux2D8ZxfPMADQti3KsoRSClEU8etoxR5HkqZp0DTN4hkmAOCAf5fLYRgiiiLEcTwuH4v/DK2Pj8FHY4wZ1+MMMwsGAMIwfFrT7bRO02ge13T7GIw3nVM4s/w90/suS3d9n4IZNzCUP+23nwf+AzNnFIrywW/wAAAAAElFTkSuQmCC"
+                 transform="matrix(1,0,0,-1,0,1)"
+                 height="1"
+                 width="1" /></g></g></g></g></mask><clipPath
+       id="clipPath3646-3"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3648-7"
+         d="m 558.314,543.945 139.351,0 0,-78.634 -139.351,0 0,78.634 z" /></clipPath><mask
+       id="mask3662-9"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3664-6"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIwAAABPCAAAAAAc13L4AAAAAXNCSVQI5gpbmQAAAdJJREFUaIHt2rFu2zAUheFDirICJUZQt0OQdun7v1fgwRHqylJMkbyng1S0He5aarj/C/gDLWnhcQAAONSNfxTOwdXkkCBXjIP33vtqp0OIiAiIAMCHtm1DLQ0hJaWlCBjgfOj6x8cu+EoYKXGe5nsuCHC+7U+fT8euqfLckBKnH+8DKQgOvn368u311Le+ggVg/rie27KkUraTef3+cjzU+Z8kzZcu3caP5NZn5un08vX5oRJmmQ73S39o3PY2df3x+VPXVHlmZAlz3wXvHALgnG/aQ9c9VML4GDxIrt8ZOO980zR1MM47lpyLbBjArVXAAIDkkgvBOq/zP5EiRYTEDjDgGnaBAUgCe8FsGUbLMFqG0TKMlmG0DKNlGC3DaBlGyzBahtEyjJZhtAyjZRgtw2gZRsswWobRMoyWYbQMo2UYLcNoGUZru0r+fWX5//v7lwMAUCillCprHpZShMINQ0pJS4yoc+NfYlxSEXI9GclxHq+osxKh3K/jHLMACKDkeBvO+FlnP0NZxvNwi1mIAEqahzdcay2LJM3D2zAnIQKdpNuFU73NVYnj8H5LAq4ng3ituEbLcZrmJIQDXPWdXk4p5Q2zmwXj3radwF5Wr78ATrQFVxEFtwQAAAAASUVORK5CYII="
+         height="1"
+         width="1" /></mask><clipPath
+       id="clipPath3634-8-0"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3636-7-9"
+         d="m 570.26,532 c 0,-30.785 24.955,-55.742 55.74,-55.742 l 0,0 c 30.784,0 55.74,24.957 55.74,55.742 l 0,0 c 0,30.784 -24.956,55.74 -55.74,55.74 l 0,0 c -30.785,0 -55.74,-24.956 -55.74,-55.74" /></clipPath><clipPath
+       id="clipPath3642-3-4"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3644-4-2"
+         d="m 558.314,543.945 139.351,0 0,-78.633 -139.351,0 0,78.633 z" /></clipPath><mask
+       id="mask3650-5-0"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><g
+         id="g3652-7-6"><g
+           id="g3654-7-6"
+           clip-path="url(#clipPath3646-3-3)"><g
+             id="g3656-5-4"><g
+               id="g3658-1-6"
+               transform="matrix(139.35082,0,0,78.633677,558.31445,465.31115)"><image
+                 id="image3660-3-1"
+                 xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIwAAABPCAYAAAA5vC0kAAAABHNCSVQICAgIfAhkiAAABCJJREFUeJzt3UFvskwYheEDAmNQYkq7MLab/v//1bhQUgqMwjDMt3gzBJTmy7Ol50omNSLdcAcfcEEAwGFBEARLb9Mf4dxiFgjwEEwQBGMs09f0Nzjnxlimr73Iv/BhhGH4tKbbaZ18GMMwPK3p9mi6UxiGiKIIcRyPK4oiRrNy01istTDGwBiDrutgrZ1FEwH/QvCxKKWQpil2ux12ux2UUmM0DGadnHNjLG3bQmuNpmmgtcb9fkff97DWAsA8mDiOkaYp8jzH6+sr8jxHlmVQSmGz2XCmWSE/pwzDgLZt0TQNvr+/cb1eURTFbDsARNPZJY5j7Pd7vL294ePjA6fTCXmeI01TxHE8fjXRujjn0Pc9brcbyrLE+XxGHMew1qLrOhhjYK2Ftfb3M8zpdMLn5yeOxyOyLEOSJPxaWqlhGGCMgdYal8sFSikYY1DXNaqqwu12gzEGQRAszzD7/R55nuN4POL9/R2HwwHb7ZbBrNQwDOi6Dk3TIEkS3O93XC4XpGmKJEnGcQT45SrJD75ZluFwOODl5WU2x9B6+Pmk6zpEUQStNdI0fbrYeQrGvxmGITabDeI4RpIkUEpBKYXtdstgVsgHE4Yh2rad3UbxA+/0Bl70+A98NNN4povBrItzbnbMnXOw1qLv+/FyehiG34Px/BlnadF6DcMwhuL/Tn8q4HUyAZjfj/E38fzr6VcSg6HR48zyOL8ADIYWLIXiMRgSYTAkwmBIhMGQCIMhEQZDIgyGRBgMiTAYEmEwJMJgSITBkAiDIREGQyIMhkQYDIkwGBJhMCTCYEiEwZAIgyERBkMiDIZEGAyJMBgSYTAkwmBIhMGQCIMhEQZDIgyGRBgMiTAYEmEwJMJgSITBkAiDIREGQyIMhkQYDIkwGBJhMCTCYEiEwZAIgyERBkMiDIZEGAyJMBgSYTAkwmBI5NfHEP/fwyJpHaTH+SkY/yha/9daOy4AfG71yvgHm/s1PfZL4UTTHaeRGGPQdR3atkXbtgCAzWbDYFbGB+OPc9d1MMbM4pmGMzvD+Keit20LrTWqqkJZlgCA7XaLMAwZzMr4k8T9fkdZlqiqClprtG2Lvu8xDMPs89F0Jx9LXdcoigLn8xkA8PPzgyRJGMwK+WPfdR2qqsL5fEZRFKjrehaNP8vMgjHGQGuNoijw9fUFACjLEmmaIo5jhCEvqtZo6dgXRQGtNYwx82CccwiCYNyprmtcLhc459A0DbIsg1JqnF94hlkXP6P4OaaqKhRFgev1irqux2D8ZxfPMADQti3KsoRSClEU8etoxR5HkqZp0DTN4hkmAOCAf5fLYRgiiiLEcTwuH4v/DK2Pj8FHY4wZ1+MMMwsGAMIwfFrT7bRO02ge13T7GIw3nVM4s/w90/suS3d9n4IZNzCUP+23nwf+AzNnFIrywW/wAAAAAElFTkSuQmCC"
+                 transform="matrix(1,0,0,-1,0,1)"
+                 height="1"
+                 width="1" /></g></g></g></g></mask><clipPath
+       id="clipPath3646-3-3"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3648-7-6"
+         d="m 558.314,543.945 139.351,0 0,-78.634 -139.351,0 0,78.634 z" /></clipPath><mask
+       id="mask3662-9-4"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3664-6-5"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIwAAABPCAAAAAAc13L4AAAAAXNCSVQI5gpbmQAAAdJJREFUaIHt2rFu2zAUheFDirICJUZQt0OQdun7v1fgwRHqylJMkbyng1S0He5aarj/C/gDLWnhcQAAONSNfxTOwdXkkCBXjIP33vtqp0OIiAiIAMCHtm1DLQ0hJaWlCBjgfOj6x8cu+EoYKXGe5nsuCHC+7U+fT8euqfLckBKnH+8DKQgOvn368u311Le+ggVg/rie27KkUraTef3+cjzU+Z8kzZcu3caP5NZn5un08vX5oRJmmQ73S39o3PY2df3x+VPXVHlmZAlz3wXvHALgnG/aQ9c9VML4GDxIrt8ZOO980zR1MM47lpyLbBjArVXAAIDkkgvBOq/zP5EiRYTEDjDgGnaBAUgCe8FsGUbLMFqG0TKMlmG0DKNlGC3DaBlGyzBahtEyjJZhtAyjZRgtw2gZRsswWobRMoyWYbQMo2UYLcNoGUZru0r+fWX5//v7lwMAUCillCprHpZShMINQ0pJS4yoc+NfYlxSEXI9GclxHq+osxKh3K/jHLMACKDkeBvO+FlnP0NZxvNwi1mIAEqahzdcay2LJM3D2zAnIQKdpNuFU73NVYnj8H5LAq4ng3ituEbLcZrmJIQDXPWdXk4p5Q2zmwXj3radwF5Wr78ATrQFVxEFtwQAAAAASUVORK5CYII="
+         height="1"
+         width="1" /></mask><clipPath
+       id="clipPath3592-5"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3594-9"
+         d="m 730.778,549 12,0 0,-12 -12,0 0,12 z" /></clipPath><clipPath
+       id="clipPath3566-8"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3568-8"
+         d="m 679,547.865 32,0 0,-12.002 -32,0 0,12.002 z" /></clipPath><clipPath
+       id="clipPath3570-6"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3572-0"
+         d="m 679,535.865 32,0 0,12 -32,0 0,-12 z" /></clipPath><clipPath
+       id="clipPath3520-6"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3522-3"
+         d="m 667,561 93,0 0,-68 -93,0 0,68 z" /></clipPath><mask
+       id="mask3528-3"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><g
+         id="g3530-7"><g
+           id="g3532-3"
+           clip-path="url(#clipPath3524-5)"><g
+             id="g3534-0"><g
+               id="g3536-4"
+               transform="matrix(93,0,0,68,667,493)"><image
+                 id="image3538-4"
+                 xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF0AAABECAYAAADjqDmQAAAABHNCSVQICAgIfAhkiAAAA51JREFUeJztnEtv4koQRo/BpokBoThZIJJN/v/vCkoUYuSAbYwfPYu57duOzWPm3lEvpo5UwqLbXhyXihaLzwM0A3ieN/S1cCNaD2oFwOObdM/zWuH2tXAbWutWuH1t45sLI3c0GvXKXheGMXKbpumVvQ6WdPgp3Pd9giBoy/d9EX8FW3hd15RlSVmWnE4n6rruiffhp0wjXClFGIbMZjNmsxlKqVa8SB9Ga90KL4qCLMvIsow0TTkej1RVRV3X7f6O9CAICMOQKIp4eHggiiIWiwVKKcbjscz4AczcbpqG0+lEmqbsdjviOGY0GrXrZo/WGt+e5UEQMJ/PeXx85Pn5mfV6TRRFhGFIEATtmBG6aK2pqorj8UiSJLy/v6OUomkayrK8vdPX6zUvLy+sVisWiwWTyURGzBmapqGqKvI8J45jwjBEa02e5+2IKcvy306H/kyfz+dEUcRqteLp6Ynlcsl0OhXpZzDSsyxjNpvRNA37/Z7tdst2u22nhBnPg6cX82O6WCxYLpfc39935rrQxYyX6XQKwH6/Z7lcMp/PW2/2aO6c003Hj8djgiBgMpmglEIpxXQ6FelnMNIB8jwnDEPu7u5QShEEQe8Q4n9/gBFvvwC7RHofc/42zer7flv2WDH0pBvMxqES+pgmtctuYBs5A/4BrjWoSHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASP8D2GlGQ5zNBrBvvPaQvx07LsouO0LKpifd3mjCwEyBJNYNYaJHTFJdVVVtGZeDEYH22zI3n04niqKgKAoAiR45g5GeZRl5nrefRVFQliV1XXfEdzrdxCKZmLv9fk+SJAASJ3UBO07q8/OTOI5JkoTD4UBRFJ1sRvhHuulwI/xwOBDHMW9vbwB8fX1JcNoFvgenvb6+8vHxQZIk5HneCU1rg9OM9LIsybKMOI7ZbDYAJEkiEYFXGIoI3Gw2xHFMmqYd6QC+1hrP81rph8OB7XaL1po0TSUM8wqXwjB3ux15nlNVVf+H9HunAxRFQZIkEvt6A5diX+2ZbsS3Ud52NqMEHP8atwQc26eXjnSQKO/f5VeivCW0/n/mltD6nvR2QWT/Jy79ZfIDbR7YvKqk0OoAAAAASUVORK5CYII="
+                 transform="matrix(1,0,0,-1,0,1)"
+                 height="1"
+                 width="1" /></g></g></g></g></mask><clipPath
+       id="clipPath3524-5"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3526-4"
+         d="m 667,561 93,0 0,-68 -93,0 0,68 z" /></clipPath><mask
+       id="mask3540-4"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3542-1"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF0AAABECAAAAADGw2ZMAAAAAXNCSVQI5gpbmQAAAZJJREFUWIXt2DFv2zAQhuHvTlTkyDaMuBmCtEv//+9q0KKuAtWWZJnkfR0UAwY69jyVXAhoeEQcyOUVAAAEvos3rAjE0ydBfugCVVV1Oz9hZmYgEABoqOs6ePGE5Rgv2UAEiIamXa+boE665Xkch3PKQIBo3e4/7bdN5TJ70i7De6ckjUGg9eb5y+u+rdUBB5jO/Y/G4s3ZX7++bB98RmNp6lpOwzkal7lv9i+fdysvfVzb8XCoVWS5M0273T01lYvOtMJxt2kqBQIgolX90DQrLx1T+9jUlQgCAIiKVlXlpKOqQwgqsrwmALIsDx2iqioqAHxu4V8/+DjoffTrKnrRi170ohe96EUvetGLXvSiF/3/0bkkvWsnIHn98u+ymRmNV51Gyzn7RD2mHFNKxqUYkpbjZZ7h1WfGaZzmmEkEAJbm8djDr1z96vrTnA0IoKX51H3Hb8fq9u1nP0UjA2hx7N7QuxbDt26IRgSKxdOBg3PtfJ8Sl8nEEXPvXWrnbIQAcqfKTN65kN+97t9sfv6y/QG64fFP78GtbgAAAABJRU5ErkJggg=="
+         height="1"
+         width="1" /></mask><clipPath
+       id="clipPath3592-5-6"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3594-9-5"
+         d="m 730.778,549 12,0 0,-12 -12,0 0,12 z" /></clipPath><clipPath
+       id="clipPath3566-8-1"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3568-8-2"
+         d="m 679,547.865 32,0 0,-12.002 -32,0 0,12.002 z" /></clipPath><clipPath
+       id="clipPath3570-6-5"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3572-0-0"
+         d="m 679,535.865 32,0 0,12 -32,0 0,-12 z" /></clipPath><clipPath
+       id="clipPath3520-6-0"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3522-3-3"
+         d="m 667,561 93,0 0,-68 -93,0 0,68 z" /></clipPath><mask
+       id="mask3528-3-8"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><g
+         id="g3530-7-0"><g
+           id="g3532-3-9"
+           clip-path="url(#clipPath3524-5-5)"><g
+             id="g3534-0-9"><g
+               id="g3536-4-3"
+               transform="matrix(93,0,0,68,667,493)"><image
+                 id="image3538-4-0"
+                 xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF0AAABECAYAAADjqDmQAAAABHNCSVQICAgIfAhkiAAAA51JREFUeJztnEtv4koQRo/BpokBoThZIJJN/v/vCkoUYuSAbYwfPYu57duOzWPm3lEvpo5UwqLbXhyXihaLzwM0A3ieN/S1cCNaD2oFwOObdM/zWuH2tXAbWutWuH1t45sLI3c0GvXKXheGMXKbpumVvQ6WdPgp3Pd9giBoy/d9EX8FW3hd15RlSVmWnE4n6rruiffhp0wjXClFGIbMZjNmsxlKqVa8SB9Ga90KL4qCLMvIsow0TTkej1RVRV3X7f6O9CAICMOQKIp4eHggiiIWiwVKKcbjscz4AczcbpqG0+lEmqbsdjviOGY0GrXrZo/WGt+e5UEQMJ/PeXx85Pn5mfV6TRRFhGFIEATtmBG6aK2pqorj8UiSJLy/v6OUomkayrK8vdPX6zUvLy+sVisWiwWTyURGzBmapqGqKvI8J45jwjBEa02e5+2IKcvy306H/kyfz+dEUcRqteLp6Ynlcsl0OhXpZzDSsyxjNpvRNA37/Z7tdst2u22nhBnPg6cX82O6WCxYLpfc39935rrQxYyX6XQKwH6/Z7lcMp/PW2/2aO6c003Hj8djgiBgMpmglEIpxXQ6FelnMNIB8jwnDEPu7u5QShEEQe8Q4n9/gBFvvwC7RHofc/42zer7flv2WDH0pBvMxqES+pgmtctuYBs5A/4BrjWoSHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASP8D2GlGQ5zNBrBvvPaQvx07LsouO0LKpifd3mjCwEyBJNYNYaJHTFJdVVVtGZeDEYH22zI3n04niqKgKAoAiR45g5GeZRl5nrefRVFQliV1XXfEdzrdxCKZmLv9fk+SJAASJ3UBO07q8/OTOI5JkoTD4UBRFJ1sRvhHuulwI/xwOBDHMW9vbwB8fX1JcNoFvgenvb6+8vHxQZIk5HneCU1rg9OM9LIsybKMOI7ZbDYAJEkiEYFXGIoI3Gw2xHFMmqYd6QC+1hrP81rph8OB7XaL1po0TSUM8wqXwjB3ux15nlNVVf+H9HunAxRFQZIkEvt6A5diX+2ZbsS3Ud52NqMEHP8atwQc26eXjnSQKO/f5VeivCW0/n/mltD6nvR2QWT/Jy79ZfIDbR7YvKqk0OoAAAAASUVORK5CYII="
+                 transform="matrix(1,0,0,-1,0,1)"
+                 height="1"
+                 width="1" /></g></g></g></g></mask><clipPath
+       id="clipPath3524-5-5"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3526-4-5"
+         d="m 667,561 93,0 0,-68 -93,0 0,68 z" /></clipPath><mask
+       id="mask3540-4-8"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3542-1-9"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF0AAABECAAAAADGw2ZMAAAAAXNCSVQI5gpbmQAAAZJJREFUWIXt2DFv2zAQhuHvTlTkyDaMuBmCtEv//+9q0KKuAtWWZJnkfR0UAwY69jyVXAhoeEQcyOUVAAAEvos3rAjE0ydBfugCVVV1Oz9hZmYgEABoqOs6ePGE5Rgv2UAEiIamXa+boE665Xkch3PKQIBo3e4/7bdN5TJ70i7De6ckjUGg9eb5y+u+rdUBB5jO/Y/G4s3ZX7++bB98RmNp6lpOwzkal7lv9i+fdysvfVzb8XCoVWS5M0273T01lYvOtMJxt2kqBQIgolX90DQrLx1T+9jUlQgCAIiKVlXlpKOqQwgqsrwmALIsDx2iqioqAHxu4V8/+DjoffTrKnrRi170ohe96EUvetGLXvSiF/3/0bkkvWsnIHn98u+ymRmNV51Gyzn7RD2mHFNKxqUYkpbjZZ7h1WfGaZzmmEkEAJbm8djDr1z96vrTnA0IoKX51H3Hb8fq9u1nP0UjA2hx7N7QuxbDt26IRgSKxdOBg3PtfJ8Sl8nEEXPvXWrnbIQAcqfKTN65kN+97t9sfv6y/QG64fFP78GtbgAAAABJRU5ErkJggg=="
+         height="1"
+         width="1" /></mask><clipPath
+       id="clipPath3942-2"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3944-1"
+         d="m 1337.7,554.569 67.31,0 0,-64.569 -67.31,0 0,64.569 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3912-3"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3914-9"
+         d="m 1404.777,549.002 12,0 0,11.998 -12,0 0,-11.998 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3908-4"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3910-0"
+         d="m 1404.78,561 12,0 0,-12 -12,0 0,12 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3886-1"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3888-7"
+         d="m 1363,547.865 32,0 0,12 -32,0 0,-12 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3882-9"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3884-9"
+         d="m 1363,559.865 32,0 0,-12.002 -32,0 0,12.002 z"
+         inkscape:connector-curvature="0" /></clipPath><mask
+       id="mask3852-6"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3854-6"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHEAAABECAAAAACTooUSAAAAAXNCSVQI5gpbmQAAAXhJREFUWIXt2T9v3DAMBfBHWj4Fzh2CXjsEaZd+/+8VZGiN+v4Y1cni6+ADmqUjnQ7kqEE/ULQXPgEAQLBB8S8lAnE3SZCrKFBVVd8+CTMzA5EAaOr7PrmShC211sWABNGUh8fHnNRTtKVcrzMWY4JoPxw/Hw+585sl2cp5/AkzMgm033/59nIcevUCAavz+Cq3Upvce3z5/nzY+T0r7XZ+w/zrpMJ1jvvj89enB0/x94Rpn5PK/VvNw+HpU+78xFZwGnJSAAkQ0a7f5fzgKSLv+k5FgAQAoqJd1zmK6DqVdWppPZK1vES8u93xj/hHhRhiiCGGGGKIIYYYYoghhhhiiCGGGOL/Jt73ciRJuinvr08AQKO11vzCALbWjMa7SFqrt1LgutEtt9qMXHu0pcznCc5b6/NcFgOQQFvKZXzDyXszP17KYkQCrc7jKyb/9GGcqxGJYvXyg9ctEpZLNXDtEWXaJEWqRgggWyZl/IA08EMST2DTVPcPY4fdi0eNNAgAAAAASUVORK5CYII="
+         height="1"
+         width="1" /></mask><mask
+       id="mask3840-6"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><g
+         id="g3842-8"><g
+           id="g3844-1"
+           clip-path="url(#clipPath3836-1)"><g
+             id="g3846-7"><g
+               id="g3848-5"
+               transform="matrix(113,0,0,68,1351,505)"><image
+                 id="image3850-5"
+                 xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHEAAABECAYAAAC2ydrOAAAABHNCSVQICAgIfAhkiAAAA1NJREFUeJztnc1uozAURj8HjCMCikq7iNJu+v7vVXXRovJn1RDiWUztMQnttIuQmat7pKugAFn4yDZk8V0BwGIGIcTc18wVsXZWFQROJAohvMDwmLke1lovMDx2xO7AyVqtVmcVnmeWw8k6Ho9nFZ6Pw5tWqxXiOIaU0lccxyzyCoQCD4cDhmHwdTgcvEjgQ6IQwgtUSiFNU2w2G2w2GyilvEiWuBzWWi/QGIOu69B1HbTWAOBFWmunEqWUSNMURVHg9vYWRVEgz3MopRBFEe+RC+H2vXEcYYxB0zQoyxKvr68A/iyv7ro43AullMiyDHd3d3h4eMB+v0dRFEjTFFJKv6wyl+d4PGIYBmitUZYlnp6eIIRA3/cwxmAYBozjCCHE5zNxv9/j8fERu90OeZ4jSRJeUhfCLaV936NpGjw/PwMAtNZ4e3tDXdfexdly6vbELMtQFAV2ux3u7++x3W6xXq9Z4kI4ie/v76iqCgBQVRWyLJt9Rpl9OnUPN3meY7vd4ubmZrIvMpcl3A8BoK5rpGk6ERgyeU90MzKKIkgpkSQJlFJQSmG9XrPEhXASAUAphSRJIKVEFEV+BoYe4tMfcCJDoWGxxMvj3hHdmIc+5sb/TKLD2Z4r5vL8ZNz5nYEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEALJEAn2a7uWji02Iuz0/H/kyiC0x1n+M4+gI4kX8JXFSmq9DHnMw4vDEUNwyDz5t24akclbkMYWitMQZ93/vM7zDA3TGZiWGEv9YaTdP4+GKOj16O0/jopmmgtYYx5qwnBvAh8bQHQ9u2KMvSB4jXdc1B7gsyF+ReliXatp2InHSocTedRvgDvwPEuaXC8sz5KMsSWmsMwzCVaK2FEMLf1LYtXl5eYK1F13Xc3OQKfNXcpG1bL9FdOzsTAcAYg6qquM3QlfiqzdDpTPSt98LeGNzw6/p8p+HXrESAW+/9S3y39R43wfwP+FsTzDOJ/gTL++f47K+3XyWNnXDxB1SBAAAAAElFTkSuQmCC"
+                 transform="matrix(1,0,0,-1,0,1)"
+                 height="1"
+                 width="1" /></g></g></g></g></mask><clipPath
+       id="clipPath3836-1"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3838-6"
+         d="m 1351,573 113,0 0,-68 -113,0 0,68 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3832-3"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3834-3"
+         d="m 1351,573 113,0 0,-68 -113,0 0,68 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3824-4"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3826-5"
+         d="m 0,1080 1920,0 L 1920,0 0,0 0,1080 z"
+         inkscape:connector-curvature="0" /></clipPath><mask
+       id="mask3798-6"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3800-3"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHEAAABECAAAAACTooUSAAAAAXNCSVQI5gpbmQAAAZ9JREFUWIXt2U9v1DAQBfA348lmyXa1FdBSgRDf/4tVe4CI7J+oXtvzOKQIOCOnF8/Ft/lpZCeHeQIAgGCF4h9KBFLdJEEuokBVVevOSbi7OwiDiIZN14WqJOE5pZQdMEBtO+yGPmhN0XO8Xmdkp4mEfv/+w/2u13p3SZZ4Hn/AnTRo2B6evjwd3lnFGT3N47PcYipiIrY9PH77+nHotBpIv52PmH+eVGiQsBnuHz5/2m1qii8TprveVJa3av2wP9xt6j0dlojT0JsCMJAk1LptVRH9pgsqAhjoJedC0YqfBxGCytLfCJZcsgM1/3Qi8ru7gnQv7mQ17t9SgEutBEIBYEXvVVy1mtjEJjaxiU1sYhOb2MQmNrGJTWxiE5v4P2XLUXlt9Xd7AwA6vZRSLwxgKcXpfBVJL+kWI0LNjW68peLkMqPnOJ8nbCvuV/1lOs8xO5aNbo6X8YhTzR2y387H8RKzEwZ6msdnTDWzgCV9GOfkhFE8Xb7zuu9D9YTlkhxcZkScelshRUpOCCBqXdfZOkkZ3yANfJPEE1g11f0FocoCRBRb0tkAAAAASUVORK5CYII="
+         height="1"
+         width="1" /></mask><mask
+       id="mask3786-0"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><g
+         id="g3788-7"><g
+           id="g3790-3"
+           clip-path="url(#clipPath3782-0)"><g
+             id="g3792-9"><g
+               id="g3794-3"
+               transform="matrix(113,0,0,68,1351,444)"><image
+                 id="image3796-9"
+                 xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHEAAABECAYAAAC2ydrOAAAABHNCSVQICAgIfAhkiAAAA59JREFUeJztnclurDoURTdgmkAhSmlLiaL8/49FGSQodFZM5zd4sstUkdsMQnKPzpKsQgVMWDo2ZrCPB0BjBc/z1v5mvhGtV1XBw4lEz/OsQPeY+T601lage2wQ5sDI8n3/bLjnme0wsuZ5PhvueQEcK873fQRBgCiKEIYhwjBEEAQs8htwBY7jiGEY7BjH0YoEnEr0fR9CCCRJgjRNkWUZ0jRFHMdWJEvcDq21FaiUQtd16LoOUkoAsCK11hCmCoMgQBzHyPMcl5eXuLq6wn6/R5ZliOPYSmSRX49Z96ZpglIKTdOgLEu8vb0BOE6v5joBwE6jSZKgKAocDgc8PDzgcDigKApcXFxACMECN2SeZwzDACklyrLE8/MzPM9D3/dQSmEYBkzTBM/zjpVoptKiKHB7e4unpyc8Pj7i+voaaZoiDEO7NjJfi5lK+75H0zR4eXkBAEgp8f7+jrqu7cxoK9FMp1EUIU1T7Pd73Nzc4P7+Hnd3d8iyDFEUscSNMBI/Pj5QVRUAoKoq7HY7xHEMIcTiHeXs7VQIgTiOkaYp8jxHURTY7XZWIk+pX4+7HgJAXdf2JdMIdBHmJncAx7fVMAyRJAlL3BAjEQDiOLZbPneX4HqwEud5xjRNGMcR4zhimiZorRf7R5a4DaaQgiBYPPfPnr9wP+cYiebX3VAC/BluS8yzdsdn+MBxOjX7j2mazvYizM/FrpCn6+LpGsn8XM72DCzv34M3fgRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQRgiQQQn53gdKnv42+f/ZlEk/HmJi+aAXAi/xaYsEQzXB9rMoV7oytuGAabN23CU4MgYIkb4IbWKqXQ973N/F4LTVxUohvhL6VE0zQ2vjhJEs473YjT+OimaSClhFJqNcJ0EVprBLZti7IsbYB4XdecPLwha0HuZVmibduFyEWHGnPTaYQ/8H+AOKfxb8+aj7IsIaXEMAxLiSYi2tzUti1eX1+htUbXdcjz3Hap4eThbfhVc5O2ba1Ec+1qJQKAUgpVVa1G+DNfz6/aDJ1Wom2957ZUMM2+wjBcRPizxO34k4ZfqxIBbr33k/jT1nvcBPMf4HdNMM8k2hMs78fx2ae3/wBR6gt9OOvm0AAAAABJRU5ErkJggg=="
+                 transform="matrix(1,0,0,-1,0,1)"
+                 height="1"
+                 width="1" /></g></g></g></g></mask><clipPath
+       id="clipPath3782-0"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3784-8"
+         d="m 1351,512 113,0 0,-68 -113,0 0,68 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3778-1"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3780-0"
+         d="m 1351,512 113,0 0,-68 -113,0 0,68 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3770-5"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3772-0"
+         d="m 1341,490 129,0 0,89 -129,0 0,-89 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3748-6"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3750-3"
+         d="m 1214,628 270,0 0,-182 -270,0 0,182 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3726-6"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3728-1"
+         d="m 652.002,520.002 12,0 0,11.998 -12,0 0,-11.998 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3722-1"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3724-4"
+         d="m 652,532 12.002,0 0,-12 -12.002,0 0,12 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3700-1"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3702-8"
+         d="m 592,518.865 32,0 0,12 -32,0 0,-12 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3696-9"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3698-6"
+         d="m 592,530.865 32,0 0,-12.002 -32,0 0,12.002 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3688-4"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3690-8"
+         d="m 0,1080 1920,0 L 1920,0 0,0 0,1080 z"
+         inkscape:connector-curvature="0" /></clipPath><mask
+       id="mask3662-6"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3664-9"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIwAAABPCAAAAAAc13L4AAAAAXNCSVQI5gpbmQAAAdJJREFUaIHt2rFu2zAUheFDirICJUZQt0OQdun7v1fgwRHqylJMkbyng1S0He5aarj/C/gDLWnhcQAAONSNfxTOwdXkkCBXjIP33vtqp0OIiAiIAMCHtm1DLQ0hJaWlCBjgfOj6x8cu+EoYKXGe5nsuCHC+7U+fT8euqfLckBKnH+8DKQgOvn368u311Le+ggVg/rie27KkUraTef3+cjzU+Z8kzZcu3caP5NZn5un08vX5oRJmmQ73S39o3PY2df3x+VPXVHlmZAlz3wXvHALgnG/aQ9c9VML4GDxIrt8ZOO980zR1MM47lpyLbBjArVXAAIDkkgvBOq/zP5EiRYTEDjDgGnaBAUgCe8FsGUbLMFqG0TKMlmG0DKNlGC3DaBlGyzBahtEyjJZhtAyjZRgtw2gZRsswWobRMoyWYbQMo2UYLcNoGUZru0r+fWX5//v7lwMAUCillCprHpZShMINQ0pJS4yoc+NfYlxSEXI9GclxHq+osxKh3K/jHLMACKDkeBvO+FlnP0NZxvNwi1mIAEqahzdcay2LJM3D2zAnIQKdpNuFU73NVYnj8H5LAq4ng3ituEbLcZrmJIQDXPWdXk4p5Q2zmwXj3radwF5Wr78ATrQFVxEFtwQAAAAASUVORK5CYII="
+         height="1"
+         width="1" /></mask><mask
+       id="mask3650-6"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><g
+         id="g3652-6"><g
+           id="g3654-8"
+           clip-path="url(#clipPath3646-6)"><g
+             id="g3656-3"><g
+               id="g3658-9"
+               transform="matrix(139.35082,0,0,78.633677,558.31445,465.31115)"><image
+                 id="image3660-2"
+                 xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIwAAABPCAYAAAA5vC0kAAAABHNCSVQICAgIfAhkiAAABCJJREFUeJzt3UFvskwYheEDAmNQYkq7MLab/v//1bhQUgqMwjDMt3gzBJTmy7Ol50omNSLdcAcfcEEAwGFBEARLb9Mf4dxiFgjwEEwQBGMs09f0Nzjnxlimr73Iv/BhhGH4tKbbaZ18GMMwPK3p9mi6UxiGiKIIcRyPK4oiRrNy01istTDGwBiDrutgrZ1FEwH/QvCxKKWQpil2ux12ux2UUmM0DGadnHNjLG3bQmuNpmmgtcb9fkff97DWAsA8mDiOkaYp8jzH6+sr8jxHlmVQSmGz2XCmWSE/pwzDgLZt0TQNvr+/cb1eURTFbDsARNPZJY5j7Pd7vL294ePjA6fTCXmeI01TxHE8fjXRujjn0Pc9brcbyrLE+XxGHMew1qLrOhhjYK2Ftfb3M8zpdMLn5yeOxyOyLEOSJPxaWqlhGGCMgdYal8sFSikYY1DXNaqqwu12gzEGQRAszzD7/R55nuN4POL9/R2HwwHb7ZbBrNQwDOi6Dk3TIEkS3O93XC4XpGmKJEnGcQT45SrJD75ZluFwOODl5WU2x9B6+Pmk6zpEUQStNdI0fbrYeQrGvxmGITabDeI4RpIkUEpBKYXtdstgVsgHE4Yh2rad3UbxA+/0Bl70+A98NNN4povBrItzbnbMnXOw1qLv+/FyehiG34Px/BlnadF6DcMwhuL/Tn8q4HUyAZjfj/E38fzr6VcSg6HR48zyOL8ADIYWLIXiMRgSYTAkwmBIhMGQCIMhEQZDIgyGRBgMiTAYEmEwJMJgSITBkAiDIREGQyIMhkQYDIkwGBJhMCTCYEiEwZAIgyERBkMiDIZEGAyJMBgSYTAkwmBIhMGQCIMhEQZDIgyGRBgMiTAYEmEwJMJgSITBkAiDIREGQyIMhkQYDIkwGBJhMCTCYEiEwZAIgyERBkMiDIZEGAyJMBgSYTAkwmBI5NfHEP/fwyJpHaTH+SkY/yha/9daOy4AfG71yvgHm/s1PfZL4UTTHaeRGGPQdR3atkXbtgCAzWbDYFbGB+OPc9d1MMbM4pmGMzvD+Keit20LrTWqqkJZlgCA7XaLMAwZzMr4k8T9fkdZlqiqClprtG2Lvu8xDMPs89F0Jx9LXdcoigLn8xkA8PPzgyRJGMwK+WPfdR2qqsL5fEZRFKjrehaNP8vMgjHGQGuNoijw9fUFACjLEmmaIo5jhCEvqtZo6dgXRQGtNYwx82CccwiCYNyprmtcLhc459A0DbIsg1JqnF94hlkXP6P4OaaqKhRFgev1irqux2D8ZxfPMADQti3KsoRSClEU8etoxR5HkqZp0DTN4hkmAOCAf5fLYRgiiiLEcTwuH4v/DK2Pj8FHY4wZ1+MMMwsGAMIwfFrT7bRO02ge13T7GIw3nVM4s/w90/suS3d9n4IZNzCUP+23nwf+AzNnFIrywW/wAAAAAElFTkSuQmCC"
+                 transform="matrix(1,0,0,-1,0,1)"
+                 height="1"
+                 width="1" /></g></g></g></g></mask><clipPath
+       id="clipPath3646-6"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3648-8"
+         d="m 558.314,543.945 139.351,0 0,-78.634 -139.351,0 0,78.634 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3642-7"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3644-3"
+         d="m 558.314,543.945 139.351,0 0,-78.633 -139.351,0 0,78.633 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3634-3"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3636-8"
+         d="m 570.26,532 c 0,-30.785 24.955,-55.742 55.74,-55.742 l 0,0 c 30.784,0 55.74,24.957 55.74,55.742 l 0,0 c 0,30.784 -24.956,55.74 -55.74,55.74 l 0,0 c -30.785,0 -55.74,-24.956 -55.74,-55.74"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3610-5"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3612-4"
+         d="m 652.333,574.333 101,0 0,-79.333 -101,0 0,79.333 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3592-6"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3594-98"
+         d="m 730.778,549 12,0 0,-12 -12,0 0,12 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3570-0"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3572-8"
+         d="m 679,535.865 32,0 0,12 -32,0 0,-12 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3566-5"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3568-3"
+         d="m 679,547.865 32,0 0,-12.002 -32,0 0,12.002 z"
+         inkscape:connector-curvature="0" /></clipPath><mask
+       id="mask3540-6"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3542-0"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF0AAABECAAAAADGw2ZMAAAAAXNCSVQI5gpbmQAAAZJJREFUWIXt2DFv2zAQhuHvTlTkyDaMuBmCtEv//+9q0KKuAtWWZJnkfR0UAwY69jyVXAhoeEQcyOUVAAAEvos3rAjE0ydBfugCVVV1Oz9hZmYgEABoqOs6ePGE5Rgv2UAEiIamXa+boE665Xkch3PKQIBo3e4/7bdN5TJ70i7De6ckjUGg9eb5y+u+rdUBB5jO/Y/G4s3ZX7++bB98RmNp6lpOwzkal7lv9i+fdysvfVzb8XCoVWS5M0273T01lYvOtMJxt2kqBQIgolX90DQrLx1T+9jUlQgCAIiKVlXlpKOqQwgqsrwmALIsDx2iqioqAHxu4V8/+DjoffTrKnrRi170ohe96EUvetGLXvSiF/3/0bkkvWsnIHn98u+ymRmNV51Gyzn7RD2mHFNKxqUYkpbjZZ7h1WfGaZzmmEkEAJbm8djDr1z96vrTnA0IoKX51H3Hb8fq9u1nP0UjA2hx7N7QuxbDt26IRgSKxdOBg3PtfJ8Sl8nEEXPvXWrnbIQAcqfKTN65kN+97t9sfv6y/QG64fFP78GtbgAAAABJRU5ErkJggg=="
+         height="1"
+         width="1" /></mask><mask
+       id="mask3528-8"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><g
+         id="g3530-9"><g
+           id="g3532-7"
+           clip-path="url(#clipPath3524-3)"><g
+             id="g3534-3"><g
+               id="g3536-8"
+               transform="matrix(93,0,0,68,667,493)"><image
+                 id="image3538-8"
+                 xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF0AAABECAYAAADjqDmQAAAABHNCSVQICAgIfAhkiAAAA51JREFUeJztnEtv4koQRo/BpokBoThZIJJN/v/vCkoUYuSAbYwfPYu57duOzWPm3lEvpo5UwqLbXhyXihaLzwM0A3ieN/S1cCNaD2oFwOObdM/zWuH2tXAbWutWuH1t45sLI3c0GvXKXheGMXKbpumVvQ6WdPgp3Pd9giBoy/d9EX8FW3hd15RlSVmWnE4n6rruiffhp0wjXClFGIbMZjNmsxlKqVa8SB9Ga90KL4qCLMvIsow0TTkej1RVRV3X7f6O9CAICMOQKIp4eHggiiIWiwVKKcbjscz4AczcbpqG0+lEmqbsdjviOGY0GrXrZo/WGt+e5UEQMJ/PeXx85Pn5mfV6TRRFhGFIEATtmBG6aK2pqorj8UiSJLy/v6OUomkayrK8vdPX6zUvLy+sVisWiwWTyURGzBmapqGqKvI8J45jwjBEa02e5+2IKcvy306H/kyfz+dEUcRqteLp6Ynlcsl0OhXpZzDSsyxjNpvRNA37/Z7tdst2u22nhBnPg6cX82O6WCxYLpfc39935rrQxYyX6XQKwH6/Z7lcMp/PW2/2aO6c003Hj8djgiBgMpmglEIpxXQ6FelnMNIB8jwnDEPu7u5QShEEQe8Q4n9/gBFvvwC7RHofc/42zer7flv2WDH0pBvMxqES+pgmtctuYBs5A/4BrjWoSHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASP8D2GlGQ5zNBrBvvPaQvx07LsouO0LKpifd3mjCwEyBJNYNYaJHTFJdVVVtGZeDEYH22zI3n04niqKgKAoAiR45g5GeZRl5nrefRVFQliV1XXfEdzrdxCKZmLv9fk+SJAASJ3UBO07q8/OTOI5JkoTD4UBRFJ1sRvhHuulwI/xwOBDHMW9vbwB8fX1JcNoFvgenvb6+8vHxQZIk5HneCU1rg9OM9LIsybKMOI7ZbDYAJEkiEYFXGIoI3Gw2xHFMmqYd6QC+1hrP81rph8OB7XaL1po0TSUM8wqXwjB3ux15nlNVVf+H9HunAxRFQZIkEvt6A5diX+2ZbsS3Ud52NqMEHP8atwQc26eXjnSQKO/f5VeivCW0/n/mltD6nvR2QWT/Jy79ZfIDbR7YvKqk0OoAAAAASUVORK5CYII="
+                 transform="matrix(1,0,0,-1,0,1)"
+                 height="1"
+                 width="1" /></g></g></g></g></mask><clipPath
+       id="clipPath3524-3"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3526-7"
+         d="m 667,561 93,0 0,-68 -93,0 0,68 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3520-9"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3522-1"
+         d="m 667,561 93,0 0,-68 -93,0 0,68 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3498-7"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3500-1"
+         d="m 560,628 270,0 0,-182 -270,0 0,182 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3490-4"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3492-5"
+         d="m 0,1080 1920,0 L 1920,0 0,0 0,1080 z"
+         inkscape:connector-curvature="0" /></clipPath><mask
+       id="mask3476-8"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3478-3"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABHcAAAK/CAAAAADGr34kAAAAAXNCSVQI5gpbmQAACLFJREFUeJzt1DEBACAMwDDAv+fhohwkCnp1zwJIndcBwHd8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4DaBSkuBn0AocgUAAAAAElFTkSuQmCC"
+         height="1"
+         width="1" /></mask><clipPath
+       id="clipPath3470-9"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3472-6"
+         d="m 538,215 954,0 0,118 -954,0 0,-118 z"
+         inkscape:connector-curvature="0" /></clipPath><mask
+       id="mask3460-8"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3462-0"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABHcAAAK/CAAAAADGr34kAAAAAXNCSVQI5gpbmQAACLFJREFUeJzt1DEBACAMwDDAv+fhohwkCnp1zwJIndcBwHd8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4Ca7wA13wFqvgPUfAeo+Q5Q8x2g5jtAzXeAmu8ANd8Bar4D1HwHqPkOUPMdoOY7QM13gJrvADXfAWq+A9R8B6j5DlDzHaDmO0DNd4DaBSkuBn0AocgUAAAAAElFTkSuQmCC"
+         height="1"
+         width="1" /></mask><clipPath
+       id="clipPath3454-4"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3456-3"
+         d="m 554,720 958,0 0,204 -958,0 0,-204 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3432-5"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3434-1"
+         d="m 904,587 32,0 0,12 -32,0 0,-12 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3428-5"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3430-0"
+         d="m 904,599 32,0 0,-12.002 -32,0 0,12.002 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3420-8"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3422-5"
+         d="m 0,1080 1920,0 L 1920,0 0,0 0,1080 z"
+         inkscape:connector-curvature="0" /></clipPath><mask
+       id="mask3396-6"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3398-2"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFwAAACdCAAAAAAcMECVAAAAAXNCSVQI5gpbmQAAAZdJREFUaIHt27tu20AQheEzy6Vo0BKMKCkMJ03e/70MFzYR3YisljsnBQXETZpg1J0pt/gwGGz7GwAAhtjhX9UMFsmTIFfckFJKKWx7wt3dQWQAKfd9n6N0wpda6+JAhqU8jI+PQ05BuC/lcpmxODMs9eP+6343dCF3J1s5TR9wJ7Mh9dtvP172Y58CbMDrPL3atdRmt81ffj7vNiF3oV9Pb5h/HZNxvfl2//z96SEI/33AYTvkZLffMoy7py9DF4K3guM45AQgA2ap6zfD8BCEY9j0XTIDMgBYstR1XQyOrku2XjivT7ZOAI5PUMz3+8cIFy5cuHDhwoULFy5cuHDhwoULFy5cuHDhwoULFy5cuHDhwoULFy5cuHDhwoULFy5cuHDhwv97bkEBSZIR4GcpAwCd3loLaX7YWnM6bzjprV5LQVQhUq61Oblu7kuZTwfEtS2nuSwOIIO+lPP0hmNglTOdy+JEBr3O0ysOoT3RNFcnMs3r+Z2X4BLqXB1cN0c5RDdc1QkD7E71Ge/bzd27+APu1Sr+ATqP3j0zgxPtAAAAAElFTkSuQmCC"
+         height="1"
+         width="1" /></mask><mask
+       id="mask3384-8"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><g
+         id="g3386-8"><g
+           id="g3388-5"
+           clip-path="url(#clipPath3380-6)"><g
+             id="g3390-8"><g
+               id="g3392-8"
+               transform="matrix(92,0,0,157,888,469)"><image
+                 id="image3394-9"
+                 xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFwAAACdCAYAAAA5Wx9JAAAABHNCSVQICAgIfAhkiAAABIZJREFUeJzt111rs0gYxvHL92AipbYHIe1Jv//3CjlopMYXMmqcPdgdH03s7lOWvWDh+sPQUDWUX4c7Ew+AxUqe5639Wv1m1q6ywsMduOd5E/b8tfq9rLUT9vy1K3QvHKzv+w9rfl2t52DHcXxY8+vh/CHf9xGGIaIomlYYhkL/h+bYwzCg7/tpDcMwoQN/gXueN2EnSYI0TbHdbrHdbpEkyYQu8PWstRO2MQZN06BpGrRtCwATurV2CR5FEdI0RZ7neHl5QZ7nyLIMSZIgCALN9JXcnL7dbjDGoKoqFEWB8/kM4NeIcfeF89kdRRF2ux1eX1/x/v6Ow+GAPM+RpimiKJpGi1o2jiP6vkfbtiiKAsfjEZ7noes6GGPQ9z1utxs8z/t+hx8OB3x8fGC/3yPLMsRxrLGykhsnXdehqiqcTicAQNu2+Pr6wuVymdweRoqb4bvdDnmeY7/f4+3tDU9PT9hsNgJfyYFfr1eUZQkAKMsSu91u9fNv9ZTiPjizLMPT0xOen58Xc1z9aj6/AeByuSBN0wX2vMU53O30IAgQRRHiOEaSJEiSBJvNRuArOXAASJIEcRwjiiIEQTDt7LlZeP8GDn2OP18CX+bO4M5nbrdm9QDucv+ZtaWW/cRI5zxyAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInJ3ByAicncHICJydwcgInF353wVq7utSynzo9gFtrMY7j9PN2u00LADzP++/++v9h1tqF0dxuDT6cPzhH7vseXdfBGANjDAAgCAKB3+XAnVPXdej7foE/h1/s8HEcMQwDjDFo2xZVVaEsSwDAZrOB7/sCv8tt0uv1irIsUVUV2raFMQbDMGAcx8X94fwhh13XNYqiwOl0AgBcLhfEcSzwlZxd13Woqgqn0wlFUaCu6wW62+UL8L7v0bYtiqLA8XgEAJRliTRNEUURfF+HmrXW7IqiQNu26Pt+CW6thed500N1XePz8xPWWjRNgyzLkCTJNL+1w5e5Ge3meFVVKIoC5/MZdV1P4O7e1R0OAMYYlGWJJEkQhqHGyd90P5KbpkHTNKs73ANggT+Pe77vIwxDRFE0LYft7lGPOUyH3vf9tO5n+AIcAHzff1jz62q9Ofr9ml+fwF3zOa2Z/fPm5+61b50P4NMFQf+rvvt6/we8Kp4iURf8WgAAAABJRU5ErkJggg=="
+                 transform="matrix(1,0,0,-1,0,1)"
+                 height="1"
+                 width="1" /></g></g></g></g></mask><clipPath
+       id="clipPath3380-6"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3382-6"
+         d="m 888,626 92,0 0,-157 -92,0 0,157 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3376-1"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3378-8"
+         d="m 888,626 92,0 0,-157 -92,0 0,157 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3354-1"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3356-9"
+         d="m 1116,527 26.006,0 0,3 -26.006,0 0,-3 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3350-2"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3352-7"
+         d="m 1116,530 26.01,0 0,-3 -26.01,0 0,3 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3328-2"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3330-1"
+         d="m 1057.994,527 11.006,0 0,3 -11.006,0 0,-3 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3324-6"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3326-2"
+         d="m 1057.99,530 26,0 0,-3 -26,0 0,3 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3302-2"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3304-7"
+         d="m 1000,527 26.006,0 0,3 -26.006,0 0,-3 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3298-9"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3300-4"
+         d="m 1000,530 26.01,0 0,-3 -26.01,0 0,3 z"
+         inkscape:connector-curvature="0" /></clipPath><mask
+       id="mask3272-6"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3274-5"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD4AAABUCAAAAAD/xdukAAAAAXNCSVQI5gpbmQAAAZZJREFUWIXt2L1u3DAQBOBZijoZsg9GLikMO03e/72MK85CLvrxUeTuuJCCJB0lA6m4tT4tl6x2BAAAwdbiHycC2fYDEuTCBc455zacgDAzMxAegPN1Xft8T5jGOKuBHuJ8097fN95lc9MwjdMtKTzE1e3p6+nYVJnzkxbGn28dafACVz98+/58amuX2z29X8+1zlF17f784+l4yD29xenSxKF/j7LM/nB6enm8y+bzeLhd2kMl68037fHxS1Nlzm6zn9rGOxF4QMRV9aFp7rK5C96B5PLuECeuqqpcLk6oKamtHJClsjgAWNKkBHMf69/+NFMzErs4uBR2coAksJ+vVXjhhRdeeOGFF1544YUXXvh/5usO+3srzKm/v/UAQKOpamZ0QlU1GldOmsY5BOQu4BrCHNXIpbulMPVX5IYPtNu1n0IyAB60FIbujF+50Qdt7s/dEJIRHrQ4da+45gcvFqfutZuiEZ5icbhw3BL7aOi7tyEauHRHuG4KnVIYxykaIYDsiLxSjDGt/BOB2+fjPmB/2PgBJp8FYb3sImYAAAAASUVORK5CYII="
+         height="1"
+         width="1" /></mask><mask
+       id="mask3260-5"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><g
+         id="g3262-2"><g
+           id="g3264-6"
+           clip-path="url(#clipPath3256-0)"><g
+             id="g3266-6"><g
+               id="g3268-0"
+               transform="matrix(62,0,0,84,1107,495)"><image
+                 id="image3270-6"
+                 xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD4AAABUCAYAAADaroR4AAAABHNCSVQICAgIfAhkiAAAA1pJREFUeJztnMtuqzoYRheES0QSRaUdRGknff/3qjJIUCmXYIzhDI6MTC5765wR1F6SFQvHESvmByb+PGDgAZ7nPTq8OIbhoR4eN+Ke543SZn9pDMMwSpt9TaA7WtD3/btmjs8dLdj3/V0zxwNzku/7BEFAGIZjC4JgMfKmtFIKKSVSStq2RSk1kQ/gXyEtHccxSZKw2WzYbDbEcTzKL0FcSwshqOuaqqqo65qmaei6DqUUwFQ8DEOSJCFNU15fX0nTlN1uRxzHrFarWde8ruO+7xFCUFUV39/fXC4XsiybjAMEZm2HYch2u+Xt7Y2Pjw+OxyNpmpIkCWEYjpf8XBmGga7ruF6v5HnO6XQiDEOUUrRti5QSpRRKqecrfjwe+fz85HA4sNvtiKJo9pd73/dIKanrmvP5TBzHSCkpy5KiKLher0gp8TzvcY1vt1vSNOVwOPD+/s5+v2e9Xi9CvG1bqqoiiiKapuF8PpMkCVEUjeUKT+7q+ga32+3Y7/e8vLxM6nyO6Ppt25YgCKjrmiRJ7m7Od+L6oO/7rFYrwjAkiiLiOCaOY9br9SLEfd9HCDF5DOsbm/kiE9z+gJY3/wSzzVncPPdhGFBK0XXd+Bjr+/65uEZfAY/aEuj7fhTWn+Yr7LyfT/8D83mtX2Z037zUf5043Nf0bX3DLxXXPBLW/GrxP+HEbcOJ24YTtw0nbhtO3DacuG04cdtw4rbhxG3DiduGE7cNJ24bTtw2nLhtOHHbcOK24cRtw4nbhhO3DSduG07cNpy4bThx23DituHEbcOJ24YTtw1rxZ/uLf3bTr258V/P905c78s0gyZ0g/kmg+jdw7qZDo/+gMCcaMrqGBEhBEIIgNlvo9ZpIEKISSbE7YZauFlxvfVYR4kURUGe5wCzj0rQi9Y0DXmeUxQFdV0jhKDrujENRBOYk7R0WZZkWcbpdALg5+dn9uEYZlRCURScTieyLKMsy4n8ZOO8nqQTNbIs4+vrC4A8zxcTh/LIIcsy6rpGSjkV1xEDelJZlpzPZ4ZhoKqqxQXg6DovioIsy7hcLpRlOYrr7z5ccQAhBHmeLzLySJdsVVVj5NHtio+xZmYWzG8Iueq6bgy5klLe1fhEHOyJNbM2yO5OfBxYqPAtz15b/wHsvBSUT5t0gwAAAABJRU5ErkJggg=="
+                 transform="matrix(1,0,0,-1,0,1)"
+                 height="1"
+                 width="1" /></g></g></g></g></mask><clipPath
+       id="clipPath3256-0"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3258-5"
+         d="m 1107,579 62,0 0,-84 -62,0 0,84 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3252-1"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3254-3"
+         d="m 1107,579 62,0 0,-84 -62,0 0,84 z"
+         inkscape:connector-curvature="0" /></clipPath><mask
+       id="mask3226-6"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3228-8"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD4AAABUCAAAAAD/xdukAAAAAXNCSVQI5gpbmQAAAZZJREFUWIXt2L1u3DAQBOBZijoZsg9GLikMO03e/72MK85CLvrxUeTuuJCCJB0lA6m4tT4tl6x2BAAAwdbiHycC2fYDEuTCBc455zacgDAzMxAegPN1Xft8T5jGOKuBHuJ8097fN95lc9MwjdMtKTzE1e3p6+nYVJnzkxbGn28dafACVz98+/58amuX2z29X8+1zlF17f784+l4yD29xenSxKF/j7LM/nB6enm8y+bzeLhd2kMl68037fHxS1Nlzm6zn9rGOxF4QMRV9aFp7rK5C96B5PLuECeuqqpcLk6oKamtHJClsjgAWNKkBHMf69/+NFMzErs4uBR2coAksJ+vVXjhhRdeeOGFF1544YUXXvh/5usO+3srzKm/v/UAQKOpamZ0QlU1GldOmsY5BOQu4BrCHNXIpbulMPVX5IYPtNu1n0IyAB60FIbujF+50Qdt7s/dEJIRHrQ4da+45gcvFqfutZuiEZ5icbhw3BL7aOi7tyEauHRHuG4KnVIYxykaIYDsiLxSjDGt/BOB2+fjPmB/2PgBJp8FYb3sImYAAAAASUVORK5CYII="
+         height="1"
+         width="1" /></mask><mask
+       id="mask3214-5"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><g
+         id="g3216-2"><g
+           id="g3218-9"
+           clip-path="url(#clipPath3210-9)"><g
+             id="g3220-8"><g
+               id="g3222-2"
+               transform="matrix(62,0,0,84,1049,495)"><image
+                 id="image3224-4"
+                 xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD4AAABUCAYAAADaroR4AAAABHNCSVQICAgIfAhkiAAAA1pJREFUeJztnMtuqzoYRheES0QSRaUdRGknff/3qjJIUCmXYIzhDI6MTC5765wR1F6SFQvHESvmByb+PGDgAZ7nPTq8OIbhoR4eN+Ke543SZn9pDMMwSpt9TaA7WtD3/btmjs8dLdj3/V0zxwNzku/7BEFAGIZjC4JgMfKmtFIKKSVSStq2RSk1kQ/gXyEtHccxSZKw2WzYbDbEcTzKL0FcSwshqOuaqqqo65qmaei6DqUUwFQ8DEOSJCFNU15fX0nTlN1uRxzHrFarWde8ruO+7xFCUFUV39/fXC4XsiybjAMEZm2HYch2u+Xt7Y2Pjw+OxyNpmpIkCWEYjpf8XBmGga7ruF6v5HnO6XQiDEOUUrRti5QSpRRKqecrfjwe+fz85HA4sNvtiKJo9pd73/dIKanrmvP5TBzHSCkpy5KiKLher0gp8TzvcY1vt1vSNOVwOPD+/s5+v2e9Xi9CvG1bqqoiiiKapuF8PpMkCVEUjeUKT+7q+ga32+3Y7/e8vLxM6nyO6Ppt25YgCKjrmiRJ7m7Od+L6oO/7rFYrwjAkiiLiOCaOY9br9SLEfd9HCDF5DOsbm/kiE9z+gJY3/wSzzVncPPdhGFBK0XXd+Bjr+/65uEZfAY/aEuj7fhTWn+Yr7LyfT/8D83mtX2Z037zUf5043Nf0bX3DLxXXPBLW/GrxP+HEbcOJ24YTtw0nbhtO3DacuG04cdtw4rbhxG3DiduGE7cNJ24bTtw2nLhtOHHbcOK24cRtw4nbhhO3DSduG07cNpy4bThx23DituHEbcOJ24YTtw1rxZ/uLf3bTr258V/P905c78s0gyZ0g/kmg+jdw7qZDo/+gMCcaMrqGBEhBEIIgNlvo9ZpIEKISSbE7YZauFlxvfVYR4kURUGe5wCzj0rQi9Y0DXmeUxQFdV0jhKDrujENRBOYk7R0WZZkWcbpdALg5+dn9uEYZlRCURScTieyLKMsy4n8ZOO8nqQTNbIs4+vrC4A8zxcTh/LIIcsy6rpGSjkV1xEDelJZlpzPZ4ZhoKqqxQXg6DovioIsy7hcLpRlOYrr7z5ccQAhBHmeLzLySJdsVVVj5NHtio+xZmYWzG8Iueq6bgy5klLe1fhEHOyJNbM2yO5OfBxYqPAtz15b/wHsvBSUT5t0gwAAAABJRU5ErkJggg=="
+                 transform="matrix(1,0,0,-1,0,1)"
+                 height="1"
+                 width="1" /></g></g></g></g></mask><clipPath
+       id="clipPath3210-9"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3212-3"
+         d="m 1049,579 62,0 0,-84 -62,0 0,84 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3206-7"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3208-1"
+         d="m 1049,579 62,0 0,-84 -62,0 0,84 z"
+         inkscape:connector-curvature="0" /></clipPath><mask
+       id="mask3180-7"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3182-1"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD4AAABUCAAAAAD/xdukAAAAAXNCSVQI5gpbmQAAAZZJREFUWIXt2L1u3DAQBOBZijoZsg9GLikMO03e/72MK85CLvrxUeTuuJCCJB0lA6m4tT4tl6x2BAAAwdbiHycC2fYDEuTCBc455zacgDAzMxAegPN1Xft8T5jGOKuBHuJ8097fN95lc9MwjdMtKTzE1e3p6+nYVJnzkxbGn28dafACVz98+/58amuX2z29X8+1zlF17f784+l4yD29xenSxKF/j7LM/nB6enm8y+bzeLhd2kMl68037fHxS1Nlzm6zn9rGOxF4QMRV9aFp7rK5C96B5PLuECeuqqpcLk6oKamtHJClsjgAWNKkBHMf69/+NFMzErs4uBR2coAksJ+vVXjhhRdeeOGFF1544YUXXvh/5usO+3srzKm/v/UAQKOpamZ0QlU1GldOmsY5BOQu4BrCHNXIpbulMPVX5IYPtNu1n0IyAB60FIbujF+50Qdt7s/dEJIRHrQ4da+45gcvFqfutZuiEZ5icbhw3BL7aOi7tyEauHRHuG4KnVIYxykaIYDsiLxSjDGt/BOB2+fjPmB/2PgBJp8FYb3sImYAAAAASUVORK5CYII="
+         height="1"
+         width="1" /></mask><mask
+       id="mask3168-6"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><g
+         id="g3170-1"><g
+           id="g3172-4"
+           clip-path="url(#clipPath3164-3)"><g
+             id="g3174-6"><g
+               id="g3176-0"
+               transform="matrix(62,0,0,84,991,495)"><image
+                 id="image3178-0"
+                 xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD4AAABUCAYAAADaroR4AAAABHNCSVQICAgIfAhkiAAAA1pJREFUeJztnMtuqzoYRheES0QSRaUdRGknff/3qjJIUCmXYIzhDI6MTC5765wR1F6SFQvHESvmByb+PGDgAZ7nPTq8OIbhoR4eN+Ke543SZn9pDMMwSpt9TaA7WtD3/btmjs8dLdj3/V0zxwNzku/7BEFAGIZjC4JgMfKmtFIKKSVSStq2RSk1kQ/gXyEtHccxSZKw2WzYbDbEcTzKL0FcSwshqOuaqqqo65qmaei6DqUUwFQ8DEOSJCFNU15fX0nTlN1uRxzHrFarWde8ruO+7xFCUFUV39/fXC4XsiybjAMEZm2HYch2u+Xt7Y2Pjw+OxyNpmpIkCWEYjpf8XBmGga7ruF6v5HnO6XQiDEOUUrRti5QSpRRKqecrfjwe+fz85HA4sNvtiKJo9pd73/dIKanrmvP5TBzHSCkpy5KiKLher0gp8TzvcY1vt1vSNOVwOPD+/s5+v2e9Xi9CvG1bqqoiiiKapuF8PpMkCVEUjeUKT+7q+ga32+3Y7/e8vLxM6nyO6Ppt25YgCKjrmiRJ7m7Od+L6oO/7rFYrwjAkiiLiOCaOY9br9SLEfd9HCDF5DOsbm/kiE9z+gJY3/wSzzVncPPdhGFBK0XXd+Bjr+/65uEZfAY/aEuj7fhTWn+Yr7LyfT/8D83mtX2Z037zUf5043Nf0bX3DLxXXPBLW/GrxP+HEbcOJ24YTtw0nbhtO3DacuG04cdtw4rbhxG3DiduGE7cNJ24bTtw2nLhtOHHbcOK24cRtw4nbhhO3DSduG07cNpy4bThx23DituHEbcOJ24YTtw1rxZ/uLf3bTr258V/P905c78s0gyZ0g/kmg+jdw7qZDo/+gMCcaMrqGBEhBEIIgNlvo9ZpIEKISSbE7YZauFlxvfVYR4kURUGe5wCzj0rQi9Y0DXmeUxQFdV0jhKDrujENRBOYk7R0WZZkWcbpdALg5+dn9uEYZlRCURScTieyLKMsy4n8ZOO8nqQTNbIs4+vrC4A8zxcTh/LIIcsy6rpGSjkV1xEDelJZlpzPZ4ZhoKqqxQXg6DovioIsy7hcLpRlOYrr7z5ccQAhBHmeLzLySJdsVVVj5NHtio+xZmYWzG8Iueq6bgy5klLe1fhEHOyJNbM2yO5OfBxYqPAtz15b/wHsvBSUT5t0gwAAAABJRU5ErkJggg=="
+                 transform="matrix(1,0,0,-1,0,1)"
+                 height="1"
+                 width="1" /></g></g></g></g></mask><clipPath
+       id="clipPath3164-3"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3166-1"
+         d="m 991,579 62,0 0,-84 -62,0 0,84 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3160-9"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3162-3"
+         d="m 991,579 62,0 0,-84 -62,0 0,84 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3152-4"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3154-4"
+         d="m 897,482 239.999,0 0,135 -239.999,0 0,-135 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3126-1"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3128-0"
+         d="m 887,628 270,0 0,-182 -270,0 0,182 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3118-8"
+       clipPathUnits="userSpaceOnUse"><path
+         id="path3120-5"
+         d="m 0,1080 1920,0 L 1920,0 0,0 0,1080 z"
+         inkscape:connector-curvature="0" /></clipPath><clipPath
+       id="clipPath3722-1-6"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3724-4-6"
+         d="m 652,532 12.002,0 0,-12 -12.002,0 0,12 z" /></clipPath><clipPath
+       id="clipPath3726-6-9"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3728-1-7"
+         d="m 652.002,520.002 12,0 0,11.998 -12,0 0,-11.998 z" /></clipPath><clipPath
+       id="clipPath3696-9-7"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3698-6-3"
+         d="m 592,530.865 32,0 0,-12.002 -32,0 0,12.002 z" /></clipPath><clipPath
+       id="clipPath3700-1-1"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3702-8-2"
+         d="m 592,518.865 32,0 0,12 -32,0 0,-12 z" /></clipPath><clipPath
+       id="clipPath3696-9-7-9"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3698-6-3-5"
+         d="m 592,530.865 32,0 0,-12.002 -32,0 0,12.002 z" /></clipPath><clipPath
+       id="clipPath3700-1-1-8"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3702-8-2-6"
+         d="m 592,518.865 32,0 0,12 -32,0 0,-12 z" /></clipPath><clipPath
+       id="clipPath3722-1-6-1"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3724-4-6-5"
+         d="m 652,532 12.002,0 0,-12 -12.002,0 0,12 z" /></clipPath><clipPath
+       id="clipPath3726-6-9-4"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3728-1-7-6"
+         d="m 652.002,520.002 12,0 0,11.998 -12,0 0,-11.998 z" /></clipPath><clipPath
+       id="clipPath3086-4-0"><path
+         inkscape:connector-curvature="0"
+         d="m 1058,722 374,0 0,-374 -374,0 0,374 z"
+         id="path3088-8-7" /></clipPath><clipPath
+       id="clipPath3100-8-2"><path
+         inkscape:connector-curvature="0"
+         d="m 1029,344 432,0 0,-32 -432,0 0,32 z"
+         id="path3102-2-9" /></clipPath><clipPath
+       id="clipPath3116-4-9"><path
+         inkscape:connector-curvature="0"
+         d="m 1029,756 432,0 0,-32 -432,0 0,32 z"
+         id="path3118-5-1" /></clipPath><clipPath
+       id="clipPath3592-5-68"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3594-9-1"
+         d="m 730.778,549 12,0 0,-12 -12,0 0,12 z" /></clipPath><clipPath
+       id="clipPath3566-8-9"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3568-8-22"
+         d="m 679,547.865 32,0 0,-12.002 -32,0 0,12.002 z" /></clipPath><clipPath
+       id="clipPath3570-6-4"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3572-0-00"
+         d="m 679,535.865 32,0 0,12 -32,0 0,-12 z" /></clipPath><clipPath
+       id="clipPath3520-6-4"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3522-3-32"
+         d="m 667,561 93,0 0,-68 -93,0 0,68 z" /></clipPath><mask
+       id="mask3528-3-5"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><g
+         id="g3530-7-3"><g
+           id="g3532-3-5"
+           clip-path="url(#clipPath3524-5-2)"><g
+             id="g3534-0-0"><g
+               id="g3536-4-5"
+               transform="matrix(93,0,0,68,667,493)"><image
+                 id="image3538-4-00"
+                 xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF0AAABECAYAAADjqDmQAAAABHNCSVQICAgIfAhkiAAAA51JREFUeJztnEtv4koQRo/BpokBoThZIJJN/v/vCkoUYuSAbYwfPYu57duOzWPm3lEvpo5UwqLbXhyXihaLzwM0A3ieN/S1cCNaD2oFwOObdM/zWuH2tXAbWutWuH1t45sLI3c0GvXKXheGMXKbpumVvQ6WdPgp3Pd9giBoy/d9EX8FW3hd15RlSVmWnE4n6rruiffhp0wjXClFGIbMZjNmsxlKqVa8SB9Ga90KL4qCLMvIsow0TTkej1RVRV3X7f6O9CAICMOQKIp4eHggiiIWiwVKKcbjscz4AczcbpqG0+lEmqbsdjviOGY0GrXrZo/WGt+e5UEQMJ/PeXx85Pn5mfV6TRRFhGFIEATtmBG6aK2pqorj8UiSJLy/v6OUomkayrK8vdPX6zUvLy+sVisWiwWTyURGzBmapqGqKvI8J45jwjBEa02e5+2IKcvy306H/kyfz+dEUcRqteLp6Ynlcsl0OhXpZzDSsyxjNpvRNA37/Z7tdst2u22nhBnPg6cX82O6WCxYLpfc39935rrQxYyX6XQKwH6/Z7lcMp/PW2/2aO6c003Hj8djgiBgMpmglEIpxXQ6FelnMNIB8jwnDEPu7u5QShEEQe8Q4n9/gBFvvwC7RHofc/42zer7flv2WDH0pBvMxqES+pgmtctuYBs5A/4BrjWoSHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASHeASP8D2GlGQ5zNBrBvvPaQvx07LsouO0LKpifd3mjCwEyBJNYNYaJHTFJdVVVtGZeDEYH22zI3n04niqKgKAoAiR45g5GeZRl5nrefRVFQliV1XXfEdzrdxCKZmLv9fk+SJAASJ3UBO07q8/OTOI5JkoTD4UBRFJ1sRvhHuulwI/xwOBDHMW9vbwB8fX1JcNoFvgenvb6+8vHxQZIk5HneCU1rg9OM9LIsybKMOI7ZbDYAJEkiEYFXGIoI3Gw2xHFMmqYd6QC+1hrP81rph8OB7XaL1po0TSUM8wqXwjB3ux15nlNVVf+H9HunAxRFQZIkEvt6A5diX+2ZbsS3Ud52NqMEHP8atwQc26eXjnSQKO/f5VeivCW0/n/mltD6nvR2QWT/Jy79ZfIDbR7YvKqk0OoAAAAASUVORK5CYII="
+                 transform="matrix(1,0,0,-1,0,1)"
+                 height="1"
+                 width="1" /></g></g></g></g></mask><clipPath
+       id="clipPath3524-5-2"
+       clipPathUnits="userSpaceOnUse"><path
+         inkscape:connector-curvature="0"
+         id="path3526-4-1"
+         d="m 667,561 93,0 0,-68 -93,0 0,68 z" /></clipPath><mask
+       id="mask3540-4-88"
+       height="1"
+       width="1"
+       y="0"
+       x="0"
+       maskUnits="userSpaceOnUse"><image
+         id="image3542-1-5"
+         xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF0AAABECAAAAADGw2ZMAAAAAXNCSVQI5gpbmQAAAZJJREFUWIXt2DFv2zAQhuHvTlTkyDaMuBmCtEv//+9q0KKuAtWWZJnkfR0UAwY69jyVXAhoeEQcyOUVAAAEvos3rAjE0ydBfugCVVV1Oz9hZmYgEABoqOs6ePGE5Rgv2UAEiIamXa+boE665Xkch3PKQIBo3e4/7bdN5TJ70i7De6ckjUGg9eb5y+u+rdUBB5jO/Y/G4s3ZX7++bB98RmNp6lpOwzkal7lv9i+fdysvfVzb8XCoVWS5M0273T01lYvOtMJxt2kqBQIgolX90DQrLx1T+9jUlQgCAIiKVlXlpKOqQwgqsrwmALIsDx2iqioqAHxu4V8/+DjoffTrKnrRi170ohe96EUvetGLXvSiF/3/0bkkvWsnIHn98u+ymRmNV51Gyzn7RD2mHFNKxqUYkpbjZZ7h1WfGaZzmmEkEAJbm8djDr1z96vrTnA0IoKX51H3Hb8fq9u1nP0UjA2hx7N7QuxbDt26IRgSKxdOBg3PtfJ8Sl8nEEXPvXWrnbIQAcqfKTN65kN+97t9sfv6y/QG64fFP78GtbgAAAABJRU5ErkJggg=="
+         height="1"
+         width="1" /></mask></defs><g
+     inkscape:groupmode="layer"
+     id="layer8"
+     inkscape:label="Layer5"
+     transform="translate(436.0495,72.4457)"><g
+       style="display:inline"
+       id="g3508-5-64"
+       transform="matrix(5.09,0,0,-5.09,-201.82504,927.02677)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><path
+         inkscape:connector-curvature="0"
+         d="m 0,0 c -2.209,0 -4,1.791 -4,4 l 0,92 c 0,2.209 1.791,4 4,4 l 92,0 c 2.209,0 4,-1.791 4,-4 L 96,4 C 96,1.791 94.209,0 92,0 L 0,0 z"
+         style="fill:#4fbdee;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path3510-0-3" /></g><g
+       style="display:inline"
+       id="g3516-7-0"
+       transform="matrix(5.09,0,0,-5.09,-3586.6755,3426.2166)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><g
+         id="g3518-2-5" /><g
+         id="g3544-9-2"><g
+           style="opacity:0.119995"
+           clip-path="url(#clipPath3520-6-4)"
+           id="g3546-7-5"><g
+             id="g3548-8-3"><g
+               id="g3550-3-8" /><g
+               mask="url(#mask3528-3-5)"
+               id="g3552-8-72"><g
+                 transform="matrix(93,0,0,68,667,493)"
+                 id="g3554-9-8"><image
+                   width="1"
+                   height="1"
+                   transform="matrix(1,0,0,-1,0,1)"
+                   xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF0AAABECAYAAADjqDmQAAAABHNCSVQICAgIfAhkiAAAAP1JREFUeJzt3DGKhEAARcFWvP+VeyNBxJGFHX3BVmU2BvL4DBP1Muec48KyLFfH/NKHrGOMMbbzgdjfsXe8ir+dX+K7ruKv1cf8N8dRr+cDnmfpL9rHvVr5+yw9sIwxPv+h5BGWHhA9IHpA9IDoAdEDogdED4geED0gekD0gOgB0QOiB0QPiB4QPSB6QPSA6AHRA6IHRA+IHhA9IHpA9IDoAdEDogdED4geED0gekD0gOgB0QOiB0QPiB4QPSB6QPSA6AHRA6IHRA+IHhA9IHpA9JfNOUUvrHe3H/MMS3/RPvD1+MA7LP0lx2Fv50N3737X7aX155fE/5u7n+wfv04ph+lQnM8AAAAASUVORK5CYII="
+                   mask="url(#mask3540-4-88)"
+                   id="image3556-9-3" /></g></g></g></g></g></g><g
+       style="display:inline"
+       id="g3558-6-1"
+       transform="matrix(5.09,0,0,-5.09,235.91496,860.85677)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><path
+         inkscape:connector-curvature="0"
+         d="m 0,0 c 0,-1.65 -1.35,-3 -3,-3 l -74,0 c -1.649,0 -3,1.35 -3,3 l 0,50 c 0,1.65 1.351,3 3,3 l 74,0 c 1.65,0 3,-1.35 3,-3 L 0,0 z"
+         style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path3560-5-6" /></g><g
+       style="display:inline"
+       id="g3562-4-0"
+       transform="matrix(5.09,0,0,-5.09,-3586.6755,3426.2166)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><g
+         id="g3564-6-3" /><g
+         id="g3574-7-9"><g
+           style="opacity:0.5"
+           clip-path="url(#clipPath3566-8-9)"
+           id="g3576-7-8"><g
+             id="g3578-2-9"><g
+               clip-path="url(#clipPath3570-6-4)"
+               id="g3580-1-9"><path
+                 inkscape:connector-curvature="0"
+                 d="m 710.994,535.863 -31.988,0 0,12.002 31.988,0 0,-12.002 z"
+                 style="fill:#6d6e71;fill-opacity:1;fill-rule:nonzero;stroke:none"
+                 id="path3582-0-16" /></g></g></g></g></g><path
+       inkscape:connector-curvature="0"
+       d="m 123.93496,748.87677 -254.5,0 0,-25.45 254.5,0 0,25.45 z"
+       style="fill:#d1d2d3;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+       id="path3584-1-9"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999" /><path
+       inkscape:connector-curvature="0"
+       d="m 6.8649591,799.77677 -137.4299991,0 0,-25.45 137.4299991,0 0,25.45 z"
+       style="fill:#d1d2d3;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+       id="path3586-5-0"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999" /><g
+       style="display:inline"
+       id="g3588-5-0"
+       transform="matrix(5.09,0,0,-5.09,-3586.6755,3426.2166)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><g
+         id="g3590-3-9" /><g
+         id="g3596-7-2"><g
+           style="opacity:0"
+           clip-path="url(#clipPath3592-5-68)"
+           id="g3598-6-5"><path
+             inkscape:connector-curvature="0"
+             d="m 730.777,537 12,0 0,12 -12,0 0,-12 z"
+             style="fill:#03a9f4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+             id="path3600-8-1" /></g></g></g><g
+       style="display:inline"
+       id="g3602-7-0"
+       transform="matrix(5.09,0,0,-5.09,188.97176,661.07427)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><path
+         inkscape:connector-curvature="0"
+         d="m 0,0 c 0,0.414 -0.336,0.75 -0.75,0.75 l -2.75,0 -2.5,4 -1,0 1.25,-4 -2.75,0 -0.75,1 -0.75,0 0.5,-1.75 -0.5,-1.75 0.75,0 0.75,1 2.75,0 -1.25,-4 1,0 2.5,4 2.75,0 C -0.336,-0.75 0,-0.414 0,0"
+         style="fill:#00c853;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path3604-3-8" /></g><g
+       transform="matrix(1.25,0,0,-1.25,-1884.887,1349.9021)"
+       id="g3012-8"
+       style="display:inline"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><g
+         transform="translate(1677.8121,922.30928)"
+         id="g3072-5"
+         style="fill:#333333;fill-opacity:1"><path
+           inkscape:connector-curvature="0"
+           d="m 0,0 -285.486,0 -14,-190.491 313.486,0 L 0,0 z"
+           id="path3074-5"
+           style="fill:#101010;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g><g
+         transform="translate(1691.8121,352.84148)"
+         id="g3076-9"
+         style="fill:#333333;fill-opacity:1"><path
+           inkscape:connector-curvature="0"
+           d="m 0,0 -313.486,0 14,-190.491 286.486,0 L 0,0 z"
+           id="path3078-3"
+           style="fill:#101010;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g><path
+         inkscape:connector-curvature="0"
+         d="m 1721.07,355.32978 -374,0 0,374 374,0 0,-374 z m 3.332,409 -378.666,0 c -14.729,0 -26.666,-11.938 -26.666,-26.667 l 0,-5.333 0,-380 0,-5.334 c 0,-14.727 11.937,-26.666 26.666,-26.666 l 378.666,0 c 14.729,0 26.668,11.939 26.668,26.666 l 0,5.334 0,380 0,5.333 c 0,14.729 -11.939,26.667 -26.668,26.667"
+         id="path3080-4"
+         style="fill:#101010;fill-opacity:1;fill-rule:nonzero;stroke:none" /><g
+         transform="translate(290.06807,8.3297801)"
+         id="g3082-3"><g
+           id="g3084-9" /><g
+           id="g3090-2"><g
+             clip-path="url(#clipPath3086-4-0)"
+             id="g3092-8"
+             style="opacity:0.10000598"><path
+               inkscape:connector-curvature="0"
+               d="m 1432.002,722 -374,0 0,-374 374,0 0,374 z m -3,-371 -368,0 0,368 368,0 0,-368 z"
+               id="path3094-1"
+               style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></g><g
+         transform="translate(290.06807,8.3297801)"
+         id="g3096-6"><g
+           id="g3098-6" /><g
+           id="g3104-5"><g
+             clip-path="url(#clipPath3100-8-2)"
+             id="g3106-9"
+             style="opacity:0.10000598"><g
+               transform="translate(1434.334,317.334)"
+               id="g3108-9"><path
+                 inkscape:connector-curvature="0"
+                 d="m 0,0 -378.666,0 c -14.729,0 -26.666,11.938 -26.666,26.666 l 0,-5.334 c 0,-14.727 11.937,-26.666 26.666,-26.666 L 0,-5.334 c 14.729,0 26.668,11.939 26.668,26.666 l 0,5.334 C 26.668,11.938 14.729,0 0,0"
+                 id="path3110-8"
+                 style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></g></g><g
+         transform="translate(290.06807,8.3297801)"
+         id="g3112-1"><g
+           id="g3114-5" /><g
+           id="g3120-7"><g
+             clip-path="url(#clipPath3116-4-9)"
+             id="g3122-5"
+             style="opacity:0.10000598"><g
+               transform="translate(1434.334,756)"
+               id="g3124-1"><path
+                 inkscape:connector-curvature="0"
+                 d="m 0,0 -378.666,0 c -14.729,0 -26.666,-11.938 -26.666,-26.667 l 0,-5.333 c 0,14.728 11.937,26.667 26.666,26.667 L 0,-5.333 c 14.729,0 26.668,-11.939 26.668,-26.667 l 0,5.333 C 26.668,-11.938 14.729,0 0,0"
+                 id="path3126-0"
+                 style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></g></g></g></g><g
+     inkscape:groupmode="layer"
+     id="layer7"
+     inkscape:label="Layer4"
+     style="display:inline"
+     transform="translate(436.0495,72.4457)"><g
+       style="display:inline"
+       id="g3622-5-8"
+       transform="matrix(5.2235991,0,0,-5.1937884,507.13047,984.15494)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><path
+         inkscape:connector-curvature="0"
+         d="m 0,0 c -32.947,0 -59.75,26.804 -59.75,59.75 0,32.946 26.803,59.75 59.75,59.75 32.945,0 59.75,-26.804 59.75,-59.75 C 59.75,26.804 32.945,0 0,0"
+         style="fill:#ff4a3c;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path3624-3-9" /></g><g
+       style="display:inline"
+       id="g3630-4-7"
+       transform="matrix(5.2235991,0,0,-5.1937884,-2762.8426,3436.9216)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><g
+         id="g3632-0-4"
+         clip-path="url(#clipPath3634-8-0)"><g
+           id="g3638-2-4"><g
+             id="g3640-4-1" /><g
+             id="g3666-9-6"><g
+               style="opacity:0.119995"
+               clip-path="url(#clipPath3642-3-4)"
+               id="g3668-8-7"><g
+                 id="g3670-0-5"><g
+                   id="g3672-4-4" /><g
+                   mask="url(#mask3650-5-0)"
+                   id="g3674-2-0"><g
+                     transform="matrix(139.35082,0,0,78.633677,558.31445,465.31115)"
+                     id="g3676-6-2"><image
+                       width="1"
+                       height="1"
+                       transform="matrix(1,0,0,-1,0,1)"
+                       xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIwAAABPCAYAAAA5vC0kAAAABHNCSVQICAgIfAhkiAAAASdJREFUeJzt1rFuwyAUQFGw/P+/TIfKamQ5be7kRjlnshEDw9WDudZa48Kc82qZD/Eki7GfF4TCGD8dnMPZzxvg0Tmc7c7D8D6OcLbHH/iLCcPL5pxjjjGun8NwwYQhEQyJYEgEQyIYEsGQCIZEMCSCIREMiWBIBEMiGBLBkAiGRDAkgiERDIlgSARDIhgSwZAIhkQwJIIhEQyJYEgEQyIYEsGQCIZEMCSCIREMiWBIBEMiGBLBkAiGRDAkgiERDIlgSARDIhgSwZAIhkQwJIIhEQyJYEgEQyIYEsGQCIZEMCSCIREMiWBIBEMiGBLBkAiGRDAkgiERDMm21rr7DLyJtZYJQ7ON8V0O/OZoxIQh2Y+Po6A5522H4f853z77sw3C+WzPnilfB04mnX6avLgAAAAASUVORK5CYII="
+                       mask="url(#mask3662-9-4)"
+                       id="image3678-1-3" /></g></g></g></g></g></g><g
+           id="g3680-5-3"
+           transform="translate(689.7031,476.2588)"><path
+             inkscape:connector-curvature="0"
+             d="m 0,0 c 0,-1.642 -1.344,-2.984 -2.986,-2.984 l -121.434,0 c -1.643,0 -2.986,1.342 -2.986,2.984 l 0,60.719 c 0,1.641 1.343,2.985 2.986,2.985 l 121.434,0 C -1.344,63.704 0,62.36 0,60.719 L 0,0 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+             id="path3682-6-2" /></g></g></g><g
+       id="layer3"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><g
+         transform="matrix(1.25,0,0,-1.25,715.58308,453.4259)"
+         id="g3024-4"
+         style="fill:#000000;display:inline"><path
+           inkscape:connector-curvature="0"
+           d="m 0,0 -12.195,205.05 -307.49,0 L -331.88,0 c 44.595,34.886 102.563,58.974 165.94,58.974 C -102.563,58.974 -44.595,34.886 0,0"
+           id="path3026-3"
+           style="fill:#2e2e2e;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g><g
+         transform="matrix(1.25,0,0,-1.25,300.90228,894.5124)"
+         id="g3028-0"
+         style="fill:#000000;display:inline"><path
+           inkscape:connector-curvature="0"
+           d="m 0,0 12.06,-202.039 307.49,0 L 331.609,0 C 287.033,-34.822 229.119,-58.869 165.805,-58.869 102.491,-58.869 44.576,-34.822 0,0"
+           id="path3030-8"
+           style="fill:#2e2e2e;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g><g
+         transform="matrix(1.25,0,0,-1.25,456.87948,388.9154)"
+         id="g3032-2"
+         style="display:inline"><path
+           inkscape:connector-curvature="0"
+           d="m 0,0 c 5.706,1.02 11.485,1.83 17.328,2.423 3.895,0.395 7.819,0.694 11.769,0.895 3.95,0.2 7.926,0.301 11.926,0.301 4,0 7.976,-0.101 11.926,-0.301 3.95,-0.201 7.874,-0.5 11.77,-0.895 C 70.561,1.83 76.341,1.02 82.047,0 c 108.425,-19.367 190.726,-114.139 190.726,-228.132 0,-127.991 -103.756,-231.75 -231.75,-231.75 -127.99,0 -231.751,103.759 -231.751,231.75 0,113.993 82.305,208.765 190.728,228.132 m 41.023,26.794 c -140.792,0 -254.926,-114.133 -254.926,-254.926 0,-140.792 114.134,-254.926 254.926,-254.926 140.79,0 254.926,114.134 254.926,254.926 0,140.793 -114.136,254.926 -254.926,254.926"
+           id="path3034-1"
+           style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g><g
+         transform="matrix(1.25,0,0,-1.25,508.15818,355.4224)"
+         id="g3036-8"
+         style="fill:#000000;display:inline"><path
+           inkscape:connector-curvature="0"
+           d="m 0,0 c -140.792,0 -254.926,-114.134 -254.926,-254.926 0,-140.792 114.134,-254.926 254.926,-254.926 140.792,0 254.926,114.134 254.926,254.926 C 254.926,-114.134 140.792,0 0,0 m 231.75,-254.926 c 0,-127.991 -103.758,-231.75 -231.75,-231.75 -127.992,0 -231.75,103.759 -231.75,231.75 0,127.993 103.758,231.751 231.75,231.751 127.992,0 231.75,-103.758 231.75,-231.751"
+           id="path3038-3"
+           style="fill:#2c2c2c;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g><g
+         transform="matrix(1.25,0,0,-1.25,-264.34372,1339.588)"
+         id="g3040-9"
+         style="display:inline"><g
+           id="g3042-1" /><g
+           id="g3048-2"><g
+             clip-path="url(#clipPath3044-8-3-2)"
+             id="g3050-4"
+             style="opacity:0.10000598"><g
+               transform="translate(844.249,532.4062)"
+               id="g3052-7"><path
+                 inkscape:connector-curvature="0"
+                 d="m 0,0 c 0,-124.952 -101.295,-226.248 -226.248,-226.248 -124.952,0 -226.247,101.296 -226.247,226.248 0,124.953 101.295,226.248 226.247,226.248 C -101.295,226.248 0,124.953 0,0"
+                 id="path3054-5"
+                 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></g></g><g
+         transform="matrix(1.25,0,0,-1.25,-264.34372,1339.588)"
+         id="g3056-2"
+         style="display:inline"><g
+           id="g3058-6" /><g
+           id="g3064-1"><g
+             clip-path="url(#clipPath3060-8-2-1)"
+             id="g3066-2"
+             style="opacity:0.10000598"><g
+               transform="translate(618.0015,787.7266)"
+               id="g3068-5"><path
+                 inkscape:connector-curvature="0"
+                 d="m 0,0 c -34.466,0 -67.903,-6.75 -99.383,-20.065 -30.404,-12.861 -57.707,-31.269 -81.155,-54.716 -23.446,-23.447 -41.856,-50.752 -54.715,-81.156 -13.314,-31.48 -20.066,-64.916 -20.066,-99.383 0,-34.465 6.752,-67.904 20.066,-99.381 12.859,-30.405 31.269,-57.709 54.715,-81.156 23.448,-23.447 50.751,-41.857 81.155,-54.715 31.48,-13.315 64.917,-20.066 99.383,-20.066 34.466,0 67.903,6.751 99.382,20.066 30.405,12.858 57.708,31.268 81.155,54.715 23.447,23.447 41.857,50.751 54.716,81.156 13.314,31.477 20.066,64.916 20.066,99.381 0,34.467 -6.752,67.903 -20.066,99.383 -12.859,30.404 -31.269,57.709 -54.716,81.156 -23.447,23.447 -50.75,41.855 -81.155,54.716 C 67.903,-6.75 34.466,0 0,0 m 0,-3.153 c 139.268,0 252.167,-112.897 252.167,-252.167 0,-139.267 -112.899,-252.166 -252.167,-252.166 -139.268,0 -252.167,112.899 -252.167,252.166 0,139.27 112.899,252.167 252.167,252.167"
+                 id="path3070-2"
+                 style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></g></g></g><g
+       style="display:inline"
+       id="g3692-7-8"
+       transform="matrix(5.2956158,0,0,-5.2956158,-2815.7539,3491.418)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><g
+         id="g3694-5-3" /><g
+         id="g3704-5-3"><g
+           clip-path="url(#clipPath3696-9-7-9)"
+           id="g3706-2-5"
+           style="opacity:0.5"><g
+             id="g3708-6-9"><g
+               clip-path="url(#clipPath3700-1-1-8)"
+               id="g3710-3-0"><path
+                 d="m 623.994,518.863 -31.988,0 0,12.002 31.988,0 0,-12.002 z"
+                 style="fill:#6d6e71;fill-opacity:1;fill-rule:nonzero;stroke:none"
+                 id="path3712-4-5"
+                 inkscape:connector-curvature="0" /></g></g></g></g></g><path
+       d="m 584.03152,795.94967 -264.78075,0 0,-26.47808 264.78075,0 0,26.47808 z"
+       style="fill:#d1d2d3;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+       id="path3714-2-5"
+       inkscape:connector-curvature="0"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999" /><path
+       d="m 462.23242,848.90583 -142.98165,0 0,-26.47808 142.98165,0 0,26.47808 z"
+       style="fill:#d1d2d3;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+       id="path3716-3-1"
+       inkscape:connector-curvature="0"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999" /><g
+       style="display:inline"
+       id="g3718-7-1"
+       transform="matrix(5.2956158,0,0,-5.2956158,-2815.7539,3491.418)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><g
+         id="g3720-1-0" /><g
+         id="g3730-8-4"><g
+           clip-path="url(#clipPath3722-1-6-1)"
+           id="g3732-8-4"
+           style="opacity:0"><g
+             id="g3734-9-2"><g
+               clip-path="url(#clipPath3726-6-9-4)"
+               id="g3736-3-3"><path
+                 d="m 664.001,520 -12.001,0 0,12 12.001,0 0,-12 z"
+                 style="fill:#ee2a7b;fill-opacity:1;fill-rule:nonzero;stroke:none"
+                 id="path3738-7-6"
+                 inkscape:connector-curvature="0" /></g></g></g></g></g><g
+       style="display:inline"
+       id="g3740-9-7"
+       transform="matrix(5.2956158,0,0,-5.2956158,644.93112,705.35546)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><path
+         d="m 0,0 4.5,0 0,-4.501 0.501,0 4,9.001 L 0,0.501 0,0 z"
+         style="fill:#03a9f4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path3742-8-7"
+         inkscape:connector-curvature="0" /></g></g><g
+     inkscape:groupmode="layer"
+     id="layer6"
+     inkscape:label="Layer3"
+     style="display:inline"
+     transform="translate(436.0495,72.4457)"><g
+       style="display:inline"
+       id="g3508-5-6"
+       transform="matrix(5.09,0,0,-5.09,742.55563,925.70096)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><path
+         inkscape:connector-curvature="0"
+         d="m 0,0 c -2.209,0 -4,1.791 -4,4 l 0,92 c 0,2.209 1.791,4 4,4 l 92,0 c 2.209,0 4,-1.791 4,-4 L 96,4 C 96,1.791 94.209,0 92,0 L 0,0 z"
+         style="fill:#9d65dc;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path3510-0-8" /></g><g
+       style="display:inline"
+       id="g3516-7-9"
+       transform="matrix(5.09,0,0,-5.09,-2642.2948,3424.8908)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><g
+         id="g3518-2-7" /><g
+         id="g3544-9-6"><g
+           style="opacity:0.119995"
+           clip-path="url(#clipPath3520-6-0)"
+           id="g3546-7-3"><g
+             id="g3548-8-7"><g
+               id="g3550-3-6" /><g
+               mask="url(#mask3528-3-8)"
+               id="g3552-8-7"><g
+                 transform="matrix(93,0,0,68,667,493)"
+                 id="g3554-9-9"><image
+                   width="1"
+                   height="1"
+                   transform="matrix(1,0,0,-1,0,1)"
+                   xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF0AAABECAYAAADjqDmQAAAABHNCSVQICAgIfAhkiAAAAP1JREFUeJzt3DGKhEAARcFWvP+VeyNBxJGFHX3BVmU2BvL4DBP1Muec48KyLFfH/NKHrGOMMbbzgdjfsXe8ir+dX+K7ruKv1cf8N8dRr+cDnmfpL9rHvVr5+yw9sIwxPv+h5BGWHhA9IHpA9IDoAdEDogdED4geED0gekD0gOgB0QOiB0QPiB4QPSB6QPSA6AHRA6IHRA+IHhA9IHpA9IDoAdEDogdED4geED0gekD0gOgB0QOiB0QPiB4QPSB6QPSA6AHRA6IHRA+IHhA9IHpA9JfNOUUvrHe3H/MMS3/RPvD1+MA7LP0lx2Fv50N3737X7aX155fE/5u7n+wfv04ph+lQnM8AAAAASUVORK5CYII="
+                   mask="url(#mask3540-4-8)"
+                   id="image3556-9-8" /></g></g></g></g></g></g><g
+       style="display:inline"
+       id="g3558-6-7"
+       transform="matrix(5.09,0,0,-5.09,1180.2956,859.53096)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><path
+         inkscape:connector-curvature="0"
+         d="m 0,0 c 0,-1.65 -1.35,-3 -3,-3 l -74,0 c -1.649,0 -3,1.35 -3,3 l 0,50 c 0,1.65 1.351,3 3,3 l 74,0 c 1.65,0 3,-1.35 3,-3 L 0,0 z"
+         style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path3560-5-9" /></g><g
+       style="display:inline"
+       id="g3562-4-5"
+       transform="matrix(5.09,0,0,-5.09,-2642.2948,3424.8908)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><g
+         id="g3564-6-8" /><g
+         id="g3574-7-5"><g
+           style="opacity:0.5"
+           clip-path="url(#clipPath3566-8-1)"
+           id="g3576-7-7"><g
+             id="g3578-2-1"><g
+               clip-path="url(#clipPath3570-6-5)"
+               id="g3580-1-1"><path
+                 inkscape:connector-curvature="0"
+                 d="m 710.994,535.863 -31.988,0 0,12.002 31.988,0 0,-12.002 z"
+                 style="fill:#6d6e71;fill-opacity:1;fill-rule:nonzero;stroke:none"
+                 id="path3582-0-1" /></g></g></g></g></g><path
+       inkscape:connector-curvature="0"
+       d="m 1068.3156,747.55096 -254.49997,0 0,-25.45 254.49997,0 0,25.45 z"
+       style="fill:#d1d2d3;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+       id="path3584-1-4"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999" /><path
+       inkscape:connector-curvature="0"
+       d="m 951.24563,798.45096 -137.43,0 0,-25.45 137.43,0 0,25.45 z"
+       style="fill:#d1d2d3;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+       id="path3586-5-3"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999" /><g
+       style="display:inline"
+       id="g3588-5-2"
+       transform="matrix(5.09,0,0,-5.09,-2642.2948,3424.8908)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><g
+         id="g3590-3-5" /><g
+         id="g3596-7-7"><g
+           style="opacity:0"
+           clip-path="url(#clipPath3592-5-6)"
+           id="g3598-6-3"><path
+             inkscape:connector-curvature="0"
+             d="m 730.777,537 12,0 0,12 -12,0 0,-12 z"
+             style="fill:#03a9f4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+             id="path3600-8-8" /></g></g></g><g
+       style="display:inline"
+       id="g3602-7-1"
+       transform="matrix(5.09,0,0,-5.09,1133.3524,659.74846)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><path
+         inkscape:connector-curvature="0"
+         d="m 0,0 c 0,0.414 -0.336,0.75 -0.75,0.75 l -2.75,0 -2.5,4 -1,0 1.25,-4 -2.75,0 -0.75,1 -0.75,0 0.5,-1.75 -0.5,-1.75 0.75,0 0.75,1 2.75,0 -1.25,-4 1,0 2.5,4 2.75,0 C -0.336,-0.75 0,-0.414 0,0"
+         style="fill:#00c853;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path3604-3-1" /></g><g
+       id="layer2"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><g
+         transform="matrix(1.25,0,0,-1.25,1156.7381,197.1134)"
+         id="g3072-2"
+         style="fill:#4d4d4d;display:inline"><path
+           inkscape:connector-curvature="0"
+           d="m 0,0 -285.486,0 -14,-190.491 313.486,0 L 0,0 z"
+           id="path3074-4"
+           style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g><g
+         transform="matrix(1.25,0,0,-1.25,1174.2381,908.94815)"
+         id="g3076-2"
+         style="fill:#333333;display:inline"><path
+           inkscape:connector-curvature="0"
+           d="m 0,0 -313.486,0 14,-190.491 286.486,0 L 0,0 z"
+           id="path3078-2"
+           style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g><path
+         inkscape:connector-curvature="0"
+         d="m 1210.8105,905.83777 -467.50004,0 0,-467.5 467.50004,0 0,467.5 z m 4.165,-511.25 -473.33254,0 c -18.41125,0 -33.3325,14.92251 -33.3325,33.33376 l 0,6.66624 0,475 0,6.66751 c 0,18.40874 14.92125,33.33249 33.3325,33.33249 l 473.33254,0 c 18.4112,0 33.335,-14.92375 33.335,-33.33249 l 0,-6.66751 0,-475 0,-6.66624 c 0,-18.41125 -14.9238,-33.33376 -33.335,-33.33376"
+         id="path3080-8"
+         style="fill:#4d4d4d;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline" /><g
+         transform="matrix(1.25,0,0,-1.25,-577.94194,1339.5878)"
+         id="g3082-6"
+         style="display:inline"><g
+           id="g3084-6" /><g
+           id="g3090-6"><g
+             clip-path="url(#clipPath3086-0-0-4)"
+             id="g3092-6"
+             style="opacity:0.10000598"><path
+               inkscape:connector-curvature="0"
+               d="m 1432.002,722 -374,0 0,-374 374,0 0,374 z m -3,-371 -368,0 0,368 368,0 0,-368 z"
+               id="path3094-4"
+               style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></g><g
+         transform="matrix(1.25,0,0,-1.25,-577.94194,1339.5878)"
+         id="g3096-1"
+         style="display:inline"><g
+           id="g3098-7" /><g
+           id="g3104-3"><g
+             clip-path="url(#clipPath3100-0-7-1)"
+             id="g3106-8"
+             style="opacity:0.10000598"><g
+               transform="translate(1434.334,317.334)"
+               id="g3108-5"><path
+                 inkscape:connector-curvature="0"
+                 d="m 0,0 -378.666,0 c -14.729,0 -26.666,11.938 -26.666,26.666 l 0,-5.334 c 0,-14.727 11.937,-26.666 26.666,-26.666 L 0,-5.334 c 14.729,0 26.668,11.939 26.668,26.666 l 0,5.334 C 26.668,11.938 14.729,0 0,0"
+                 id="path3110-7"
+                 style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></g></g><g
+         transform="matrix(1.25,0,0,-1.25,-577.94194,1339.5878)"
+         id="g3112-0"
+         style="display:inline"><g
+           id="g3114-4" /><g
+           id="g3120-4"><g
+             clip-path="url(#clipPath3116-3-2-9)"
+             id="g3122-9"
+             style="opacity:0.10000598"><g
+               transform="translate(1434.334,756)"
+               id="g3124-5"><path
+                 inkscape:connector-curvature="0"
+                 d="m 0,0 -378.666,0 c -14.729,0 -26.666,-11.938 -26.666,-26.667 l 0,-5.333 c 0,14.728 11.937,26.667 26.666,26.667 L 0,-5.333 c 14.729,0 26.668,-11.939 26.668,-26.667 l 0,5.333 C 26.668,-11.938 14.729,0 0,0"
+                 id="path3126-3"
+                 style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></g></g></g></g><g
+     inkscape:groupmode="layer"
+     id="layer5"
+     inkscape:label="Layer2"
+     style="display:inline"
+     transform="translate(436.0495,72.4457)"><g
+       style="display:inline"
+       id="g3622-5"
+       transform="matrix(5.2235991,0,0,-5.1937884,1450.0328,987.05631)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><path
+         inkscape:connector-curvature="0"
+         d="m 0,0 c -32.947,0 -59.75,26.804 -59.75,59.75 0,32.946 26.803,59.75 59.75,59.75 32.945,0 59.75,-26.804 59.75,-59.75 C 59.75,26.804 32.945,0 0,0"
+         style="fill:#0bda2f;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path3624-3" /></g><g
+       style="display:inline"
+       id="g3630-4"
+       transform="matrix(5.2235991,0,0,-5.1937884,-1819.9402,3439.8229)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><g
+         id="g3632-0"
+         clip-path="url(#clipPath3634-8)"><g
+           id="g3638-2"><g
+             id="g3640-4" /><g
+             id="g3666-9"><g
+               style="opacity:0.119995"
+               clip-path="url(#clipPath3642-3)"
+               id="g3668-8"><g
+                 id="g3670-0"><g
+                   id="g3672-4" /><g
+                   mask="url(#mask3650-5)"
+                   id="g3674-2"><g
+                     transform="matrix(139.35082,0,0,78.633677,558.31445,465.31115)"
+                     id="g3676-6"><image
+                       width="1"
+                       height="1"
+                       transform="matrix(1,0,0,-1,0,1)"
+                       xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIwAAABPCAYAAAA5vC0kAAAABHNCSVQICAgIfAhkiAAAASdJREFUeJzt1rFuwyAUQFGw/P+/TIfKamQ5be7kRjlnshEDw9WDudZa48Kc82qZD/Eki7GfF4TCGD8dnMPZzxvg0Tmc7c7D8D6OcLbHH/iLCcPL5pxjjjGun8NwwYQhEQyJYEgEQyIYEsGQCIZEMCSCIREMiWBIBEMiGBLBkAiGRDAkgiERDIlgSARDIhgSwZAIhkQwJIIhEQyJYEgEQyIYEsGQCIZEMCSCIREMiWBIBEMiGBLBkAiGRDAkgiERDIlgSARDIhgSwZAIhkQwJIIhEQyJYEgEQyIYEsGQCIZEMCSCIREMiWBIBEMiGBLBkAiGRDAkgiERDMm21rr7DLyJtZYJQ7ON8V0O/OZoxIQh2Y+Po6A5522H4f853z77sw3C+WzPnilfB04mnX6avLgAAAAASUVORK5CYII="
+                       mask="url(#mask3662-9)"
+                       id="image3678-1" /></g></g></g></g></g></g><g
+           id="g3680-5"
+           transform="translate(689.7031,476.2588)"><path
+             inkscape:connector-curvature="0"
+             d="m 0,0 c 0,-1.642 -1.344,-2.984 -2.986,-2.984 l -121.434,0 c -1.643,0 -2.986,1.342 -2.986,2.984 l 0,60.719 c 0,1.641 1.343,2.985 2.986,2.985 l 121.434,0 C -1.344,63.704 0,62.36 0,60.719 L 0,0 z"
+             style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+             id="path3682-6" /></g></g></g><g
+       transform="translate(2e-5,-3e-5)"
+       id="layer1"
+       style="display:inline"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><g
+         transform="matrix(1.25,0,0,-1.25,1656.802,453.73263)"
+         id="g3024"
+         style="fill:#000000"><path
+           inkscape:connector-curvature="0"
+           d="m 0,0 -12.195,205.05 -307.49,0 L -331.88,0 c 44.595,34.886 102.563,58.974 165.94,58.974 C -102.563,58.974 -44.595,34.886 0,0"
+           id="path3026"
+           style="fill:#606060;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g><g
+         transform="matrix(1.25,0,0,-1.25,1242.1212,894.81914)"
+         id="g3028"
+         style="fill:#000000"><path
+           inkscape:connector-curvature="0"
+           d="m 0,0 12.06,-202.039 307.49,0 L 331.609,0 C 287.033,-34.822 229.119,-58.869 165.805,-58.869 102.491,-58.869 44.576,-34.822 0,0"
+           id="path3030"
+           style="fill:#606060;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g><g
+         transform="matrix(1.25,0,0,-1.25,1398.0984,389.22214)"
+         id="g3032"><path
+           inkscape:connector-curvature="0"
+           d="m 0,0 c 5.706,1.02 11.485,1.83 17.328,2.423 3.895,0.395 7.819,0.694 11.769,0.895 3.95,0.2 7.926,0.301 11.926,0.301 4,0 7.976,-0.101 11.926,-0.301 3.95,-0.201 7.874,-0.5 11.77,-0.895 C 70.561,1.83 76.341,1.02 82.047,0 c 108.425,-19.367 190.726,-114.139 190.726,-228.132 0,-127.991 -103.756,-231.75 -231.75,-231.75 -127.99,0 -231.751,103.759 -231.751,231.75 0,113.993 82.305,208.765 190.728,228.132 m 41.023,26.794 c -140.792,0 -254.926,-114.133 -254.926,-254.926 0,-140.792 114.134,-254.926 254.926,-254.926 140.79,0 254.926,114.134 254.926,254.926 0,140.793 -114.136,254.926 -254.926,254.926"
+           id="path3034"
+           style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g><g
+         transform="matrix(1.25,0,0,-1.25,1449.3771,355.72914)"
+         id="g3036"
+         style="fill:#000000"><path
+           inkscape:connector-curvature="0"
+           d="m 0,0 c -140.792,0 -254.926,-114.134 -254.926,-254.926 0,-140.792 114.134,-254.926 254.926,-254.926 140.792,0 254.926,114.134 254.926,254.926 C 254.926,-114.134 140.792,0 0,0 m 231.75,-254.926 c 0,-127.991 -103.758,-231.75 -231.75,-231.75 -127.992,0 -231.75,103.759 -231.75,231.75 0,127.993 103.758,231.751 231.75,231.751 127.992,0 231.75,-103.758 231.75,-231.751"
+           id="path3038"
+           style="fill:#606060;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g><g
+         transform="matrix(1.25,0,0,-1.25,676.87523,1339.8947)"
+         id="g3040"><g
+           id="g3042" /><g
+           id="g3048"><g
+             clip-path="url(#clipPath3044-8-1)"
+             id="g3050"
+             style="opacity:0.10000598"><g
+               transform="translate(844.249,532.4062)"
+               id="g3052"><path
+                 inkscape:connector-curvature="0"
+                 d="m 0,0 c 0,-124.952 -101.295,-226.248 -226.248,-226.248 -124.952,0 -226.247,101.296 -226.247,226.248 0,124.953 101.295,226.248 226.247,226.248 C -101.295,226.248 0,124.953 0,0"
+                 id="path3054"
+                 style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></g></g><g
+         transform="matrix(1.25,0,0,-1.25,676.87523,1339.8947)"
+         id="g3056"><g
+           id="g3058" /><g
+           id="g3064"><g
+             clip-path="url(#clipPath3060-8-27)"
+             id="g3066"
+             style="opacity:0.10000598"><g
+               transform="translate(618.0015,787.7266)"
+               id="g3068"><path
+                 inkscape:connector-curvature="0"
+                 d="m 0,0 c -34.466,0 -67.903,-6.75 -99.383,-20.065 -30.404,-12.861 -57.707,-31.269 -81.155,-54.716 -23.446,-23.447 -41.856,-50.752 -54.715,-81.156 -13.314,-31.48 -20.066,-64.916 -20.066,-99.383 0,-34.465 6.752,-67.904 20.066,-99.381 12.859,-30.405 31.269,-57.709 54.715,-81.156 23.448,-23.447 50.751,-41.857 81.155,-54.715 31.48,-13.315 64.917,-20.066 99.383,-20.066 34.466,0 67.903,6.751 99.382,20.066 30.405,12.858 57.708,31.268 81.155,54.715 23.447,23.447 41.857,50.751 54.716,81.156 13.314,31.477 20.066,64.916 20.066,99.381 0,34.467 -6.752,67.903 -20.066,99.383 -12.859,30.404 -31.269,57.709 -54.716,81.156 -23.447,23.447 -50.75,41.855 -81.155,54.716 C 67.903,-6.75 34.466,0 0,0 m 0,-3.153 c 139.268,0 252.167,-112.897 252.167,-252.167 0,-139.267 -112.899,-252.166 -252.167,-252.166 -139.268,0 -252.167,112.899 -252.167,252.166 0,139.27 112.899,252.167 252.167,252.167"
+                 id="path3070"
+                 style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></g></g></g><g
+       style="display:inline"
+       id="g3692-7"
+       transform="matrix(5.2956158,0,0,-5.2956158,-1870.725,3488.2105)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><g
+         id="g3694-5" /><g
+         id="g3704-5"><g
+           clip-path="url(#clipPath3696-9-7)"
+           id="g3706-2"
+           style="opacity:0.5"><g
+             id="g3708-6"><g
+               clip-path="url(#clipPath3700-1-1)"
+               id="g3710-3"><path
+                 d="m 623.994,518.863 -31.988,0 0,12.002 31.988,0 0,-12.002 z"
+                 style="fill:#6d6e71;fill-opacity:1;fill-rule:nonzero;stroke:none"
+                 id="path3712-4"
+                 inkscape:connector-curvature="0" /></g></g></g></g></g><path
+       d="m 1529.0604,792.7421 -264.7808,0 0,-26.47808 264.7808,0 0,26.47808 z"
+       style="fill:#d1d2d3;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+       id="path3714-2"
+       inkscape:connector-curvature="0"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999" /><path
+       d="m 1407.2613,845.69826 -142.9817,0 0,-26.47808 142.9817,0 0,26.47808 z"
+       style="fill:#d1d2d3;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+       id="path3716-3"
+       inkscape:connector-curvature="0"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999" /><g
+       style="display:inline"
+       id="g3718-7"
+       transform="matrix(5.2956158,0,0,-5.2956158,-1870.725,3488.2105)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><g
+         id="g3720-1" /><g
+         id="g3730-8"><g
+           clip-path="url(#clipPath3722-1-6)"
+           id="g3732-8"
+           style="opacity:0"><g
+             id="g3734-9"><g
+               clip-path="url(#clipPath3726-6-9)"
+               id="g3736-3"><path
+                 d="m 664.001,520 -12.001,0 0,12 12.001,0 0,-12 z"
+                 style="fill:#ee2a7b;fill-opacity:1;fill-rule:nonzero;stroke:none"
+                 id="path3738-7"
+                 inkscape:connector-curvature="0" /></g></g></g></g></g><g
+       style="display:inline"
+       id="g3740-9"
+       transform="matrix(5.2956158,0,0,-5.2956158,1589.96,702.14789)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><path
+         d="m 0,0 4.5,0 0,-4.501 0.501,0 4,9.001 L 0,0.501 0,0 z"
+         style="fill:#03a9f4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path3742-8"
+         inkscape:connector-curvature="0" /></g></g><g
+     inkscape:groupmode="layer"
+     id="layer4"
+     inkscape:label="Layer1"
+     style="display:inline"
+     transform="translate(436.0495,72.4457)"><g
+       style="display:inline"
+       id="g3508-5"
+       transform="matrix(5.09,0,0,-5.09,1683.0619,927.12472)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><path
+         inkscape:connector-curvature="0"
+         d="m 0,0 c -2.209,0 -4,1.791 -4,4 l 0,92 c 0,2.209 1.791,4 4,4 l 92,0 c 2.209,0 4,-1.791 4,-4 L 96,4 C 96,1.791 94.209,0 92,0 L 0,0 z"
+         style="fill:#ffed0d;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path3510-0" /></g><g
+       style="display:inline"
+       id="g3516-7"
+       transform="matrix(5.09,0,0,-5.09,-1701.7885,3426.3146)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><g
+         id="g3518-2" /><g
+         id="g3544-9"><g
+           style="opacity:0.119995"
+           clip-path="url(#clipPath3520-6)"
+           id="g3546-7"><g
+             id="g3548-8"><g
+               id="g3550-3" /><g
+               mask="url(#mask3528-3)"
+               id="g3552-8"><g
+                 transform="matrix(93,0,0,68,667,493)"
+                 id="g3554-9"><image
+                   width="1"
+                   height="1"
+                   transform="matrix(1,0,0,-1,0,1)"
+                   xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF0AAABECAYAAADjqDmQAAAABHNCSVQICAgIfAhkiAAAAP1JREFUeJzt3DGKhEAARcFWvP+VeyNBxJGFHX3BVmU2BvL4DBP1Muec48KyLFfH/NKHrGOMMbbzgdjfsXe8ir+dX+K7ruKv1cf8N8dRr+cDnmfpL9rHvVr5+yw9sIwxPv+h5BGWHhA9IHpA9IDoAdEDogdED4geED0gekD0gOgB0QOiB0QPiB4QPSB6QPSA6AHRA6IHRA+IHhA9IHpA9IDoAdEDogdED4geED0gekD0gOgB0QOiB0QPiB4QPSB6QPSA6AHRA6IHRA+IHhA9IHpA9JfNOUUvrHe3H/MMS3/RPvD1+MA7LP0lx2Fv50N3737X7aX155fE/5u7n+wfv04ph+lQnM8AAAAASUVORK5CYII="
+                   mask="url(#mask3540-4)"
+                   id="image3556-9" /></g></g></g></g></g></g><g
+       style="display:inline"
+       id="g3558-6"
+       transform="matrix(5.09,0,0,-5.09,2120.8019,860.95472)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><path
+         inkscape:connector-curvature="0"
+         d="m 0,0 c 0,-1.65 -1.35,-3 -3,-3 l -74,0 c -1.649,0 -3,1.35 -3,3 l 0,50 c 0,1.65 1.351,3 3,3 l 74,0 c 1.65,0 3,-1.35 3,-3 L 0,0 z"
+         style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path3560-5" /></g><g
+       style="display:inline"
+       id="g3562-4"
+       transform="matrix(5.09,0,0,-5.09,-1701.7885,3426.3146)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><g
+         id="g3564-6" /><g
+         id="g3574-7"><g
+           style="opacity:0.5"
+           clip-path="url(#clipPath3566-8)"
+           id="g3576-7"><g
+             id="g3578-2"><g
+               clip-path="url(#clipPath3570-6)"
+               id="g3580-1"><path
+                 inkscape:connector-curvature="0"
+                 d="m 710.994,535.863 -31.988,0 0,12.002 31.988,0 0,-12.002 z"
+                 style="fill:#6d6e71;fill-opacity:1;fill-rule:nonzero;stroke:none"
+                 id="path3582-0" /></g></g></g></g></g><path
+       inkscape:connector-curvature="0"
+       d="m 2008.8219,748.97472 -254.5,0 0,-25.45 254.5,0 0,25.45 z"
+       style="fill:#d1d2d3;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+       id="path3584-1"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999" /><path
+       inkscape:connector-curvature="0"
+       d="m 1891.7519,799.87472 -137.43,0 0,-25.45 137.43,0 0,25.45 z"
+       style="fill:#d1d2d3;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline"
+       id="path3586-5"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999" /><g
+       style="display:inline"
+       id="g3588-5"
+       transform="matrix(5.09,0,0,-5.09,-1701.7885,3426.3146)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><g
+         id="g3590-3" /><g
+         id="g3596-7"><g
+           style="opacity:0"
+           clip-path="url(#clipPath3592-5)"
+           id="g3598-6"><path
+             inkscape:connector-curvature="0"
+             d="m 730.777,537 12,0 0,12 -12,0 0,-12 z"
+             style="fill:#03a9f4;fill-opacity:1;fill-rule:nonzero;stroke:none"
+             id="path3600-8" /></g></g></g><g
+       style="display:inline"
+       id="g3602-7"
+       transform="matrix(5.09,0,0,-5.09,2073.8587,661.17222)"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"><path
+         inkscape:connector-curvature="0"
+         d="m 0,0 c 0,0.414 -0.336,0.75 -0.75,0.75 l -2.75,0 -2.5,4 -1,0 1.25,-4 -2.75,0 -0.75,1 -0.75,0 0.5,-1.75 -0.5,-1.75 0.75,0 0.75,1 2.75,0 -1.25,-4 1,0 2.5,4 2.75,0 C -0.336,-0.75 0,-0.414 0,0"
+         style="fill:#00c853;fill-opacity:1;fill-rule:nonzero;stroke:none"
+         id="path3604-3" /></g><g
+       transform="matrix(1.25,0,0,-1.25,0,1350)"
+       id="g3012"
+       style="display:inline"
+       inkscape:export-xdpi="18.559999"
+       inkscape:export-ydpi="18.559999"
+       inkscape:export-filename="C:\Users\Joe Fernandez\Downloads\Android Wear Artwork\g3014.png"><g
+         transform="translate(1677.8121,922.30928)"
+         id="g3072"
+         style="fill:#333333;fill-opacity:1"><path
+           inkscape:connector-curvature="0"
+           d="m 0,0 -285.486,0 -14,-190.491 313.486,0 L 0,0 z"
+           id="path3074"
+           style="fill:#747474;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g><g
+         transform="translate(1691.8121,352.84148)"
+         id="g3076"
+         style="fill:#333333;fill-opacity:1"><path
+           inkscape:connector-curvature="0"
+           d="m 0,0 -313.486,0 14,-190.491 286.486,0 L 0,0 z"
+           id="path3078"
+           style="fill:#747474;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g><path
+         inkscape:connector-curvature="0"
+         d="m 1721.07,355.32978 -374,0 0,374 374,0 0,-374 z m 3.332,409 -378.666,0 c -14.729,0 -26.666,-11.938 -26.666,-26.667 l 0,-5.333 0,-380 0,-5.334 c 0,-14.727 11.937,-26.666 26.666,-26.666 l 378.666,0 c 14.729,0 26.668,11.939 26.668,26.666 l 0,5.334 0,380 0,5.333 c 0,14.729 -11.939,26.667 -26.668,26.667"
+         id="path3080"
+         style="fill:#747474;fill-opacity:1;fill-rule:nonzero;stroke:none" /><g
+         transform="translate(290.06807,8.3297801)"
+         id="g3082"><g
+           id="g3084" /><g
+           id="g3090"><g
+             clip-path="url(#clipPath3086-4)"
+             id="g3092"
+             style="opacity:0.10000598"><path
+               inkscape:connector-curvature="0"
+               d="m 1432.002,722 -374,0 0,-374 374,0 0,374 z m -3,-371 -368,0 0,368 368,0 0,-368 z"
+               id="path3094"
+               style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></g><g
+         transform="translate(290.06807,8.3297801)"
+         id="g3096"><g
+           id="g3098" /><g
+           id="g3104"><g
+             clip-path="url(#clipPath3100-8)"
+             id="g3106"
+             style="opacity:0.10000598"><g
+               transform="translate(1434.334,317.334)"
+               id="g3108"><path
+                 inkscape:connector-curvature="0"
+                 d="m 0,0 -378.666,0 c -14.729,0 -26.666,11.938 -26.666,26.666 l 0,-5.334 c 0,-14.727 11.937,-26.666 26.666,-26.666 L 0,-5.334 c 14.729,0 26.668,11.939 26.668,26.666 l 0,5.334 C 26.668,11.938 14.729,0 0,0"
+                 id="path3110"
+                 style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></g></g><g
+         transform="translate(290.06807,8.3297801)"
+         id="g3112"><g
+           id="g3114" /><g
+           id="g3120"><g
+             clip-path="url(#clipPath3116-4)"
+             id="g3122"
+             style="opacity:0.10000598"><g
+               transform="translate(1434.334,756)"
+               id="g3124"><path
+                 inkscape:connector-curvature="0"
+                 d="m 0,0 -378.666,0 c -14.729,0 -26.666,-11.938 -26.666,-26.667 l 0,-5.333 c 0,14.728 11.937,26.667 26.666,26.667 L 0,-5.333 c 14.729,0 26.668,-11.939 26.668,-26.667 l 0,5.333 C 26.668,-11.938 14.729,0 0,0"
+                 id="path3126"
+                 style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /></g></g></g></g></g><g
+       id="g3744"
+       transform="matrix(1.25,0,0,-1.25,-298.02174,762.5543)"><g
+         id="g3746" /><g
+         id="g3752"><g
+           clip-path="url(#clipPath3748-6)"
+           id="g3754"
+           style="opacity:0"><path
+             d="m 1484,446 -270,0 0,182 270,0 0,-182 z"
+             style="fill:#ec008c;fill-opacity:1;fill-rule:nonzero;stroke:none"
+             id="path3756"
+             inkscape:connector-curvature="0" /></g></g></g><g
+       id="g3758"
+       transform="matrix(1.25,0,0,-1.25,1378.2283,155.0543)" /><g
+       id="g3762"
+       transform="matrix(1.25,0,0,-1.25,1539.4783,28.8043)" /></g></svg>
\ No newline at end of file
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index bec1d38..1fac5b6 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -1058,54 +1058,72 @@
         final Drawable drawable;
 
         final String name = parser.getName();
-        if (name.equals("selector")) {
-            drawable = new StateListDrawable();
-        } else if (name.equals("animated-selector")) {
-            drawable = new AnimatedStateListDrawable();
-        } else if (name.equals("level-list")) {
-            drawable = new LevelListDrawable();
-        } else if (name.equals("layer-list")) {
-            drawable = new LayerDrawable();
-        } else if (name.equals("transition")) {
-            drawable = new TransitionDrawable();
-        } else if (name.equals("ripple")) {
-            drawable = new RippleDrawable();
-        } else if (name.equals("color")) {
-            drawable = new ColorDrawable();
-        } else if (name.equals("shape")) {
-            drawable = new GradientDrawable();
-        } else if (name.equals("vector")) {
-            drawable = new VectorDrawable();
-        } else if (name.equals("animated-vector")) {
-            drawable = new AnimatedVectorDrawable();
-        } else if (name.equals("scale")) {
-            drawable = new ScaleDrawable();
-        } else if (name.equals("clip")) {
-            drawable = new ClipDrawable();
-        } else if (name.equals("rotate")) {
-            drawable = new RotateDrawable();
-        } else if (name.equals("animated-rotate")) {
-            drawable = new AnimatedRotateDrawable();
-        } else if (name.equals("animation-list")) {
-            drawable = new AnimationDrawable();
-        } else if (name.equals("inset")) {
-            drawable = new InsetDrawable();
-        } else if (name.equals("bitmap")) {
-            //noinspection deprecation
-            drawable = new BitmapDrawable(r);
-            if (r != null) {
-               ((BitmapDrawable) drawable).setTargetDensity(r.getDisplayMetrics());
-            }
-        } else if (name.equals("nine-patch")) {
-            drawable = new NinePatchDrawable();
-            if (r != null) {
-                ((NinePatchDrawable) drawable).setTargetDensity(r.getDisplayMetrics());
-             }
-        } else {
-            throw new XmlPullParserException(parser.getPositionDescription() +
-                    ": invalid drawable tag " + name);
-        }
+        switch (name) {
+            case "selector":
+                drawable = new StateListDrawable();
+                break;
+            case "animated-selector":
+                drawable = new AnimatedStateListDrawable();
+                break;
+            case "level-list":
+                drawable = new LevelListDrawable();
+                break;
+            case "layer-list":
+                drawable = new LayerDrawable();
+                break;
+            case "transition":
+                drawable = new TransitionDrawable();
+                break;
+            case "ripple":
+                drawable = new RippleDrawable();
+                break;
+            case "color":
+                drawable = new ColorDrawable();
+                break;
+            case "shape":
+                drawable = new GradientDrawable();
+                break;
+            case "vector":
+                drawable = new VectorDrawable();
+                break;
+            case "animated-vector":
+                drawable = new AnimatedVectorDrawable();
+                break;
+            case "scale":
+                drawable = new ScaleDrawable();
+                break;
+            case "clip":
+                drawable = new ClipDrawable();
+                break;
+            case "rotate":
+                drawable = new RotateDrawable();
+                break;
+            case "animated-rotate":
+                drawable = new AnimatedRotateDrawable();
+                break;
+            case "animation-list":
+                drawable = new AnimationDrawable();
+                break;
+            case "inset":
+                drawable = new InsetDrawable();
+                break;
+            case "bitmap":
+                drawable = new BitmapDrawable(r);
+                if (r != null) {
+                    ((BitmapDrawable) drawable).setTargetDensity(r.getDisplayMetrics());
+                }
+                break;
+            case "nine-patch":
+                drawable = new NinePatchDrawable();
+                if (r != null) {
+                    ((NinePatchDrawable) drawable).setTargetDensity(r.getDisplayMetrics());
+                }
+                break;
+            default:
+                throw new XmlPullParserException(parser.getPositionDescription() +
+                        ": invalid drawable tag " + name);
 
+        }
         drawable.inflate(r, parser, attrs, theme);
         return drawable;
     }
diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk
index 5808d20..1344dd9 100644
--- a/libs/androidfw/tests/Android.mk
+++ b/libs/androidfw/tests/Android.mk
@@ -26,6 +26,7 @@
     Idmap_test.cpp \
     ResTable_test.cpp \
     Split_test.cpp \
+    TestHelpers.cpp \
     Theme_test.cpp \
     TypeWrappers_test.cpp \
     ZipUtils_test.cpp
diff --git a/libs/androidfw/tests/ResTable_test.cpp b/libs/androidfw/tests/ResTable_test.cpp
index 89d271d0..6a9314e 100644
--- a/libs/androidfw/tests/ResTable_test.cpp
+++ b/libs/androidfw/tests/ResTable_test.cpp
@@ -37,8 +37,6 @@
 
 #include "data/lib/lib_arsc.h"
 
-enum { MAY_NOT_BE_BAG = false };
-
 TEST(ResTableTest, shouldLoadSuccessfully) {
     ResTable table;
     ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
@@ -48,15 +46,7 @@
     ResTable table;
     ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
 
-    Res_value val;
-    ssize_t block = table.getResource(base::R::string::test1, &val, MAY_NOT_BE_BAG);
-
-    ASSERT_GE(block, 0);
-    ASSERT_EQ(Res_value::TYPE_STRING, val.dataType);
-
-    const ResStringPool* pool = table.getTableStringBlock(block);
-    ASSERT_TRUE(NULL != pool);
-    ASSERT_EQ(String8("test1"), pool->string8ObjectAt(val.data));
+    EXPECT_TRUE(IsStringEqual(table, base::R::string::test1, "test1"));
 }
 
 TEST(ResTableTest, resourceNameIsResolved) {
diff --git a/libs/androidfw/tests/Split_test.cpp b/libs/androidfw/tests/Split_test.cpp
index f63f566..b69d685 100644
--- a/libs/androidfw/tests/Split_test.cpp
+++ b/libs/androidfw/tests/Split_test.cpp
@@ -42,6 +42,9 @@
  * Package: com.android.test.basic
  */
 #include "data/basic/split_de_fr_arsc.h"
+#include "data/basic/split_hdpi_v4_arsc.h"
+#include "data/basic/split_xhdpi_v4_arsc.h"
+#include "data/basic/split_xxhdpi_v4_arsc.h"
 
 /**
  * Include a binary resource table. This table
@@ -163,6 +166,33 @@
     EXPECT_EQ(ResTable_config::CONFIG_LOCALE, frSpecFlags);
 }
 
+TEST(SplitTest, SelectBestDensity) {
+    ResTable_config baseConfig;
+    memset(&baseConfig, 0, sizeof(baseConfig));
+    baseConfig.density = ResTable_config::DENSITY_XHIGH;
+    baseConfig.sdkVersion = 21;
+
+    ResTable table;
+    table.setParameters(&baseConfig);
+    ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
+    ASSERT_EQ(NO_ERROR, table.add(split_hdpi_v4_arsc, split_hdpi_v4_arsc_len));
+
+    EXPECT_TRUE(IsStringEqual(table, base::R::string::density, "hdpi"));
+
+    ASSERT_EQ(NO_ERROR, table.add(split_xhdpi_v4_arsc, split_xhdpi_v4_arsc_len));
+
+    EXPECT_TRUE(IsStringEqual(table, base::R::string::density, "xhdpi"));
+
+    ASSERT_EQ(NO_ERROR, table.add(split_xxhdpi_v4_arsc, split_xxhdpi_v4_arsc_len));
+
+    EXPECT_TRUE(IsStringEqual(table, base::R::string::density, "xhdpi"));
+
+    baseConfig.density = ResTable_config::DENSITY_XXHIGH;
+    table.setParameters(&baseConfig);
+
+    EXPECT_TRUE(IsStringEqual(table, base::R::string::density, "xxhdpi"));
+}
+
 TEST(SplitFeatureTest, TestNewResourceIsAccessible) {
     ResTable table;
     ASSERT_EQ(NO_ERROR, table.add(basic_arsc, basic_arsc_len));
@@ -188,7 +218,7 @@
 
     ASSERT_EQ(NO_ERROR, table.add(feature_arsc, feature_arsc_len));
 
-    EXPECT_TRUE(table.getResourceName(base::R::string::test3, false, &name));
+    ASSERT_TRUE(table.getResourceName(base::R::string::test3, false, &name));
 
     EXPECT_EQ(String16("com.android.test.basic"),
             String16(name.package, name.packageLen));
diff --git a/libs/androidfw/tests/TestHelpers.cpp b/libs/androidfw/tests/TestHelpers.cpp
new file mode 100644
index 0000000..41a19a7
--- /dev/null
+++ b/libs/androidfw/tests/TestHelpers.cpp
@@ -0,0 +1,48 @@
+/*
+ * 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 "TestHelpers.h"
+
+#include <androidfw/ResourceTypes.h>
+#include <utils/String8.h>
+#include <gtest/gtest.h>
+
+namespace android {
+
+::testing::AssertionResult IsStringEqual(const ResTable& table, uint32_t resourceId, const char* expectedStr) {
+    Res_value val;
+    ssize_t block = table.getResource(resourceId, &val, MAY_NOT_BE_BAG);
+    if (block < 0) {
+        return ::testing::AssertionFailure() << "could not find resource";
+    }
+
+    if (val.dataType != Res_value::TYPE_STRING) {
+        return ::testing::AssertionFailure() << "resource is not a string";
+    }
+
+    const ResStringPool* pool = table.getTableStringBlock(block);
+    if (pool == NULL) {
+        return ::testing::AssertionFailure() << "table has no string pool for block " << block;
+    }
+
+    const String8 actual = pool->string8ObjectAt(val.data);
+    if (String8(expectedStr) != actual) {
+        return ::testing::AssertionFailure() << actual.string();
+    }
+    return ::testing::AssertionSuccess() << actual.string();
+}
+
+} // namespace android
diff --git a/libs/androidfw/tests/TestHelpers.h b/libs/androidfw/tests/TestHelpers.h
index fe2e5ce..ac80d88 100644
--- a/libs/androidfw/tests/TestHelpers.h
+++ b/libs/androidfw/tests/TestHelpers.h
@@ -6,6 +6,7 @@
 #include <androidfw/ResourceTypes.h>
 #include <utils/String8.h>
 #include <utils/String16.h>
+#include <gtest/gtest.h>
 
 static inline ::std::ostream& operator<<(::std::ostream& out, const android::String8& str) {
     return out << str.string();
@@ -17,6 +18,8 @@
 
 namespace android {
 
+enum { MAY_NOT_BE_BAG = false };
+
 static inline bool operator==(const android::ResTable_config& a, const android::ResTable_config& b) {
     return memcmp(&a, &b, sizeof(a)) == 0;
 }
@@ -25,6 +28,8 @@
     return out << c.toString().string();
 }
 
+::testing::AssertionResult IsStringEqual(const ResTable& table, uint32_t resourceId, const char* expectedStr);
+
 } // namespace android
 
 #endif // __TEST_HELPERS_H
diff --git a/libs/androidfw/tests/data/app/R.h b/libs/androidfw/tests/data/app/R.h
index 780a116..23e68e3 100644
--- a/libs/androidfw/tests/data/app/R.h
+++ b/libs/androidfw/tests/data/app/R.h
@@ -1,3 +1,19 @@
+/*
+ * 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 __APP_R_H
 #define __APP_R_H
 
diff --git a/libs/androidfw/tests/data/app/build b/libs/androidfw/tests/data/app/build
index 89c4641..62257bc 100755
--- a/libs/androidfw/tests/data/app/build
+++ b/libs/androidfw/tests/data/app/build
@@ -1,4 +1,19 @@
 #!/bin/bash
+#
+# 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.
+#
 
 aapt package -v -I ../system/bundle.apk -M AndroidManifest.xml -S res -F bundle.apk -f && \
 unzip bundle.apk resources.arsc && \
diff --git a/libs/androidfw/tests/data/app/res/values/values.xml b/libs/androidfw/tests/data/app/res/values/values.xml
index b0ead38..c1cf64c 100644
--- a/libs/androidfw/tests/data/app/res/values/values.xml
+++ b/libs/androidfw/tests/data/app/res/values/values.xml
@@ -1,4 +1,19 @@
 <?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.
+-->
+
 <resources>
     <attr name="number" format="integer"/>
     <style name="Theme.One" parent="@android:style/Theme.One">
diff --git a/libs/androidfw/tests/data/basic/R.h b/libs/androidfw/tests/data/basic/R.h
index 363dcb9..aaac740 100644
--- a/libs/androidfw/tests/data/basic/R.h
+++ b/libs/androidfw/tests/data/basic/R.h
@@ -1,3 +1,19 @@
+/*
+ * 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 __BASE_R_H
 #define __BASE_R_H
 
@@ -21,9 +37,10 @@
     enum {
         test1       = 0x7f030000,   // default
         test2       = 0x7f030001,   // default
+        density     = 0x7f030002,   // default
 
-        test3       = 0x7f070000,   // default (in feature)
-        test4       = 0x7f070001,   // default (in feature)
+        test3       = 0x7f080000,   // default (in feature)
+        test4       = 0x7f080001,   // default (in feature)
     };
 }
 
@@ -32,7 +49,7 @@
         number1     = 0x7f040000,   // default, sv
         number2     = 0x7f040001,   // default
 
-        test3       = 0x7f080000,   // default (in feature)
+        test3       = 0x7f090000,   // default (in feature)
     };
 }
 
diff --git a/libs/androidfw/tests/data/basic/basic_arsc.h b/libs/androidfw/tests/data/basic/basic_arsc.h
index 61cb94c..13ab4fa 100644
--- a/libs/androidfw/tests/data/basic/basic_arsc.h
+++ b/libs/androidfw/tests/data/basic/basic_arsc.h
@@ -1,5 +1,5 @@
 unsigned char basic_arsc[] = {
-  0x02, 0x00, 0x0c, 0x00, 0x60, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x0c, 0x00, 0x68, 0x07, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x01, 0x00, 0x1c, 0x00, 0xbc, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00,
@@ -16,7 +16,7 @@
   0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
   0x31, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
   0x74, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01,
-  0x98, 0x06, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00,
+  0xa0, 0x06, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00,
   0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00,
   0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00,
   0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00,
@@ -101,61 +101,61 @@
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
   0x08, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
-  0x18, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
-  0x6c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-  0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x02, 0x44, 0x00, 0x70, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
-  0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
-  0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
-  0x6c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-  0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10,
-  0xc8, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x7f, 0x01, 0x02, 0x44, 0x00,
-  0x5c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-  0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x73, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
-  0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10,
-  0x90, 0x01, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
-  0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x90, 0x00, 0x00, 0x00,
-  0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
+  0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x6c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
   0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
-  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x01, 0x7f, 0x08, 0x00, 0x00, 0x10, 0x64, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x01, 0x7f, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x7f,
-  0x10, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x7f,
-  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7f, 0x08, 0x00, 0x00, 0x10,
-  0x2c, 0x01, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
-  0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x01, 0x02, 0x44, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0xc8, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01,
+  0x00, 0x00, 0x06, 0x7f, 0x01, 0x02, 0x44, 0x00, 0x5c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
+  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x73, 0x76, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, 0x90, 0x01, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x02, 0x44, 0x00, 0x90, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x10, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
-  0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
-  0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10,
-  0x03, 0x00, 0x00, 0x00
+  0x28, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x7f,
+  0x08, 0x00, 0x00, 0x10, 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x7f,
+  0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x04, 0x7f, 0x10, 0x00, 0x01, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x7f, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x01, 0x7f, 0x08, 0x00, 0x00, 0x10, 0x2c, 0x01, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
+  0x7c, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+  0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x10, 0x03, 0x00, 0x00, 0x00
 };
-unsigned int basic_arsc_len = 1888;
+unsigned int basic_arsc_len = 1896;
diff --git a/libs/androidfw/tests/data/basic/build b/libs/androidfw/tests/data/basic/build
index 036e468..fd289fa 100755
--- a/libs/androidfw/tests/data/basic/build
+++ b/libs/androidfw/tests/data/basic/build
@@ -1,11 +1,39 @@
 #!/bin/bash
+#
+# 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.
+#
 
 PATH_TO_FRAMEWORK_RES=$(gettop)/prebuilts/sdk/current/android.jar
 
-aapt package -M AndroidManifest.xml -S res -I $PATH_TO_FRAMEWORK_RES --split fr,de -F bundle.apk -f && \
+aapt package -M AndroidManifest.xml -S res -I $PATH_TO_FRAMEWORK_RES --split hdpi --split xhdpi --split xxhdpi --split fr,de -F bundle.apk -f && \
 unzip bundle.apk resources.arsc && \
 mv resources.arsc basic.arsc && \
 xxd -i basic.arsc > basic_arsc.h && \
+\
 unzip bundle_de_fr.apk resources.arsc && \
 mv resources.arsc split_de_fr.arsc && \
-xxd -i split_de_fr.arsc > split_de_fr_arsc.h
+xxd -i split_de_fr.arsc > split_de_fr_arsc.h && \
+\
+unzip bundle_hdpi-v4.apk resources.arsc && \
+mv resources.arsc split_hdpi_v4.arsc && \
+xxd -i split_hdpi_v4.arsc > split_hdpi_v4_arsc.h && \
+\
+unzip bundle_xhdpi-v4.apk resources.arsc && \
+mv resources.arsc split_xhdpi_v4.arsc && \
+xxd -i split_xhdpi_v4.arsc > split_xhdpi_v4_arsc.h && \
+\
+unzip bundle_xxhdpi-v4.apk resources.arsc && \
+mv resources.arsc split_xxhdpi_v4.arsc && \
+xxd -i split_xxhdpi_v4.arsc > split_xxhdpi_v4_arsc.h \
diff --git a/libs/androidfw/tests/data/basic/res/layout-fr-sw600dp/main.xml b/libs/androidfw/tests/data/basic/res/layout-fr-sw600dp/main.xml
index 05ffd58..0dcf7e0 100644
--- a/libs/androidfw/tests/data/basic/res/layout-fr-sw600dp/main.xml
+++ b/libs/androidfw/tests/data/basic/res/layout-fr-sw600dp/main.xml
@@ -1,3 +1,18 @@
 <?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.
+-->
+
 <merge>
 </merge>
diff --git a/libs/androidfw/tests/data/basic/res/layout/main.xml b/libs/androidfw/tests/data/basic/res/layout/main.xml
index 05ffd58..0dcf7e0 100644
--- a/libs/androidfw/tests/data/basic/res/layout/main.xml
+++ b/libs/androidfw/tests/data/basic/res/layout/main.xml
@@ -1,3 +1,18 @@
 <?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.
+-->
+
 <merge>
 </merge>
diff --git a/libs/androidfw/tests/data/basic/res/values-de/values.xml b/libs/androidfw/tests/data/basic/res/values-de/values.xml
index 103c6a3..2683a7e 100644
--- a/libs/androidfw/tests/data/basic/res/values-de/values.xml
+++ b/libs/androidfw/tests/data/basic/res/values-de/values.xml
@@ -1,4 +1,19 @@
 <?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.
+-->
+
 <resources>
     <string name="test1">versuch 1</string>
     <string name="test2">versuch 2</string>
diff --git a/libs/androidfw/tests/data/basic/res/values-fr/values.xml b/libs/androidfw/tests/data/basic/res/values-fr/values.xml
index 1806a2d..7d3bed3 100644
--- a/libs/androidfw/tests/data/basic/res/values-fr/values.xml
+++ b/libs/androidfw/tests/data/basic/res/values-fr/values.xml
@@ -1,4 +1,19 @@
 <?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.
+-->
+
 <resources>
     <string name="test1">essai 1</string>
     <string name="test2">essai 2</string>
diff --git a/libs/androidfw/tests/data/basic/res/values-hdpi/values.xml b/libs/androidfw/tests/data/basic/res/values-hdpi/values.xml
new file mode 100644
index 0000000..04bf943
--- /dev/null
+++ b/libs/androidfw/tests/data/basic/res/values-hdpi/values.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<resources>
+    <string name="density">hdpi</string>
+</resources>
diff --git a/libs/androidfw/tests/data/basic/res/values-sv/values.xml b/libs/androidfw/tests/data/basic/res/values-sv/values.xml
index 9d52307..7351b49 100644
--- a/libs/androidfw/tests/data/basic/res/values-sv/values.xml
+++ b/libs/androidfw/tests/data/basic/res/values-sv/values.xml
@@ -1,4 +1,19 @@
 <?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.
+-->
+
 <resources>
     <integer name="number1">400</integer>
 </resources>
diff --git a/libs/androidfw/tests/data/basic/res/values-xhdpi/values.xml b/libs/androidfw/tests/data/basic/res/values-xhdpi/values.xml
new file mode 100644
index 0000000..845e9a0
--- /dev/null
+++ b/libs/androidfw/tests/data/basic/res/values-xhdpi/values.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<resources>
+    <string name="density">xhdpi</string>
+</resources>
diff --git a/libs/androidfw/tests/data/basic/res/values-xxhdpi/values.xml b/libs/androidfw/tests/data/basic/res/values-xxhdpi/values.xml
new file mode 100644
index 0000000..964da02
--- /dev/null
+++ b/libs/androidfw/tests/data/basic/res/values-xxhdpi/values.xml
@@ -0,0 +1,19 @@
+<?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.
+-->
+
+<resources>
+    <string name="density">xxhdpi</string>
+</resources>
diff --git a/libs/androidfw/tests/data/basic/res/values/values.xml b/libs/androidfw/tests/data/basic/res/values/values.xml
index 662eda6..a010cca 100644
--- a/libs/androidfw/tests/data/basic/res/values/values.xml
+++ b/libs/androidfw/tests/data/basic/res/values/values.xml
@@ -1,4 +1,19 @@
 <?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.
+-->
+
 <resources>
     <attr name="attr1" format="reference|integer" />
     <attr name="attr2" format="reference|integer" />
diff --git a/libs/androidfw/tests/data/basic/split_de_fr_arsc.h b/libs/androidfw/tests/data/basic/split_de_fr_arsc.h
index a8eaf0b..b742d28 100644
--- a/libs/androidfw/tests/data/basic/split_de_fr_arsc.h
+++ b/libs/androidfw/tests/data/basic/split_de_fr_arsc.h
@@ -1,5 +1,5 @@
 unsigned char split_de_fr_arsc[] = {
-  0x02, 0x00, 0x0c, 0x00, 0xd8, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x0c, 0x00, 0xe4, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x01, 0x00, 0x1c, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
@@ -10,7 +10,7 @@
   0x32, 0x00, 0x00, 0x00, 0x07, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00,
   0x61, 0x00, 0x69, 0x00, 0x20, 0x00, 0x31, 0x00, 0x00, 0x00, 0x07, 0x00,
   0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x61, 0x00, 0x69, 0x00, 0x20, 0x00,
-  0x32, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0x50, 0x03, 0x00, 0x00,
+  0x32, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0x5c, 0x03, 0x00, 0x00,
   0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
   0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
   0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
@@ -55,24 +55,25 @@
   0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
   0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
-  0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-  0x04, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x6c, 0x00, 0x00, 0x00,
-  0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
-  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x65, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
+  0x70, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x50, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x64, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00,
+  0x01, 0x02, 0x44, 0x00, 0x70, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x66, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
-  0x01, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x6c, 0x00, 0x00, 0x00,
-  0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
-  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x72, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x10, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x08, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x00,
   0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
   0x03, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
@@ -82,4 +83,4 @@
   0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
   0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
-unsigned int split_de_fr_arsc_len = 984;
+unsigned int split_de_fr_arsc_len = 996;
diff --git a/libs/androidfw/tests/data/basic/split_hdpi_v4_arsc.h b/libs/androidfw/tests/data/basic/split_hdpi_v4_arsc.h
new file mode 100644
index 0000000..e9fb7ea
--- /dev/null
+++ b/libs/androidfw/tests/data/basic/split_hdpi_v4_arsc.h
@@ -0,0 +1,68 @@
+unsigned char split_hdpi_v4_arsc[] = {
+  0x02, 0x00, 0x0c, 0x00, 0x08, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x1c, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x68, 0x00,
+  0x64, 0x00, 0x70, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01,
+  0xd0, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00,
+  0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00,
+  0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00,
+  0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00,
+  0x69, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x20, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb0, 0x01, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
+  0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
+  0x2c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00, 0x6f, 0x00, 0x75, 0x00,
+  0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00,
+  0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00, 0x07, 0x00, 0x69, 0x00,
+  0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00,
+  0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00, 0x79, 0x00, 0x6c, 0x00,
+  0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00, 0x72, 0x00, 0x72, 0x00,
+  0x61, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
+  0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x64, 0x00, 0x65, 0x00, 0x6e, 0x00,
+  0x73, 0x00, 0x69, 0x00, 0x74, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+  0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x02, 0x44, 0x00, 0x60, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+unsigned int split_hdpi_v4_arsc_len = 776;
diff --git a/libs/androidfw/tests/data/basic/split_xhdpi_v4_arsc.h b/libs/androidfw/tests/data/basic/split_xhdpi_v4_arsc.h
new file mode 100644
index 0000000..7835f71
--- /dev/null
+++ b/libs/androidfw/tests/data/basic/split_xhdpi_v4_arsc.h
@@ -0,0 +1,68 @@
+unsigned char split_xhdpi_v4_arsc[] = {
+  0x02, 0x00, 0x0c, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x1c, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x78, 0x00,
+  0x68, 0x00, 0x64, 0x00, 0x70, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x02, 0x20, 0x01, 0xd0, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
+  0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00,
+  0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00,
+  0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00,
+  0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0xb0, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x1c, 0x00, 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x1c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00,
+  0x72, 0x00, 0x00, 0x00, 0x06, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00,
+  0x6f, 0x00, 0x75, 0x00, 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x73, 0x00,
+  0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00,
+  0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00,
+  0x79, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00,
+  0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x1c, 0x00, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x64, 0x00,
+  0x65, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x69, 0x00, 0x74, 0x00, 0x79, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x60, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
+  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+unsigned int split_xhdpi_v4_arsc_len = 780;
diff --git a/libs/androidfw/tests/data/basic/split_xxhdpi_v4_arsc.h b/libs/androidfw/tests/data/basic/split_xxhdpi_v4_arsc.h
new file mode 100644
index 0000000..f805db1
--- /dev/null
+++ b/libs/androidfw/tests/data/basic/split_xxhdpi_v4_arsc.h
@@ -0,0 +1,68 @@
+unsigned char split_xxhdpi_v4_arsc[] = {
+  0x02, 0x00, 0x0c, 0x00, 0x0c, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x1c, 0x00, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x78, 0x00,
+  0x78, 0x00, 0x68, 0x00, 0x64, 0x00, 0x70, 0x00, 0x69, 0x00, 0x00, 0x00,
+  0x00, 0x02, 0x20, 0x01, 0xd0, 0x02, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
+  0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00, 0x61, 0x00, 0x6e, 0x00,
+  0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00, 0x64, 0x00, 0x2e, 0x00,
+  0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x62, 0x00,
+  0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0xb0, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x1c, 0x00, 0x90, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x1c, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00,
+  0x72, 0x00, 0x00, 0x00, 0x06, 0x00, 0x6c, 0x00, 0x61, 0x00, 0x79, 0x00,
+  0x6f, 0x00, 0x75, 0x00, 0x74, 0x00, 0x00, 0x00, 0x06, 0x00, 0x73, 0x00,
+  0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x67, 0x00,
+  0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x05, 0x00, 0x73, 0x00, 0x74, 0x00,
+  0x79, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00,
+  0x72, 0x00, 0x72, 0x00, 0x61, 0x00, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x1c, 0x00, 0x34, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x64, 0x00,
+  0x65, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x69, 0x00, 0x74, 0x00, 0x79, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x60, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00,
+  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
+  0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+unsigned int split_xxhdpi_v4_arsc_len = 780;
diff --git a/libs/androidfw/tests/data/feature/build b/libs/androidfw/tests/data/feature/build
index b547dc2..0f3307f 100755
--- a/libs/androidfw/tests/data/feature/build
+++ b/libs/androidfw/tests/data/feature/build
@@ -1,4 +1,19 @@
 #!/bin/bash
+#
+# 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.
+#
 
 aapt package -M AndroidManifest.xml -S res --feature-of ../basic/bundle.apk -F bundle.apk -f && \
 unzip bundle.apk resources.arsc && \
diff --git a/libs/androidfw/tests/data/feature/feature_arsc.h b/libs/androidfw/tests/data/feature/feature_arsc.h
index cf7647d..cd29910 100644
--- a/libs/androidfw/tests/data/feature/feature_arsc.h
+++ b/libs/androidfw/tests/data/feature/feature_arsc.h
@@ -1,11 +1,11 @@
 unsigned char feature_arsc[] = {
-  0x02, 0x00, 0x0c, 0x00, 0x40, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x0c, 0x00, 0x44, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x01, 0x00, 0x1c, 0x00, 0x40, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
   0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x33, 0x00,
   0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
-  0x34, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xf4, 0x02, 0x00, 0x00,
+  0x34, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xf8, 0x02, 0x00, 0x00,
   0x7f, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
   0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
   0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
@@ -28,46 +28,46 @@
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x9c, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x7c, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x09, 0x00, 0x00, 0x00, 0xa0, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00, 0x80, 0x00, 0x00, 0x00,
+  0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
-  0x2e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x3c, 0x00, 0x65, 0x00, 0x6d, 0x00,
-  0x70, 0x00, 0x74, 0x00, 0x79, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x04, 0x00,
-  0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x00, 0x00, 0x06, 0x00,
-  0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x67, 0x00,
-  0x00, 0x00, 0x07, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x74, 0x00, 0x65, 0x00,
-  0x67, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x00,
-  0x58, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
-  0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00, 0x33, 0x00,
-  0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
-  0x34, 0x00, 0x00, 0x00, 0x07, 0x00, 0x6e, 0x00, 0x75, 0x00, 0x6d, 0x00,
-  0x62, 0x00, 0x65, 0x00, 0x72, 0x00, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x02, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x18, 0x00, 0x00, 0x00,
-  0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x6c, 0x00, 0x00, 0x00,
-  0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0x07, 0x00, 0x3c, 0x00,
+  0x65, 0x00, 0x6d, 0x00, 0x70, 0x00, 0x74, 0x00, 0x79, 0x00, 0x3e, 0x00,
+  0x00, 0x00, 0x04, 0x00, 0x61, 0x00, 0x74, 0x00, 0x74, 0x00, 0x72, 0x00,
+  0x00, 0x00, 0x06, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x69, 0x00,
+  0x6e, 0x00, 0x67, 0x00, 0x00, 0x00, 0x07, 0x00, 0x69, 0x00, 0x6e, 0x00,
+  0x74, 0x00, 0x65, 0x00, 0x67, 0x00, 0x65, 0x00, 0x72, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x1c, 0x00, 0x58, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x1c, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00,
+  0x74, 0x00, 0x33, 0x00, 0x00, 0x00, 0x05, 0x00, 0x74, 0x00, 0x65, 0x00,
+  0x73, 0x00, 0x74, 0x00, 0x34, 0x00, 0x00, 0x00, 0x07, 0x00, 0x6e, 0x00,
+  0x75, 0x00, 0x6d, 0x00, 0x62, 0x00, 0x65, 0x00, 0x72, 0x00, 0x33, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
+  0x6c, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x4c, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
+  0x14, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x58, 0x00, 0x00, 0x00,
+  0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
   0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03,
-  0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x01, 0x02, 0x44, 0x00, 0x58, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10,
-  0xc8, 0x00, 0x00, 0x00
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x10, 0xc8, 0x00, 0x00, 0x00
 };
-unsigned int feature_arsc_len = 832;
+unsigned int feature_arsc_len = 836;
diff --git a/libs/androidfw/tests/data/feature/res/values/values.xml b/libs/androidfw/tests/data/feature/res/values/values.xml
index d03445a..343fd6c 100644
--- a/libs/androidfw/tests/data/feature/res/values/values.xml
+++ b/libs/androidfw/tests/data/feature/res/values/values.xml
@@ -1,4 +1,19 @@
 <?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.
+-->
+
 <resources>
     <string name="test3">test3</string>
     <string name="test4">test4</string>
diff --git a/libs/androidfw/tests/data/lib/R.h b/libs/androidfw/tests/data/lib/R.h
index 13bf095..ff31120 100644
--- a/libs/androidfw/tests/data/lib/R.h
+++ b/libs/androidfw/tests/data/lib/R.h
@@ -1,3 +1,19 @@
+/*
+ * 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 __LIB_R_H
 #define __LIB_R_H
 
diff --git a/libs/androidfw/tests/data/lib/build b/libs/androidfw/tests/data/lib/build
index 8e6e70c..4102903 100755
--- a/libs/androidfw/tests/data/lib/build
+++ b/libs/androidfw/tests/data/lib/build
@@ -1,4 +1,19 @@
 #!/bin/bash
+#
+# 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.
+#
 
 aapt package -M AndroidManifest.xml -S res -F bundle.apk -f --shared-lib && \
 unzip bundle.apk resources.arsc && \
diff --git a/libs/androidfw/tests/data/lib/lib_arsc.h b/libs/androidfw/tests/data/lib/lib_arsc.h
index d670c5b..dd3dad5 100644
--- a/libs/androidfw/tests/data/lib/lib_arsc.h
+++ b/libs/androidfw/tests/data/lib/lib_arsc.h
@@ -1,8 +1,8 @@
 unsigned char lib_arsc[] = {
-  0x02, 0x00, 0x0c, 0x00, 0xc8, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x0c, 0x00, 0xb8, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
   0x01, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0xa0, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x20, 0x01, 0x90, 0x02, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
   0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
   0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
@@ -37,48 +37,25 @@
   0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x05, 0x00, 0x61, 0x00,
   0x74, 0x00, 0x74, 0x00, 0x72, 0x00, 0x31, 0x00, 0x00, 0x00, 0x05, 0x00,
   0x54, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6d, 0x00, 0x65, 0x00, 0x00, 0x00,
-  0x03, 0x02, 0x0c, 0x00, 0x10, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x2e, 0x00,
-  0x61, 0x00, 0x6e, 0x00, 0x64, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x69, 0x00,
-  0x64, 0x00, 0x2e, 0x00, 0x74, 0x00, 0x65, 0x00, 0x73, 0x00, 0x74, 0x00,
-  0x2e, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73, 0x00, 0x69, 0x00, 0x63, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
+  0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00,
+  0x02, 0x02, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00,
+  0x64, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x48, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
-  0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x64, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
-  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x08, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x00, 0x02, 0x02, 0x10, 0x00,
-  0x14, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x44, 0x00, 0x64, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00,
-  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
-  0x08, 0x00, 0x00, 0x10, 0xbc, 0x02, 0x00, 0x00
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x10, 0xbc, 0x02, 0x00, 0x00
 };
-unsigned int lib_arsc_len = 968;
+unsigned int lib_arsc_len = 696;
diff --git a/libs/androidfw/tests/data/lib/res/values/values.xml b/libs/androidfw/tests/data/lib/res/values/values.xml
index a77f0c7..3ec79b1 100644
--- a/libs/androidfw/tests/data/lib/res/values/values.xml
+++ b/libs/androidfw/tests/data/lib/res/values/values.xml
@@ -1,4 +1,19 @@
 <?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.
+-->
+
 <resources>
     <attr name="attr1" format="integer" />
 
diff --git a/libs/androidfw/tests/data/overlay/build b/libs/androidfw/tests/data/overlay/build
index 87cf6de..f737677 100755
--- a/libs/androidfw/tests/data/overlay/build
+++ b/libs/androidfw/tests/data/overlay/build
@@ -1,4 +1,19 @@
 #!/bin/bash
+#
+# 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.
+#
 
 aapt package -M AndroidManifest.xml -S res -F bundle.apk -f && \
 unzip bundle.apk resources.arsc && \
diff --git a/libs/androidfw/tests/data/overlay/res/values/values.xml b/libs/androidfw/tests/data/overlay/res/values/values.xml
index 227e889..3e1af98 100644
--- a/libs/androidfw/tests/data/overlay/res/values/values.xml
+++ b/libs/androidfw/tests/data/overlay/res/values/values.xml
@@ -1,4 +1,19 @@
 <?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.
+-->
+
 <resources>
     <string name="test2">test2-overlay</string>
     <integer-array name="integerArray1">
diff --git a/libs/androidfw/tests/data/system/R.h b/libs/androidfw/tests/data/system/R.h
index 7a9d3db..27f25fe 100644
--- a/libs/androidfw/tests/data/system/R.h
+++ b/libs/androidfw/tests/data/system/R.h
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
 #ifndef __ANDROID_R_H
 #define __ANDROID_R_H
 
diff --git a/libs/androidfw/tests/data/system/build b/libs/androidfw/tests/data/system/build
index 2a3ac0b..1a70e84 100755
--- a/libs/androidfw/tests/data/system/build
+++ b/libs/androidfw/tests/data/system/build
@@ -1,4 +1,19 @@
 #!/bin/bash
+#
+# 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.
+#
 
 aapt package -x -M AndroidManifest.xml -S res -F bundle.apk -f && \
 unzip bundle.apk resources.arsc && \
diff --git a/libs/androidfw/tests/data/system/res/values/themes.xml b/libs/androidfw/tests/data/system/res/values/themes.xml
index b29848e..35d43c7 100644
--- a/libs/androidfw/tests/data/system/res/values/themes.xml
+++ b/libs/androidfw/tests/data/system/res/values/themes.xml
@@ -1,4 +1,19 @@
 <?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.
+-->
+
 <resources>
     <public name="background" type="attr" id="0x01010000"/>
     <public name="foreground" type="attr" id="0x01010001"/>
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 70ff6e5..40cd13e 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -296,6 +296,9 @@
                 mStagingDisplayListData->children()[i]->mRenderNode->incParentRefCount();
             }
         }
+        // Damage with the old display list first then the new one to catch any
+        // changes in isRenderable or, in the future, bounds
+        damageSelf(info);
         deleteDisplayListData();
         mDisplayListData = mStagingDisplayListData;
         mStagingDisplayListData = NULL;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 3bb4778..9d2ae8b 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -42,7 +42,8 @@
         : mRenderThread(thread)
         , mEglManager(thread.eglManager())
         , mEglSurface(EGL_NO_SURFACE)
-        , mDirtyRegionsEnabled(false)
+        , mBufferPreserved(false)
+        , mSwapBehavior(kSwap_default)
         , mOpaque(!translucent)
         , mCanvas(NULL)
         , mHaveNewSurface(false)
@@ -82,7 +83,8 @@
     }
 
     if (mEglSurface != EGL_NO_SURFACE) {
-        mDirtyRegionsEnabled = mEglManager.enableDirtyRegions(mEglSurface);
+        const bool preserveBuffer = (mSwapBehavior != kSwap_discardBuffer);
+        mBufferPreserved = mEglManager.setPreserveBuffer(mEglSurface, preserveBuffer);
         mHaveNewSurface = true;
         makeCurrent();
     } else {
@@ -103,6 +105,10 @@
     makeCurrent();
 }
 
+void CanvasContext::setSwapBehavior(SwapBehavior swapBehavior) {
+    mSwapBehavior = swapBehavior;
+}
+
 bool CanvasContext::initialize(ANativeWindow* window) {
     setSurface(window);
     if (mCanvas) return false;
@@ -200,7 +206,7 @@
     if (width != mCanvas->getViewportWidth() || height != mCanvas->getViewportHeight()) {
         mCanvas->setViewport(width, height);
         dirty.setEmpty();
-    } else if (!mDirtyRegionsEnabled || mHaveNewSurface) {
+    } else if (!mBufferPreserved || mHaveNewSurface) {
         dirty.setEmpty();
     } else {
         if (!dirty.isEmpty() && !dirty.intersect(0, 0, width, height)) {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index d4282fa..e20564b 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -48,6 +48,11 @@
 
 class EglManager;
 
+enum SwapBehavior {
+    kSwap_default,
+    kSwap_discardBuffer,
+};
+
 // This per-renderer class manages the bridge between the global EGL context
 // and the render surface.
 // TODO: Rename to Renderer or some other per-window, top-level manager
@@ -57,6 +62,9 @@
             IContextFactory* contextFactory);
     virtual ~CanvasContext();
 
+    // Won't take effect until next EGLSurface creation
+    void setSwapBehavior(SwapBehavior swapBehavior);
+
     bool initialize(ANativeWindow* window);
     void updateSurface(ANativeWindow* window);
     void pauseSurface(ANativeWindow* window);
@@ -111,7 +119,8 @@
     EglManager& mEglManager;
     sp<ANativeWindow> mNativeWindow;
     EGLSurface mEglSurface;
-    bool mDirtyRegionsEnabled;
+    bool mBufferPreserved;
+    SwapBehavior mSwapBehavior;
 
     bool mOpaque;
     OpenGLRenderer* mCanvas;
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index a87834e..760fc15 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -70,12 +70,12 @@
         , mEglConfig(0)
         , mEglContext(EGL_NO_CONTEXT)
         , mPBufferSurface(EGL_NO_SURFACE)
-        , mRequestDirtyRegions(load_dirty_regions_property())
+        , mAllowPreserveBuffer(load_dirty_regions_property())
         , mCurrentSurface(EGL_NO_SURFACE)
         , mAtlasMap(NULL)
         , mAtlasMapSize(0) {
-    mCanSetDirtyRegions = mRequestDirtyRegions;
-    ALOGD("Render dirty regions requested: %s", mRequestDirtyRegions ? "true" : "false");
+    mCanSetPreserveBuffer = mAllowPreserveBuffer;
+    ALOGD("Use EGL_SWAP_BEHAVIOR_PRESERVED: %s", mAllowPreserveBuffer ? "true" : "false");
 }
 
 void EglManager::initialize() {
@@ -113,7 +113,7 @@
 }
 
 void EglManager::loadConfig() {
-    EGLint swapBehavior = mCanSetDirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
+    EGLint swapBehavior = mCanSetPreserveBuffer ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
     EGLint attribs[] = {
             EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
             EGL_RED_SIZE, 8,
@@ -131,10 +131,10 @@
     if (!eglChooseConfig(mEglDisplay, attribs, &mEglConfig, num_configs, &num_configs)
             || num_configs != 1) {
         // Failed to get a valid config
-        if (mCanSetDirtyRegions) {
+        if (mCanSetPreserveBuffer) {
             ALOGW("Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...");
             // Try again without dirty regions enabled
-            mCanSetDirtyRegions = false;
+            mCanSetPreserveBuffer = false;
             loadConfig();
         } else {
             LOG_ALWAYS_FATAL("Failed to choose config, error = %s", egl_error_str());
@@ -273,25 +273,30 @@
     return false;
 }
 
-bool EglManager::enableDirtyRegions(EGLSurface surface) {
-    if (!mRequestDirtyRegions) return false;
+bool EglManager::setPreserveBuffer(EGLSurface surface, bool preserve) {
+    if (CC_UNLIKELY(!mAllowPreserveBuffer)) return false;
 
-    if (mCanSetDirtyRegions) {
-        if (!eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED)) {
+    bool preserved = false;
+    if (mCanSetPreserveBuffer) {
+        preserved = eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR,
+                preserve ? EGL_BUFFER_PRESERVED : EGL_BUFFER_DESTROYED);
+        if (CC_UNLIKELY(!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;
+    if (CC_UNLIKELY(!preserved)) {
+        // Maybe it's already set?
+        EGLint swapBehavior;
+        if (eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &swapBehavior)) {
+            preserved = (swapBehavior == EGL_BUFFER_PRESERVED);
+        } else {
+            ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p",
+                                (void*) surface, egl_error_str());
+        }
     }
-    return value == EGL_BUFFER_PRESERVED;
+
+    return preserved;
 }
 
 } /* namespace renderthread */
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index 71213fb..ae03ea1 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -49,7 +49,8 @@
     void beginFrame(EGLSurface surface, EGLint* width, EGLint* height);
     bool swapBuffers(EGLSurface surface);
 
-    bool enableDirtyRegions(EGLSurface surface);
+    // Returns true iff the surface is now preserving buffers.
+    bool setPreserveBuffer(EGLSurface surface, bool preserve);
 
     void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize);
 
@@ -71,8 +72,8 @@
     EGLContext mEglContext;
     EGLSurface mPBufferSurface;
 
-    const bool mRequestDirtyRegions;
-    bool mCanSetDirtyRegions;
+    const bool mAllowPreserveBuffer;
+    bool mCanSetPreserveBuffer;
 
     EGLSurface mCurrentSurface;
 
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 047819d..8f99b4e 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -103,6 +103,18 @@
     post(task);
 }
 
+CREATE_BRIDGE2(setSwapBehavior, CanvasContext* context, SwapBehavior swapBehavior) {
+    args->context->setSwapBehavior(args->swapBehavior);
+    return NULL;
+}
+
+void RenderProxy::setSwapBehavior(SwapBehavior swapBehavior) {
+    SETUP_TASK(setSwapBehavior);
+    args->context = mContext;
+    args->swapBehavior = swapBehavior;
+    post(task);
+}
+
 CREATE_BRIDGE1(loadSystemProperties, CanvasContext* context) {
     bool needsRedraw = false;
     if (Caches::hasInstance()) {
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 678e7e2..dddf0c7 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -31,6 +31,7 @@
 
 #include "../Caches.h"
 #include "../IContextFactory.h"
+#include "CanvasContext.h"
 #include "DrawFrameTask.h"
 
 namespace android {
@@ -44,7 +45,6 @@
 
 namespace renderthread {
 
-class CanvasContext;
 class ErrorChannel;
 class RenderThread;
 class RenderProxyBridge;
@@ -63,6 +63,8 @@
     ANDROID_API virtual ~RenderProxy();
 
     ANDROID_API void setFrameInterval(nsecs_t frameIntervalNanos);
+    // Won't take effect until next EGLSurface creation
+    ANDROID_API void setSwapBehavior(SwapBehavior swapBehavior);
     ANDROID_API bool loadSystemProperties();
 
     ANDROID_API bool initialize(const sp<ANativeWindow>& window);
diff --git a/media/java/android/media/tv/TvContract.java b/media/java/android/media/tv/TvContract.java
index b3890d4..691df77 100644
--- a/media/java/android/media/tv/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -1052,6 +1052,24 @@
             /** The genre for Gaming. */
             public static final String GAMING = "GAMING";
 
+            /** The genre for Arts. */
+            public static final String ARTS = "ARTS";
+
+            /** The genre for Entertainment. */
+            public static final String ENTERTAINMENT = "ENTERTAINMENT";
+
+            /** The genre for Life Style. */
+            public static final String LIFE_STYLE = "LIFE_STYLE";
+
+            /** The genre for Music. */
+            public static final String MUSIC = "MUSIC";
+
+            /** The genre for Premier. */
+            public static final String PREMIER = "PREMIER";
+
+            /** The genre for Tech/Science. */
+            public static final String TECH_SCIENCE = "TECH_SCIENCE";
+
             private static final ArraySet<String> CANONICAL_GENRES = new ArraySet<String>();
             static {
                 CANONICAL_GENRES.add(FAMILY_KIDS);
@@ -1065,6 +1083,12 @@
                 CANONICAL_GENRES.add(ANIMAL_WILDLIFE);
                 CANONICAL_GENRES.add(NEWS);
                 CANONICAL_GENRES.add(GAMING);
+                CANONICAL_GENRES.add(ARTS);
+                CANONICAL_GENRES.add(ENTERTAINMENT);
+                CANONICAL_GENRES.add(LIFE_STYLE);
+                CANONICAL_GENRES.add(MUSIC);
+                CANONICAL_GENRES.add(PREMIER);
+                CANONICAL_GENRES.add(TECH_SCIENCE);
             }
 
             private Genres() {}
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 54ebc6a..b9e99d2 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -241,6 +241,9 @@
             if (DEBUG) {
                 Log.d(TAG, "Setup activity loaded. [" + input.mSetupActivity + "] for " + si.name);
             }
+            if (inputType == TYPE_TUNER && TextUtils.isEmpty(input.mSetupActivity)) {
+                throw new XmlPullParserException("Setup activity not found in " + si.name);
+            }
             input.mSettingsActivity = sa.getString(
                     com.android.internal.R.styleable.TvInputService_settingsActivity);
             if (DEBUG) {
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 819affc6..5d5ea02 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -332,8 +332,13 @@
         }
 
         /**
-         * Sends the change on the track information. This is expected to be called whenever a track
-         * is added/removed and the metadata of a track is modified.
+         * Sends the list of all audio/video/subtitle tracks. The is used by the framework to
+         * maintain the track information for a given session, which in turn is used by
+         * {@link TvView#getTracks} for the application to retrieve metadata for a given track type.
+         * The TV input service must call this method as soon as the track information becomes
+         * available or is updated. Note that in a case where a part of the information for a
+         * certain track is updated, it is not necessary to create a new {@link TvTrackInfo} object
+         * with a different track ID.
          *
          * @param tracks A list which includes track information.
          * @throws IllegalArgumentException if {@code tracks} contains redundant tracks.
@@ -364,8 +369,12 @@
         }
 
         /**
-         * Sends the ID of the selected track for a given track type. This is expected to be called
-         * whenever there is a change on track selection.
+         * Sends the type and ID of a selected track. This is used to inform the application that a
+         * specific track is selected. The TV input service must call this method as soon as a track
+         * is selected either by default or in response to a call to {@link #onSelectTrack}. The
+         * selected track ID for a given type is maintained in the framework until the next call to
+         * this method even after the entire track list is updated (but is reset when the session is
+         * tuned to a new channel), so care must be taken not to result in an obsolete track ID.
          *
          * @param type The type of the selected track. The type can be
          *            {@link TvTrackInfo#TYPE_AUDIO}, {@link TvTrackInfo#TYPE_VIDEO} or
diff --git a/media/java/android/media/tv/TvStreamConfig.java b/media/java/android/media/tv/TvStreamConfig.java
index a7e7e44..1bdc63e 100644
--- a/media/java/android/media/tv/TvStreamConfig.java
+++ b/media/java/android/media/tv/TvStreamConfig.java
@@ -33,7 +33,6 @@
 
     private int mStreamId;
     private int mType;
-    // TODO: Revisit if max widht/height really make sense.
     private int mMaxWidth;
     private int mMaxHeight;
     /**
@@ -166,4 +165,17 @@
             return config;
         }
     }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) return false;
+        if (!(obj instanceof TvStreamConfig)) return false;
+
+        TvStreamConfig config = (TvStreamConfig) obj;
+        return config.mGeneration == mGeneration
+            && config.mStreamId == mStreamId
+            && config.mType == mType
+            && config.mMaxWidth == mMaxWidth
+            && config.mMaxHeight == mMaxHeight;
+    }
 }
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index 0949b1a..92a2a39 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -88,6 +88,10 @@
     private float mStreamVolume;
     private int mVideoWidth = VIDEO_SIZE_VALUE_UNKNOWN;
     private int mVideoHeight = VIDEO_SIZE_VALUE_UNKNOWN;
+    private int mCaptionEnabled;
+    private String mAppPrivateCommandAction;
+    private Bundle mAppPrivateCommandData;
+
     private boolean mSurfaceChanged;
     private int mSurfaceFormat;
     private int mSurfaceWidth;
@@ -100,7 +104,6 @@
     private int mSurfaceViewRight;
     private int mSurfaceViewTop;
     private int mSurfaceViewBottom;
-    private int mCaptionEnabled;
 
     private final SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() {
         @Override
@@ -421,10 +424,10 @@
      * Calls {@link TvInputService.Session#appPrivateCommand(String, Bundle)
      * TvInputService.Session.appPrivateCommand()} on the current TvView.
      *
-     * @param action Name of the command to be performed. This <em>must</em> be a scoped name, i.e.
-     *            prefixed with a package name you own, so that different developers will not create
-     *            conflicting commands.
-     * @param data Any data to include with the command.
+     * @param action The name of the private command to send. This <em>must</em> be a scoped name,
+     *            i.e. prefixed with a package name you own, so that different developers will not
+     *            create conflicting commands.
+     * @param data An optional bundle to send with the command.
      * @hide
      */
     @SystemApi
@@ -434,6 +437,13 @@
         }
         if (mSession != null) {
             mSession.sendAppPrivateCommand(action, data);
+        } else {
+            Log.w(TAG, "sendAppPrivateCommand - session not created (action " + action + " cached)");
+            if (mAppPrivateCommandAction != null) {
+                Log.w(TAG, "previous cached action " + action + " removed");
+            }
+            mAppPrivateCommandAction = action;
+            mAppPrivateCommandData = data;
         }
     }
 
@@ -619,6 +629,9 @@
     }
 
     private void release() {
+        mAppPrivateCommandAction = null;
+        mAppPrivateCommandData = null;
+
         setSessionSurface(null);
         removeSessionOverlayView();
         mUseRequestedSurfaceLayout = false;
@@ -862,6 +875,12 @@
                 if (mHasStreamVolume) {
                     mSession.setStreamVolume(mStreamVolume);
                 }
+                if (mAppPrivateCommandAction != null) {
+                    mSession.sendAppPrivateCommand(
+                            mAppPrivateCommandAction, mAppPrivateCommandData);
+                    mAppPrivateCommandAction = null;
+                    mAppPrivateCommandData = null;
+                }
             } else {
                 mSessionCallback = null;
                 if (mCallback != null) {
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 5646740..3b1b1d7 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -182,7 +182,8 @@
 android_media_MediaRecorder_setAudioSource(JNIEnv *env, jobject thiz, jint as)
 {
     ALOGV("setAudioSource(%d)", as);
-    if (as < AUDIO_SOURCE_DEFAULT || as >= AUDIO_SOURCE_CNT) {
+    if (as < AUDIO_SOURCE_DEFAULT ||
+        (as >= AUDIO_SOURCE_CNT && as != AUDIO_SOURCE_FM_TUNER)) {
         jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid audio source");
         return;
     }
diff --git a/media/tests/omxjpegdecoder/Android.mk b/media/tests/omxjpegdecoder/Android.mk
deleted file mode 100644
index b0bc5d4..0000000
--- a/media/tests/omxjpegdecoder/Android.mk
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright (C) 2009 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := \
-        omx_jpeg_decoder.cpp \
-        jpeg_decoder_bench.cpp \
-        StreamSource.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-    libskia \
-    libstagefright \
-    libstagefright_foundation \
-    libbinder \
-    libutils \
-    liblog \
-    libjpeg
-
-LOCAL_C_INCLUDES := \
-    $(TOP)/external/jpeg \
-    $(TOP)/frameworks/base/media/libstagefright \
-    $(TOP)/frameworks/base/include/ \
-    $(TOP)/frameworks/base/ \
-    $(TOP)/frameworks/native/include/media/openmax
-
-LOCAL_MODULE := jpeg_bench
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_EXECUTABLE)
diff --git a/media/tests/omxjpegdecoder/StreamSource.cpp b/media/tests/omxjpegdecoder/StreamSource.cpp
deleted file mode 100644
index f764121a..0000000
--- a/media/tests/omxjpegdecoder/StreamSource.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <media/stagefright/foundation/ADebug.h>
-
-#include "StreamSource.h"
-
-namespace android {
-
-StreamSource::StreamSource(SkStream *stream)
-        : mStream(stream) {
-    CHECK(stream != NULL);
-    mSize = stream->getLength();
-}
-
-StreamSource::~StreamSource() {
-    delete mStream;
-    mStream = NULL;
-}
-
-status_t StreamSource::initCheck() const {
-    return mStream != NULL ? OK : NO_INIT;
-}
-
-ssize_t StreamSource::readAt(off64_t offset, void *data, size_t size) {
-    Mutex::Autolock autoLock(mLock);
-
-    mStream->rewind();
-    mStream->skip(offset);
-    ssize_t result = mStream->read(data, size);
-
-    return result;
-}
-
-status_t StreamSource::getSize(off64_t *size) {
-      *size = mSize;
-      return OK;
-}
-
-}  // namespace android
diff --git a/media/tests/omxjpegdecoder/StreamSource.h b/media/tests/omxjpegdecoder/StreamSource.h
deleted file mode 100644
index 9807385..0000000
--- a/media/tests/omxjpegdecoder/StreamSource.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef STREAM_SOURCE_H_
-
-#define STREAM_SOURCE_H_
-
-#include <stdio.h>
-
-#include <SkStream.h>
-#include <media/stagefright/DataSource.h>
-#include <media/stagefright/MediaErrors.h>
-#include <utils/threads.h>
-
-namespace android {
-
-class StreamSource : public DataSource {
-public:
-    // Pass the ownership of SkStream to StreamSource.
-    StreamSource(SkStream *SkStream);
-    virtual status_t initCheck() const;
-    virtual ssize_t readAt(off64_t offset, void *data, size_t size);
-    virtual status_t getSize(off64_t *size);
-
-protected:
-    virtual ~StreamSource();
-
-private:
-    SkStream *mStream;
-    size_t mSize;
-    Mutex mLock;
-
-    StreamSource(const StreamSource &);
-    StreamSource &operator=(const StreamSource &);
-};
-
-}  // namespace android
-
-#endif  // STREAM_SOURCE_H_
diff --git a/media/tests/omxjpegdecoder/jpeg_decoder_bench.cpp b/media/tests/omxjpegdecoder/jpeg_decoder_bench.cpp
deleted file mode 100644
index de6294d..0000000
--- a/media/tests/omxjpegdecoder/jpeg_decoder_bench.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "OmxJpegDecoder"
-#include <sys/time.h>
-#include <utils/Log.h>
-
-#include <binder/ProcessState.h>
-
-#include "SkBitmap.h"
-#include "SkImageDecoder.h"
-#include "SkStream.h"
-#include "omx_jpeg_decoder.h"
-
-class SkJPEGImageDecoder : public SkImageDecoder {
-public:
-    virtual Format getFormat() const {
-        return kJPEG_Format;
-    }
-
-protected:
-    virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode);
-};
-
-int nullObjectReturn(const char msg[]) {
-    if (msg) {
-        SkDebugf("--- %s\n", msg);
-    }
-    return -1;
-}
-
-static int64_t getNowUs() {
-    struct timeval tv;
-    gettimeofday(&tv, NULL);
-
-    return tv.tv_usec + (int64_t) tv.tv_sec * 1000000;
-}
-
-int testDecodeBounds(SkImageDecoder* decoder, SkStream* stream,
-        SkBitmap* bitmap) {
-    int64_t startTime = getNowUs();
-    SkColorType prefColorType = kN32_SkColorType;
-    SkImageDecoder::Mode decodeMode = SkImageDecoder::kDecodeBounds_Mode;
-
-    // Decode the input stream and then use the bitmap.
-    if (!decoder->decode(stream, bitmap, prefColorType, decodeMode)) {
-        return nullObjectReturn("decoder->decode returned false");
-    } else {
-        int64_t delay = getNowUs() - startTime;
-        printf("WidthxHeight: %dx%d\n", bitmap->width(), bitmap->height());
-        printf("Decoding Time in BoundsMode %.1f msec.\n", delay / 1000.0f);
-        return 0;
-    }
-}
-
-int testDecodePixels(SkImageDecoder* decoder, SkStream* stream,
-        SkBitmap* bitmap) {
-    int64_t startTime = getNowUs();
-    SkColorType prefColorType = kN32_SkColorType;
-    SkImageDecoder::Mode decodeMode = SkImageDecoder::kDecodePixels_Mode;
-
-    // Decode the input stream and then use the bitmap.
-    if (!decoder->decode(stream, bitmap, prefColorType, decodeMode)) {
-        return nullObjectReturn("decoder->decode returned false");
-    } else {
-        int64_t delay = getNowUs() - startTime;
-        printf("Decoding Time in PixelsMode %.1f msec.\n", delay / 1000.0f);
-        const char* filename = "/sdcard/omxJpegDecodedBitmap.rgba";
-        return storeBitmapToFile(bitmap, filename);
-    }
-}
-
-int testDecoder(SkImageDecoder* decoder, char* filename) {
-    // test DecodeMode == Pixels
-    SkStream* stream = new SkFILEStream(filename);
-    SkBitmap* bitmap = new SkBitmap;
-    testDecodePixels(decoder, stream, bitmap);
-    delete bitmap;
-
-    // test DecodeMode == Bounds
-    stream = new SkFILEStream(filename);
-    bitmap = new SkBitmap;
-    testDecodeBounds(decoder, stream, bitmap);
-    delete bitmap;
-
-    delete decoder;
-    return 0;
-}
-
-int main(int argc, char** argv) {
-    android::ProcessState::self()->startThreadPool();
-
-    printf("Decoding jpeg with libjpeg...\n");
-    SkJPEGImageDecoder* libjpeg = new SkJPEGImageDecoder;
-    testDecoder(libjpeg, argv[1]);
-
-    printf("\nDecoding jpeg with OMX...\n");
-    OmxJpegImageDecoder* omx = new OmxJpegImageDecoder;
-    testDecoder(omx, argv[1]);
-    return 0;
-}
diff --git a/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp b/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp
deleted file mode 100644
index 229bfdb..0000000
--- a/media/tests/omxjpegdecoder/omx_jpeg_decoder.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "OmxJpegDecoder"
-#include <sys/time.h>
-#include <utils/Log.h>
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <binder/IServiceManager.h>
-#include <binder/ProcessState.h>
-#include <media/IMediaPlayerService.h>
-#include <media/stagefright/foundation/ADebug.h>
-#include <media/stagefright/MediaSource.h>
-#include <media/stagefright/MetaData.h>
-#include <media/stagefright/OMXClient.h>
-#include <media/stagefright/OMXCodec.h>
-#include <SkImage.h>
-#include <SkMallocPixelRef.h>
-
-#include "omx_jpeg_decoder.h"
-#include "StreamSource.h"
-
-using namespace android;
-
-static void getJpegOutput(MediaBuffer* buffer, const char* filename) {
-    int size = buffer->range_length();
-    int offset = buffer->range_offset();
-    FILE *pFile = fopen(filename, "w+");
-
-    if (pFile == NULL) {
-        printf("Error: cannot open %s.\n", filename);
-    } else {
-        char* data = (char*) buffer->data();
-        data += offset;
-        while (size > 0) {
-            int numChars = fwrite(data, sizeof(char), 1024, pFile);
-            int numBytes = numChars * sizeof(char);
-            size -= numBytes;
-            data += numBytes;
-        }
-        fclose(pFile);
-    }
-    return;
-}
-
-extern int storeBitmapToFile(SkBitmap* bitmap, const char* filename) {
-    bitmap->lockPixels();
-    uint8_t* data = (uint8_t *)bitmap->getPixels();
-    int size = bitmap->getSize();
-    FILE* fp = fopen(filename, "w+");
-
-    if (NULL == fp) {
-        printf("Cannot open the output file! \n");
-        return -1;
-    } else {
-        while (size > 0) {
-            int numChars = fwrite(data, sizeof(char), 1024, fp);
-            int numBytes = numChars * sizeof(char);
-            size -= numBytes;
-            data += numBytes;
-        }
-        fclose(fp);
-    }
-    return 0;
-}
-
-static int64_t getNowUs() {
-    struct timeval tv;
-    gettimeofday(&tv, NULL);
-
-    return (int64_t)tv.tv_usec + tv.tv_sec * 1000000;
-}
-
-OmxJpegImageDecoder::OmxJpegImageDecoder() {
-    status_t err = mClient.connect();
-    CHECK_EQ(err, (status_t)OK);
-}
-
-OmxJpegImageDecoder::~OmxJpegImageDecoder() {
-    mClient.disconnect();
-}
-
-bool OmxJpegImageDecoder::onDecode(SkStream* stream,
-        SkBitmap* bm, Mode mode) {
-    sp<MediaSource> source = prepareMediaSource(stream);
-    sp<MetaData> meta = source->getFormat();
-    int width;
-    int height;
-    meta->findInt32(kKeyWidth, &width);
-    meta->findInt32(kKeyHeight, &height);
-    configBitmapSize(
-            bm, getPrefColorType(k32Bit_SrcDepth, false),
-            width, height);
-
-    // mode == DecodeBounds
-    if (mode == SkImageDecoder::kDecodeBounds_Mode) {
-        return true;
-    }
-
-    // mode == DecodePixels
-    if (!this->allocPixelRef(bm, NULL)) {
-        ALOGI("Cannot allocPixelRef()!");
-        return false;
-    }
-
-    sp<MediaSource> decoder = getDecoder(&mClient, source);
-    return decodeSource(decoder, source, bm);
-}
-
-JPEGSource* OmxJpegImageDecoder::prepareMediaSource(SkStream* stream) {
-    DataSource::RegisterDefaultSniffers();
-    sp<DataSource> dataSource = new StreamSource(stream);
-    return new JPEGSource(dataSource);
-}
-
-sp<MediaSource> OmxJpegImageDecoder::getDecoder(
-        OMXClient *client, const sp<MediaSource>& source) {
-    sp<MetaData> meta = source->getFormat();
-    sp<MediaSource> decoder = OMXCodec::Create(
-            client->interface(), meta, false /* createEncoder */, source);
-
-    CHECK(decoder != NULL);
-    return decoder;
-}
-
-bool OmxJpegImageDecoder::decodeSource(sp<MediaSource> decoder,
-        const sp<MediaSource>& source, SkBitmap* bm) {
-    status_t rt = decoder->start();
-    if (rt != OK) {
-        ALOGE("Cannot start OMX Decoder!");
-        return false;
-    }
-    int64_t startTime = getNowUs();
-    MediaBuffer *buffer;
-
-    // decode source
-    status_t err = decoder->read(&buffer, NULL);
-    int64_t duration = getNowUs() - startTime;
-
-    if (err != OK) {
-        CHECK(buffer == NULL);
-    }
-    printf("Duration in decoder->read(): %.1f (msecs). \n",
-                duration / 1E3 );
-
-    // Copy pixels from buffer to bm.
-    // May need to check buffer->rawBytes() == bm->rawBytes().
-    CHECK_EQ(buffer->size(), bm->getSize());
-    memcpy(bm->getPixels(), buffer->data(), buffer->size());
-    buffer->release();
-    decoder->stop();
-
-    return true;
-}
-
-void OmxJpegImageDecoder::configBitmapSize(SkBitmap* bm, SkColorType pref,
-        int width, int height) {
-    // Set the color space to ARGB_8888 for now (ignoring pref)
-    // because of limitation in hardware support.
-    bm->setInfo(SkImageInfo::MakeN32(width, height, kOpaque_SkAlphaType));
-}
diff --git a/media/tests/omxjpegdecoder/omx_jpeg_decoder.h b/media/tests/omxjpegdecoder/omx_jpeg_decoder.h
deleted file mode 100644
index e487245..0000000
--- a/media/tests/omxjpegdecoder/omx_jpeg_decoder.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef OMXJPEGIMAGEDECODER
-#define OMXJPEGIMAGEDECODER
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <media/stagefright/JPEGSource.h>
-#include <media/stagefright/MediaSource.h>
-#include <media/stagefright/OMXClient.h>
-#include <media/stagefright/OMXCodec.h>
-#include <SkImageDecoder.h>
-#include <SkStream.h>
-
-using namespace android;
-
-extern int storeBitmapToFile(SkBitmap* bitmap, const char* filename);
-
-class OmxJpegImageDecoder : public SkImageDecoder {
-public:
-    OmxJpegImageDecoder();
-    ~OmxJpegImageDecoder();
-
-    virtual Format getFormat() const {
-        return kJPEG_Format;
-    }
-
-protected:
-    virtual bool onDecode(SkStream* stream, SkBitmap* bm, Mode mode);
-
-private:
-    JPEGSource* prepareMediaSource(SkStream* stream);
-    sp<MediaSource> getDecoder(OMXClient* client, const sp<MediaSource>& source);
-    bool decodeSource(sp<MediaSource> decoder, const sp<MediaSource>& source,
-            SkBitmap* bm);
-    void configBitmapSize(SkBitmap* bm, SkColorType, int width, int height);
-
-    OMXClient mClient;
-};
-
-#endif
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
index 8a65a2e..02d2715 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/FusedPrintersProvider.java
@@ -48,6 +48,7 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -91,14 +92,14 @@
         mPersistenceManager.addPrinterAndWritePrinterHistory(printer);
     }
 
-    private void computeAndDeliverResult(ArrayMap<PrinterId, PrinterInfo> discoveredPrinters,
-            ArrayMap<PrinterId, PrinterInfo> favoritePrinters) {
+    private void computeAndDeliverResult(Map<PrinterId, PrinterInfo> discoveredPrinters,
+            List<PrinterInfo> favoritePrinters) {
         List<PrinterInfo> printers = new ArrayList<>();
 
         // Add the updated favorite printers.
         final int favoritePrinterCount = favoritePrinters.size();
         for (int i = 0; i < favoritePrinterCount; i++) {
-            PrinterInfo favoritePrinter = favoritePrinters.valueAt(i);
+            PrinterInfo favoritePrinter = favoritePrinters.get(i);
             PrinterInfo updatedPrinter = discoveredPrinters.remove(
                     favoritePrinter.getId());
             if (updatedPrinter != null) {
@@ -215,21 +216,14 @@
         // printer to use its current name instead of the historical one.
         mPersistenceManager.updatePrintersHistoricalNamesIfNeeded(printers);
 
-        ArrayMap<PrinterId, PrinterInfo> printersMap = new ArrayMap<>();
+        Map<PrinterId, PrinterInfo> printersMap = new LinkedHashMap<>();
         final int printerCount = printers.size();
         for (int i = 0; i < printerCount; i++) {
             PrinterInfo printer = printers.get(i);
             printersMap.put(printer.getId(), printer);
         }
 
-        ArrayMap<PrinterId, PrinterInfo> favoritePrintersMap = new ArrayMap<>();
-        final int favoritePrinterCount = favoritePrinters.size();
-        for (int i = 0; i < favoritePrinterCount; i++) {
-            PrinterInfo favoritePrinter = favoritePrinters.get(i);
-            favoritePrintersMap.put(favoritePrinter.getId(), favoritePrinter);
-        }
-
-        computeAndDeliverResult(printersMap, favoritePrintersMap);
+        computeAndDeliverResult(printersMap, favoritePrinters);
     }
 
     @Override
@@ -544,7 +538,7 @@
                 mReadHistoryCompleted = true;
 
                 // Deliver the printers.
-                updatePrinters(mDiscoverySession.getPrinters(), mHistoricalPrinters);
+                updatePrinters(mDiscoverySession.getPrinters(), mFavoritePrinters);
 
                 // Loading the available printers if needed.
                 loadInternal();
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 01ea3c8..21c8b83 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -1412,12 +1412,16 @@
             mCopiesEditText.setEnabled(true);
             mCopiesEditText.setFocusableInTouchMode(true);
         } else {
+            CharSequence text = mCopiesEditText.getText();
+            if (TextUtils.isEmpty(text) || !MIN_COPIES_STRING.equals(text.toString())) {
+                mCopiesEditText.setText(MIN_COPIES_STRING);
+            }
             mCopiesEditText.setEnabled(false);
             mCopiesEditText.setFocusable(false);
         }
         if (mCopiesEditText.getError() == null
                 && TextUtils.isEmpty(mCopiesEditText.getText())) {
-            mCopiesEditText.setText(String.valueOf(MIN_COPIES));
+            mCopiesEditText.setText(MIN_COPIES_STRING);
             mCopiesEditText.requestFocus();
         }
     }
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index efba03d..16c6075 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -21,6 +21,7 @@
     <integer name="def_screen_off_timeout">60000</integer>
     <integer name="def_sleep_timeout">-1</integer>
     <bool name="def_airplane_mode_on">false</bool>
+    <bool name="def_theater_mode_on">false</bool>
     <!-- Comma-separated list of bluetooth, wifi, and cell. -->
     <string name="def_airplane_mode_radios" translatable="false">cell,bluetooth,wifi,nfc,wimax</string>
     <string name="airplane_mode_toggleable_radios" translatable="false">bluetooth,wifi,nfc</string>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 8c51caf..e56806a 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -71,7 +71,7 @@
     // database gets upgraded properly. At a minimum, please confirm that 'upgradeVersion'
     // is properly propagated through your change.  Not doing so will result in a loss of user
     // settings.
-    private static final int DATABASE_VERSION = 114;
+    private static final int DATABASE_VERSION = 116;
 
     private Context mContext;
     private int mUserHandle;
@@ -1828,20 +1828,43 @@
             upgradeVersion = 113;
         }
 
-        if (upgradeVersion < 114) {
-            db.beginTransaction();
-            SQLiteStatement stmt = null;
-            try {
-                stmt = db.compileStatement("INSERT OR IGNORE INTO global(name,value)"
-                        + " VALUES(?,?);");
-                loadSetting(stmt, Settings.Global.VOLTE_VT_ENABLED, ImsConfig.FeatureValueConstants.ON);
-                db.setTransactionSuccessful();
-            } finally {
-                db.endTransaction();
-                if (stmt != null) stmt.close();
+        // We skipped 114 to handle a merge conflict with the introduction of theater mode.
+
+        if (upgradeVersion < 115) {
+            if (mUserHandle == UserHandle.USER_OWNER) {
+                db.beginTransaction();
+                SQLiteStatement stmt = null;
+                try {
+                    stmt = db.compileStatement("INSERT OR IGNORE INTO global(name,value)"
+                            + " VALUES(?,?);");
+                    loadBooleanSetting(stmt, Global.THEATER_MODE_ON,
+                            R.bool.def_theater_mode_on);
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                    if (stmt != null) stmt.close();
+                }
             }
-            upgradeVersion = 114;
+            upgradeVersion = 115;
         }
+
+        if (upgradeVersion < 116) {
+            if (mUserHandle == UserHandle.USER_OWNER) {
+                db.beginTransaction();
+                SQLiteStatement stmt = null;
+                try {
+                    stmt = db.compileStatement("INSERT OR IGNORE INTO global(name,value)"
+                            + " VALUES(?,?);");
+                    loadSetting(stmt, Settings.Global.ENHANCED_4G_MODE_ENABLED, ImsConfig.FeatureValueConstants.ON);
+                    db.setTransactionSuccessful();
+                } finally {
+                    db.endTransaction();
+                    if (stmt != null) stmt.close();
+                }
+            }
+            upgradeVersion = 116;
+        }
+
         // *** Remember to update DATABASE_VERSION above!
 
         if (upgradeVersion != currentVersion) {
@@ -2438,6 +2461,9 @@
             loadBooleanSetting(stmt, Settings.Global.AIRPLANE_MODE_ON,
                     R.bool.def_airplane_mode_on);
 
+            loadBooleanSetting(stmt, Settings.Global.THEATER_MODE_ON,
+                    R.bool.def_theater_mode_on);
+
             loadStringSetting(stmt, Settings.Global.AIRPLANE_MODE_RADIOS,
                     R.string.def_airplane_mode_radios);
 
@@ -2584,7 +2610,7 @@
 
             loadBooleanSetting(stmt, Settings.Global.GUEST_USER_ENABLED,
                     R.bool.def_guest_user_enabled);
-            loadSetting(stmt, Settings.Global.VOLTE_VT_ENABLED, ImsConfig.FeatureValueConstants.ON);
+            loadSetting(stmt, Settings.Global.ENHANCED_4G_MODE_ENABLED, ImsConfig.FeatureValueConstants.ON);
             // --- New global settings start here
         } finally {
             if (stmt != null) stmt.close();
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 7e6afa6..3c44245 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -92,6 +92,7 @@
     <uses-permission android:name="android.permission.FRAME_STATS" />
     <uses-permission android:name="android.permission.BIND_APPWIDGET" />
     <uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
+    <uses-permission android:name="android.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS"/>
 
     <application android:label="@string/app_label">
         <provider
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index aaa350c..4f867a0 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -252,5 +252,8 @@
 
     <!-- Zen toast visibility duration -->
     <integer name="zen_toast_visible_duration">500</integer>
+
+    <!-- Enable the default volume dialog -->
+    <bool name="enable_volume_ui">true</bool>
 </resources>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 89bbacf..7a0d655 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -657,8 +657,8 @@
     <string name="recents_empty_message">Your recent screens appear here</string>
     <!-- Recents: The info panel app info button string. [CHAR LIMIT=NONE] -->
     <string name="recents_app_info_button_label">Application Info</string>
-    <!-- Recents: The lock-to-app button. [CHAR LIMIT=NONE] -->
-    <string name="recents_lock_to_app_button_label">lock to app</string>
+    <!-- Recents: The screen pinning button. [CHAR LIMIT=NONE] -->
+    <string name="recents_lock_to_app_button_label">screen pinning</string>
     <!-- Recents: Temporary string for the button in the recents search bar. [CHAR LIMIT=NONE] -->
     <string name="recents_search_bar_label">search</string>
     <!-- Recents: Launch error string. [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index f5e5517..7c74246 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -69,6 +69,7 @@
 import android.view.ViewAnimationUtils;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
+import android.view.ViewParent;
 import android.view.ViewStub;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
@@ -266,6 +267,7 @@
             if (DEBUG) {
                 Log.v(TAG, "Notification click handler invoked for intent: " + pendingIntent);
             }
+            logActionClick(view);
             // The intent we are sending is for the application, which
             // won't have permission to immediately start an activity after
             // the user switches to home.  We know it is safe to do at this
@@ -308,6 +310,37 @@
             }
         }
 
+        private void logActionClick(View view) {
+            ViewParent parent = view.getParent();
+            String key = getNotificationKeyForParent(parent);
+            if (key == null) {
+                Log.w(TAG, "Couldn't determine notification for click.");
+                return;
+            }
+            int index = -1;
+            // If this is a default template, determine the index of the button.
+            if (view.getId() == com.android.internal.R.id.action0 &&
+                    parent != null && parent instanceof ViewGroup) {
+                ViewGroup actionGroup = (ViewGroup) parent;
+                index = actionGroup.indexOfChild(view);
+            }
+            try {
+                mBarService.onNotificationActionClick(key, index);
+            } catch (RemoteException e) {
+                // Ignore
+            }
+        }
+
+        private String getNotificationKeyForParent(ViewParent parent) {
+            while (parent != null) {
+                if (parent instanceof ExpandableNotificationRow) {
+                    return ((ExpandableNotificationRow) parent).getStatusBarNotification().getKey();
+                }
+                parent = parent.getParent();
+            }
+            return null;
+        }
+
         private boolean superOnClickHandler(View view, PendingIntent pendingIntent,
                 Intent fillInIntent) {
             return super.onClickHandler(view, pendingIntent, fillInIntent);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 9196dc8..556c423 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -158,6 +158,7 @@
     public void resetHeight() {
         mMaxExpandHeight = 0;
         mWasReset = true;
+        mActualHeight = 0;
         onHeightReset();
         requestLayout();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index a6fccb6..c19bdff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -802,6 +802,7 @@
             requestPanelHeightUpdate();
             mNotificationStackScroller.setInterceptDelegateEnabled(expanded);
             mStatusBar.setQsExpanded(expanded);
+            mQsPanel.setExpanded(expanded);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index f74d2f4..3efaaff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -236,4 +236,8 @@
     public void onExpandingFinished() {
 
     }
+
+    public void onClosingFinished() {
+
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index a7ff0bd..0ddda8a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -68,7 +68,6 @@
     protected int mTouchSlop;
     protected boolean mHintAnimationRunning;
     private boolean mOverExpandedBeforeFling;
-    private float mOriginalIndicationY;
     private boolean mTouchAboveFalsingThreshold;
     private int mUnlockFalsingThreshold;
 
@@ -107,7 +106,7 @@
     };
 
     protected void onExpandingFinished() {
-        mClosing = false;
+        endClosing();
         mBar.onExpandingFinished();
     }
 
@@ -250,9 +249,7 @@
                 trackMovement(event);
                 if (!waitForTouchSlop || (mHeightAnimator != null && !mHintAnimationRunning) ||
                         mPeekPending || mPeekAnimator != null) {
-                    if (mHeightAnimator != null) {
-                        mHeightAnimator.cancel(); // end any outstanding animations
-                    }
+                    cancelHeightAnimator();
                     cancelPeek();
                     mTouchSlopExceeded = (mHeightAnimator != null && !mHintAnimationRunning)
                             || mPeekPending || mPeekAnimator != null;
@@ -293,9 +290,7 @@
                             mInitialTouchY = y;
                             h = 0;
                         }
-                        if (mHeightAnimator != null) {
-                            mHeightAnimator.cancel(); // end any outstanding animations
-                        }
+                        cancelHeightAnimator();
                         removeCallbacks(mPeekRunnable);
                         mPeekPending = false;
                         onTrackingStarted();
@@ -372,7 +367,7 @@
     }
 
     protected void onTrackingStarted() {
-        mClosing = false;
+        endClosing();
         mTracking = true;
         mCollapseAfterPeek = false;
         mBar.onTrackingStarted(PanelView.this);
@@ -407,9 +402,7 @@
                 mStatusBar.userActivity();
                 if (mHeightAnimator != null && !mHintAnimationRunning ||
                         mPeekPending || mPeekAnimator != null) {
-                    if (mHeightAnimator != null) {
-                        mHeightAnimator.cancel(); // end any outstanding animations
-                    }
+                    cancelHeightAnimator();
                     cancelPeek();
                     mTouchSlopExceeded = true;
                     return true;
@@ -441,9 +434,7 @@
                 trackMovement(event);
                 if (scrolledToBottom) {
                     if (h < -mTouchSlop && h < -Math.abs(x - mInitialTouchX)) {
-                        if (mHeightAnimator != null) {
-                            mHeightAnimator.cancel();
-                        }
+                        cancelHeightAnimator();
                         mInitialOffsetOnTouch = mExpandedHeight;
                         mInitialTouchY = y;
                         mInitialTouchX = x;
@@ -461,6 +452,20 @@
         return false;
     }
 
+    private void cancelHeightAnimator() {
+        if (mHeightAnimator != null) {
+            mHeightAnimator.cancel();
+        }
+        endClosing();
+    }
+
+    private void endClosing() {
+        if (mClosing) {
+            mClosing = false;
+            onClosingFinished();
+        }
+    }
+
     private void initVelocityTracker() {
         if (mVelocityTracker != null) {
             mVelocityTracker.recycle();
@@ -700,9 +705,7 @@
                 mPeekRunnable.run();
             }
         } else if (!isFullyCollapsed() && !mTracking && !mClosing) {
-            if (mHeightAnimator != null) {
-                mHeightAnimator.cancel();
-            }
+            cancelHeightAnimator();
             mClosing = true;
             notifyExpandingStarted();
             if (delayed) {
@@ -785,13 +788,16 @@
 
     private void abortAnimations() {
         cancelPeek();
-        if (mHeightAnimator != null) {
-            mHeightAnimator.cancel();
-        }
+        cancelHeightAnimator();
         removeCallbacks(mPostCollapseRunnable);
         removeCallbacks(mFlingCollapseRunnable);
     }
 
+    protected void onClosingFinished() {
+        mBar.onClosingFinished();
+    }
+
+
     protected void startUnlockHintAnimation() {
 
         // We don't need to hint the user if an animation is already running or the user is changing
@@ -841,16 +847,15 @@
         });
         animator.start();
         mHeightAnimator = animator;
-        mOriginalIndicationY = mKeyguardBottomArea.getIndicationView().getY();
         mKeyguardBottomArea.getIndicationView().animate()
-                .y(mOriginalIndicationY - mHintDistance)
+                .translationY(-mHintDistance)
                 .setDuration(250)
                 .setInterpolator(mFastOutSlowInInterpolator)
                 .withEndAction(new Runnable() {
                     @Override
                     public void run() {
                         mKeyguardBottomArea.getIndicationView().animate()
-                                .y(mOriginalIndicationY)
+                                .translationY(0)
                                 .setDuration(450)
                                 .setInterpolator(mBounceInterpolator)
                                 .start();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index e5c9bdd..be27ddc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -801,7 +801,9 @@
         }
         mUserInfoController = new UserInfoController(mContext);
         mVolumeComponent = getComponent(VolumeComponent.class);
-        mZenModeController = mVolumeComponent.getZenController();
+        if (mVolumeComponent != null) {
+            mZenModeController = mVolumeComponent.getZenController();
+        }
         mCastController = new CastControllerImpl(mContext);
         final SignalClusterView signalCluster =
                 (SignalClusterView) mStatusBarView.findViewById(R.id.signal_cluster);
@@ -3793,6 +3795,10 @@
         runPostCollapseRunnables();
     }
 
+    public void onClosingFinished() {
+        runPostCollapseRunnables();
+    }
+
     public void onUnlockHintStarted() {
         mKeyguardIndicationController.showTransientIndication(R.string.keyguard_unlock);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 6411fb8..e4eae38 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -20,7 +20,6 @@
 import android.content.res.Resources;
 import android.util.AttributeSet;
 import android.util.EventLog;
-import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
@@ -152,6 +151,12 @@
     }
 
     @Override
+    public void onClosingFinished() {
+        super.onClosingFinished();
+        mBar.onClosingFinished();
+    }
+
+    @Override
     public void onTrackingStopped(PanelView panel, boolean expand) {
         super.onTrackingStopped(panel, expand);
         mBar.onTrackingStopped(expand);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
index ca853a9..247252c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarHeaderView.java
@@ -302,9 +302,6 @@
         updateSystemIconsLayoutParams();
         updateClickTargets();
         updateMultiUserSwitch();
-        if (mQSPanel != null) {
-            mQSPanel.setExpanded(mExpanded);
-        }
         updateClockScale();
         updateAvatarScale();
         updateClockLp();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index eb808c2..5c7909a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -571,6 +571,9 @@
                 cancel();
             } else {
                 dismiss();
+                if (ActivityManager.isUserAMonkey()) {
+                    return;
+                }
                 UserInfo user = mUserManager.createSecondaryUser(
                         mContext.getString(R.string.user_new_user_name), 0 /* flags */);
                 if (user == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
index 0586a83..0fe6d89 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeUI.java
@@ -1,7 +1,6 @@
 package com.android.systemui.volume;
 
 import android.content.Context;
-import android.content.Intent;
 import android.content.res.Configuration;
 import android.database.ContentObserver;
 import android.media.AudioManager;
@@ -11,13 +10,10 @@
 import android.media.session.MediaController;
 import android.media.session.MediaSessionManager;
 import android.net.Uri;
-import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.RemoteException;
-import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Log;
-import android.view.WindowManagerGlobal;
 
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
@@ -53,6 +49,7 @@
 
     private final Handler mHandler = new Handler();
 
+    private boolean mEnabled;
     private AudioManager mAudioManager;
     private MediaSessionManager mMediaSessionManager;
     private VolumeController mVolumeController;
@@ -63,6 +60,8 @@
 
     @Override
     public void start() {
+        mEnabled = mContext.getResources().getBoolean(R.bool.enable_volume_ui);
+        if (!mEnabled) return;
         mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
         mMediaSessionManager = (MediaSessionManager) mContext
                 .getSystemService(Context.MEDIA_SESSION_SERVICE);
@@ -84,6 +83,7 @@
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.print("mEnabled="); pw.println(mEnabled);
         if (mPanel != null) {
             mPanel.dump(fd, pw, args);
         }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 9c81f0a..1ed61fd 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -3342,9 +3342,9 @@
         final boolean noActionBar = !hasFeature(FEATURE_ACTION_BAR) || hasFeature(FEATURE_NO_TITLE);
 
         if (targetPreHoneycomb || (targetPreIcs && targetHcNeedsOptions && noActionBar)) {
-            addFlags(WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY);
+            setNeedsMenuKey(WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE);
         } else {
-            clearFlags(WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY);
+            setNeedsMenuKey(WindowManager.LayoutParams.NEEDS_MENU_SET_FALSE);
         }
 
         // Non-floating windows on high end devices must put up decor beneath the system bars and
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 6b9d95d..558cf56 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -503,6 +503,14 @@
     // What we do when the user double-taps on home
     private int mDoubleTapOnHomeBehavior;
 
+    // Allowed theater mode wake actions
+    private boolean mAllowTheaterModeWakeFromKey;
+    private boolean mAllowTheaterModeWakeFromPowerKey;
+    private boolean mAllowTheaterModeWakeFromMotion;
+    private boolean mAllowTheaterModeWakeFromCameraLens;
+    private boolean mAllowTheaterModeWakeFromLidSwitch;
+    private boolean mAllowTheaterModeWakeFromWakeGesture;
+
     // Screenshot trigger states
     // Time to volume and power must be pressed within this interval of each other.
     private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150;
@@ -656,7 +664,7 @@
             synchronized (mLock) {
                 if (shouldEnableWakeGestureLp()) {
                     performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
-                    mPowerManager.wakeUp(SystemClock.uptimeMillis());
+                    wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture);
                 }
             }
         }
@@ -1022,6 +1030,21 @@
                 com.android.internal.R.bool.config_lidControlsSleep);
         mTranslucentDecorEnabled = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_enableTranslucentDecor);
+
+        mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_allowTheaterModeWakeFromKey);
+        mAllowTheaterModeWakeFromPowerKey = mAllowTheaterModeWakeFromKey
+                || mContext.getResources().getBoolean(
+                    com.android.internal.R.bool.config_allowTheaterModeWakeFromPowerKey);
+        mAllowTheaterModeWakeFromMotion = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_allowTheaterModeWakeFromMotion);
+        mAllowTheaterModeWakeFromCameraLens = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_allowTheaterModeWakeFromCameraLens);
+        mAllowTheaterModeWakeFromLidSwitch = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_allowTheaterModeWakeFromLidSwitch);
+        mAllowTheaterModeWakeFromWakeGesture = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_allowTheaterModeWakeFromGesture);
+
         readConfigurationDependentBehaviors();
 
         mAccessibilityManager = (AccessibilityManager) context.getSystemService(
@@ -1408,6 +1431,7 @@
             case TYPE_WALLPAPER:
             case TYPE_PRIVATE_PRESENTATION:
             case TYPE_VOICE_INTERACTION:
+            case TYPE_ACCESSIBILITY_OVERLAY:
                 // The window manager will check these.
                 break;
             case TYPE_PHONE:
@@ -1637,15 +1661,18 @@
             // the drag layer: input for drag-and-drop is associated with this window,
             // which sits above all other focusable windows
             return 25;
-        case TYPE_SECURE_SYSTEM_OVERLAY:
+        case TYPE_ACCESSIBILITY_OVERLAY:
+            // overlay put by accessibility services to intercept user interaction
             return 26;
-        case TYPE_BOOT_PROGRESS:
+        case TYPE_SECURE_SYSTEM_OVERLAY:
             return 27;
+        case TYPE_BOOT_PROGRESS:
+            return 28;
         case TYPE_POINTER:
             // the (mouse) pointer layer
-            return 28;
-        case TYPE_HIDDEN_NAV_CONSUMER:
             return 29;
+        case TYPE_HIDDEN_NAV_CONSUMER:
+            return 30;
         }
         Log.e(TAG, "Unknown window type: " + type);
         return 2;
@@ -1949,7 +1976,6 @@
                 }
                 mKeyguardScrim = win;
                 break;
-
         }
         return WindowManagerGlobal.ADD_OKAY;
     }
@@ -3181,10 +3207,15 @@
             // whether it is taking care of insetting its content.  If not,
             // we need to use the parent's content frame so that the entire
             // window is positioned within that content.  Otherwise we can use
-            // the display frame and let the attached window take care of
+            // the overscan frame and let the attached window take care of
             // positioning its content appropriately.
             if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
-                cf.set(attached.getOverscanFrameLw());
+                // Set the content frame of the attached window to the parent's decor frame
+                // (same as content frame when IME isn't present) if specifically requested by
+                // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
+                // Otherwise, use the overscan frame.
+                cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
+                        ? attached.getContentFrameLw() : attached.getOverscanFrameLw());
             } else {
                 // If the window is resizing, then we want to base the content
                 // frame on our attached content frame to resize...  however,
@@ -4060,7 +4091,7 @@
         updateRotation(true);
 
         if (lidOpen) {
-            mPowerManager.wakeUp(SystemClock.uptimeMillis());
+            wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch);
         } else if (!mLidControlsSleep) {
             mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
         }
@@ -4082,7 +4113,7 @@
             } else {
                 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
             }
-            mPowerManager.wakeUp(whenNanos / 1000000);
+            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens);
             mContext.startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
         }
         mCameraLensCoverState = lensCoverState;
@@ -4260,7 +4291,8 @@
         // key processing.
         if (mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
             if (isWakeKey) {
-                mPowerManager.wakeUp(event.getEventTime());
+                wakeUp(event.getEventTime(), keyCode == KeyEvent.KEYCODE_POWER
+                        ? mAllowTheaterModeWakeFromPowerKey : mAllowTheaterModeWakeFromKey);
             }
             return result;
         }
@@ -4509,8 +4541,10 @@
         }
 
         if (isWakeKey) {
-            mPowerManager.wakeUp(event.getEventTime());
+            wakeUp(event.getEventTime(), keyCode == KeyEvent.KEYCODE_POWER
+                    ? mAllowTheaterModeWakeFromPowerKey : mAllowTheaterModeWakeFromKey);
         }
+
         return result;
     }
 
@@ -4553,7 +4587,7 @@
     @Override
     public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
         if ((policyFlags & FLAG_WAKE) != 0) {
-            mPowerManager.wakeUp(whenNanos / 1000000);
+            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion);
             return 0;
         }
         if (shouldDispatchInputWhenNonInteractive()) {
@@ -4731,6 +4765,14 @@
         }
     }
 
+    private void wakeUp(long wakeTime, boolean wakeInTheaterMode) {
+        if (!wakeInTheaterMode && isTheaterModeEnabled()) {
+            return;
+        }
+
+        mPowerManager.wakeUp(wakeTime);
+    }
+
     // Called on the PowerManager's Notifier thread.
     @Override
     public void wakingUp() {
@@ -5609,6 +5651,11 @@
         ringTone.play();
     }
 
+    private boolean isTheaterModeEnabled() {
+        return Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.THEATER_MODE_ON, 0) == 1;
+    }
+
     private boolean isGlobalAccessibilityGestureEnabled() {
         return Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1;
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index e1a74d1..2781890 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1040,7 +1040,7 @@
 
     private void addServiceLocked(Service service, UserState userState) {
         try {
-            service.linkToOwnDeathLocked();
+            service.onAdded();
             userState.mBoundServices.add(service);
             userState.mComponentNameToServiceMap.put(service.mComponentName, service);
         } catch (RemoteException re) {
@@ -1056,7 +1056,7 @@
     private void removeServiceLocked(Service service, UserState userState) {
         userState.mBoundServices.remove(service);
         userState.mComponentNameToServiceMap.remove(service.mComponentName);
-        service.unlinkToOwnDeathLocked();
+        service.onRemoved();
     }
 
     /**
@@ -1931,6 +1931,8 @@
 
         final ResolveInfo mResolveInfo;
 
+        final IBinder mOverlayWindowToken = new Binder();
+
         // the events pending events to be dispatched to this service
         final SparseArray<AccessibilityEvent> mPendingEvents =
             new SparseArray<>();
@@ -2112,7 +2114,7 @@
                     userState.mBindingServices.remove(mComponentName);
                     mWasConnectedAndDied = false;
                     try {
-                       mServiceInterface.setConnection(this, mId);
+                       mServiceInterface.init(this, mId, mOverlayWindowToken);
                        onUserStateChangedLocked(userState);
                     } catch (RemoteException re) {
                         Slog.w(LOG_TAG, "Error while setting connection for service: "
@@ -2602,6 +2604,27 @@
             /* do nothing - #binderDied takes care */
         }
 
+        public void onAdded() throws RemoteException {
+            linkToOwnDeathLocked();
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                mWindowManagerService.addWindowToken(mOverlayWindowToken,
+                        WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        public void onRemoved() {
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                mWindowManagerService.removeWindowToken(mOverlayWindowToken, true);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+            unlinkToOwnDeathLocked();
+        }
+
         public void linkToOwnDeathLocked() throws RemoteException {
             mService.linkToDeath(this, 0);
         }
@@ -2614,7 +2637,7 @@
             try {
                 // Clear the proxy in the other process so this
                 // IAccessibilityServiceConnection can be garbage collected.
-                mServiceInterface.setConnection(null, mId);
+                mServiceInterface.init(null, mId, null);
             } catch (RemoteException re) {
                 /* ignore */
             }
@@ -3164,6 +3187,10 @@
                     return AccessibilityWindowInfo.TYPE_SYSTEM;
                 }
 
+                case WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY: {
+                    return AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY;
+                }
+
                 default: {
                     return -1;
                 }
diff --git a/services/core/java/com/android/server/DockObserver.java b/services/core/java/com/android/server/DockObserver.java
index d05c280..41ce25d 100644
--- a/services/core/java/com/android/server/DockObserver.java
+++ b/services/core/java/com/android/server/DockObserver.java
@@ -65,11 +65,15 @@
 
     private boolean mUpdatesStopped;
 
+    private final boolean mAllowTheaterModeWakeFromDock;
+
     public DockObserver(Context context) {
         super(context);
 
         mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
         mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
+        mAllowTheaterModeWakeFromDock = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_allowTheaterModeWakeFromDock);
 
         init();  // set initial status
 
@@ -126,8 +130,12 @@
         if (newState != mReportedDockState) {
             mReportedDockState = newState;
             if (mSystemReady) {
-                // Wake up immediately when docked or undocked.
-                mPowerManager.wakeUp(SystemClock.uptimeMillis());
+                // Wake up immediately when docked or undocked except in theater mode.
+                if (mAllowTheaterModeWakeFromDock
+                        || Settings.Global.getInt(getContext().getContentResolver(),
+                            Settings.Global.THEATER_MODE_ON, 0) == 0) {
+                    mPowerManager.wakeUp(SystemClock.uptimeMillis());
+                }
                 updateLocked();
             }
         }
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 64d8f6f..eec97f3 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -69,6 +69,10 @@
 27511 notification_expansion (key|3),(user_action|1),(expanded|1)
 # when a notification has been clicked
 27520 notification_clicked (key|3)
+# when a notification action button has been clicked
+27521 notification_action_clicked (key|3),(action_index|1)
+# when a notification has been canceled
+27530 notification_canceled (key|3),(reason|1)
 
 # ---------------------------
 # Watchdog.java
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 28a6917..d9c96e4 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -1796,9 +1796,6 @@
 
     @Override
     public boolean addGpsStatusListener(IGpsStatusListener listener, String packageName) {
-        if (mGpsStatusProvider == null) {
-            return false;
-        }
         int allowedResolutionLevel = getCallerAllowedResolutionLevel();
         checkResolutionLevelIsSufficientForProviderUse(allowedResolutionLevel,
                 LocationManager.GPS_PROVIDER);
@@ -1813,6 +1810,10 @@
             Binder.restoreCallingIdentity(ident);
         }
 
+        if (mGpsStatusProvider == null) {
+            return false;
+        }
+
         try {
             mGpsStatusProvider.addGpsStatusListener(listener);
         } catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 970d275..9f1ce0b 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -8852,7 +8852,8 @@
                 task = mStackSupervisor.anyTaskForIdLocked(task.taskId);
                 if (task != null) {
                     if (!isSystemInitiated
-                            && ((mFocusedActivity == null) || (task != mFocusedActivity.task))) {
+                            && ((mStackSupervisor.getFocusedStack() == null)
+                                    || (task != mStackSupervisor.getFocusedStack().topTask()))) {
                         throw new IllegalArgumentException("Invalid task, not in foreground");
                     }
                     mStackSupervisor.setLockTaskModeLocked(task, !isSystemInitiated);
diff --git a/services/core/java/com/android/server/am/LockTaskNotify.java b/services/core/java/com/android/server/am/LockTaskNotify.java
index 5768ddb..b3777ed 100644
--- a/services/core/java/com/android/server/am/LockTaskNotify.java
+++ b/services/core/java/com/android/server/am/LockTaskNotify.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.os.Handler;
 import android.os.Message;
+import android.view.WindowManager;
 import android.view.accessibility.AccessibilityManager;
 import android.widget.Toast;
 
@@ -56,8 +57,7 @@
         if (mLastToast != null) {
             mLastToast.cancel();
         }
-        mLastToast = Toast.makeText(mContext, text, Toast.LENGTH_LONG);
-        mLastToast.show();
+        mLastToast = makeAllUserToastAndShow(text);
     }
 
     public void show(boolean starting) {
@@ -65,7 +65,15 @@
         if (starting) {
             showString = R.string.lock_to_app_start;
         }
-        Toast.makeText(mContext, mContext.getString(showString), Toast.LENGTH_LONG).show();
+        makeAllUserToastAndShow(mContext.getString(showString));
+    }
+
+    private Toast makeAllUserToastAndShow(String text) {
+        Toast toast = Toast.makeText(mContext, text, Toast.LENGTH_LONG);
+        toast.getWindowParams().privateFlags |=
+                WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+        toast.show();
+        return toast;
     }
 
     private final class H extends Handler {
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 953bef2..e741fc4 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -2087,7 +2087,7 @@
         assertRunOnServiceThread();
         Intent intent = new Intent(HdmiControlManager.ACTION_OSD_MESSAGE);
         intent.putExtra(HdmiControlManager.EXTRA_MESSAGE_ID, messageId);
-        intent.putExtra(HdmiControlManager.EXTRA_MESSAGE_EXTRAM_PARAM1, extra);
+        intent.putExtra(HdmiControlManager.EXTRA_MESSAGE_EXTRA_PARAM1, extra);
         getContext().sendBroadcastAsUser(intent, UserHandle.ALL,
                 HdmiControlService.PERMISSION);
     }
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index c6d2db2..83d6986 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -137,11 +137,15 @@
         public void onReceive(Context context, Intent intent) {
             Slog.d(TAG, "Receieved: " + intent.getAction());
             if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
-                int uidRemoved = intent.getIntExtra(Intent.EXTRA_UID, -1);
-                if (DEBUG) {
-                    Slog.d(TAG, "Removing jobs for uid: " + uidRemoved);
+                // If this is an outright uninstall rather than the first half of an
+                // app update sequence, cancel the jobs associated with the app.
+                if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+                    int uidRemoved = intent.getIntExtra(Intent.EXTRA_UID, -1);
+                    if (DEBUG) {
+                        Slog.d(TAG, "Removing jobs for uid: " + uidRemoved);
+                    }
+                    cancelJobsForUid(uidRemoved);
                 }
-                cancelJobsForUid(uidRemoved);
             } else if (Intent.ACTION_USER_REMOVED.equals(intent.getAction())) {
                 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
                 if (DEBUG) {
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index 97f0a1e..24fc455 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -20,6 +20,7 @@
     void onSetDisabled(int status);
     void onClearAll(int callingUid, int callingPid, int userId);
     void onNotificationClick(int callingUid, int callingPid, String key);
+    void onNotificationActionClick(int callingUid, int callingPid, String key, int actionIndex);
     void onNotificationClear(int callingUid, int callingPid,
             String pkg, String tag, int id, int userId);
     void onNotificationError(int callingUid, int callingPid,
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 22f060f..090967f 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -541,6 +541,20 @@
         }
 
         @Override
+        public void onNotificationActionClick(int callingUid, int callingPid, String key,
+                int actionIndex) {
+            synchronized (mNotificationList) {
+                EventLogTags.writeNotificationActionClicked(key, actionIndex);
+                NotificationRecord r = mNotificationsByKey.get(key);
+                if (r == null) {
+                    Log.w(TAG, "No notification with key: " + key);
+                    return;
+                }
+                // TODO: Log action click via UsageStats.
+            }
+        }
+
+        @Override
         public void onNotificationClear(int callingUid, int callingPid,
                 String pkg, String tag, int id, int userId) {
             cancelNotification(callingUid, callingPid, pkg, tag, id, 0,
@@ -2358,6 +2372,8 @@
 
         // Save it for users of getHistoricalNotifications()
         mArchive.record(r.sbn);
+
+        EventLogTags.writeNotificationCanceled(r.getKey(), reason);
     }
 
     /**
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 52807c0..5e95dfe 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -281,6 +281,9 @@
     // True if the device should wake up when plugged or unplugged.
     private boolean mWakeUpWhenPluggedOrUnpluggedConfig;
 
+    // True if the device should wake up when plugged or unplugged in theater mode.
+    private boolean mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig;
+
     // True if the device should suspend when the screen is off due to proximity.
     private boolean mSuspendWhenScreenOffDueToProximityConfig;
 
@@ -420,6 +423,9 @@
     // True if the battery level is currently considered low.
     private boolean mBatteryLevelLow;
 
+    // True if theater mode is enabled
+    private boolean mTheaterModeEnabled;
+
     private final ArrayList<PowerManagerInternal.LowPowerModeListener> mLowPowerModeListeners
             = new ArrayList<PowerManagerInternal.LowPowerModeListener>();
 
@@ -568,6 +574,9 @@
             resolver.registerContentObserver(Settings.Global.getUriFor(
                     Settings.Global.LOW_POWER_MODE_TRIGGER_LEVEL),
                     false, mSettingsObserver, UserHandle.USER_ALL);
+            resolver.registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Global.THEATER_MODE_ON),
+                    false, mSettingsObserver, UserHandle.USER_ALL);
             // Go.
             readConfigurationLocked();
             updateSettingsLocked();
@@ -585,6 +594,8 @@
                 com.android.internal.R.bool.config_powerDecoupleInteractiveModeFromDisplay);
         mWakeUpWhenPluggedOrUnpluggedConfig = resources.getBoolean(
                 com.android.internal.R.bool.config_unplugTurnsOnScreen);
+        mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig = resources.getBoolean(
+                com.android.internal.R.bool.config_allowTheaterModeWakeFromUnplug);
         mSuspendWhenScreenOffDueToProximityConfig = resources.getBoolean(
                 com.android.internal.R.bool.config_suspendWhenScreenOffDueToProximity);
         mDreamsSupportedConfig = resources.getBoolean(
@@ -636,6 +647,8 @@
                 UserHandle.USER_CURRENT);
         mStayOnWhilePluggedInSetting = Settings.Global.getInt(resolver,
                 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, BatteryManager.BATTERY_PLUGGED_AC);
+        mTheaterModeEnabled = Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.THEATER_MODE_ON, 0) == 1;
 
         final int oldScreenBrightnessSetting = mScreenBrightnessSetting;
         mScreenBrightnessSetting = Settings.System.getIntForUser(resolver,
@@ -1334,6 +1347,11 @@
             return false;
         }
 
+        // Don't wake while theater mode is enabled.
+        if (mTheaterModeEnabled && !mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig) {
+            return false;
+        }
+
         // Otherwise wake up!
         return true;
     }
@@ -2360,6 +2378,10 @@
                     + mDecoupleHalInteractiveModeFromDisplayConfig);
             pw.println("  mWakeUpWhenPluggedOrUnpluggedConfig="
                     + mWakeUpWhenPluggedOrUnpluggedConfig);
+            pw.println("  mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig="
+                    + mWakeUpWhenPluggedOrUnpluggedInTheaterModeConfig);
+            pw.println("  mTheaterModeEnabled="
+                    + mTheaterModeEnabled);
             pw.println("  mSuspendWhenScreenOffDueToProximityConfig="
                     + mSuspendWhenScreenOffDueToProximityConfig);
             pw.println("  mDreamsSupportedConfig=" + mDreamsSupportedConfig);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index f85e2d9..15e0bf0 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -26,6 +26,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.util.Slog;
+import android.view.WindowManager;
 
 import com.android.internal.statusbar.IStatusBar;
 import com.android.internal.statusbar.IStatusBarService;
@@ -295,9 +296,10 @@
         }
     }
 
-    /** 
+    /**
      * Hide or show the on-screen Menu key. Only call this from the window manager, typically in
-     * response to a window with FLAG_NEEDS_MENU_KEY set.
+     * response to a window with {@link android.view.WindowManager.LayoutParams#needsMenuKey} set
+     * to {@link android.view.WindowManager.LayoutParams#NEEDS_MENU_SET_TRUE}.
      */
     @Override
     public void topAppWindowChanged(final boolean menuVisible) {
@@ -523,6 +525,20 @@
     }
 
     @Override
+    public void onNotificationActionClick(String key, int actionIndex) {
+        enforceStatusBarService();
+        final int callingUid = Binder.getCallingUid();
+        final int callingPid = Binder.getCallingPid();
+        long identity = Binder.clearCallingIdentity();
+        try {
+            mNotificationDelegate.onNotificationActionClick(callingUid, callingPid, key,
+                    actionIndex);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
     public void onNotificationError(String pkg, String tag, int id,
             int uid, int initialPid, String message, int userId) {
         enforceStatusBarService();
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index fefbe0a..1649535 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.trust;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.server.SystemService;
@@ -24,6 +25,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.Manifest;
+import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.admin.DevicePolicyManager;
 import android.app.trust.ITrustListener;
@@ -41,6 +43,7 @@
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.graphics.drawable.Drawable;
+import android.os.Binder;
 import android.os.DeadObjectException;
 import android.os.Handler;
 import android.os.IBinder;
@@ -100,8 +103,10 @@
     /* package */ final TrustArchive mArchive = new TrustArchive();
     private final Context mContext;
     private final LockPatternUtils mLockPatternUtils;
+    private final UserManager mUserManager;
 
-    private UserManager mUserManager;
+    @GuardedBy("mUserIsTrusted")
+    private final SparseBooleanArray mUserIsTrusted = new SparseBooleanArray();
 
     public TrustManagerService(Context context) {
         super(context);
@@ -120,8 +125,9 @@
         if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY && !isSafeMode()) {
             mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true);
             mReceiver.register(mContext);
-            maybeEnableFactoryTrustAgents(mLockPatternUtils, UserHandle.USER_OWNER);
             refreshAgentList(UserHandle.USER_ALL);
+        } else if (phase == SystemService.PHASE_BOOT_COMPLETED && !isSafeMode()) {
+            maybeEnableFactoryTrustAgents(mLockPatternUtils, UserHandle.USER_OWNER);
         }
     }
 
@@ -159,7 +165,11 @@
 
     public void updateTrust(int userId, boolean initiatedByUser) {
         dispatchOnTrustManagedChanged(aggregateIsTrustManaged(userId), userId);
-        dispatchOnTrustChanged(aggregateIsTrusted(userId), userId, initiatedByUser);
+        boolean trusted = aggregateIsTrusted(userId);
+        synchronized (mUserIsTrusted) {
+            mUserIsTrusted.put(userId, trusted);
+        }
+        dispatchOnTrustChanged(trusted, userId, initiatedByUser);
     }
 
     void refreshAgentList(int userId) {
@@ -546,6 +556,16 @@
             mHandler.obtainMessage(MSG_UNREGISTER_LISTENER, trustListener).sendToTarget();
         }
 
+        @Override
+        public boolean isTrusted(int userId) throws RemoteException {
+            userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
+                    false /* allowAll */, true /* requireFull */, "isTrusted", null);
+            userId = resolveProfileParent(userId);
+            synchronized (mUserIsTrusted) {
+                return mUserIsTrusted.get(userId);
+            }
+        }
+
         private void enforceReportPermission() {
             mContext.enforceCallingOrSelfPermission(
                     Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, "reporting trust events");
@@ -622,6 +642,19 @@
         }
     };
 
+    private int resolveProfileParent(int userId) {
+        long identity = Binder.clearCallingIdentity();
+        try {
+            UserInfo parent = mUserManager.getProfileParent(userId);
+            if (parent != null) {
+                return parent.getUserHandle().getIdentifier();
+            }
+            return userId;
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
     private final Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
diff --git a/services/core/java/com/android/server/tv/TvInputHal.java b/services/core/java/com/android/server/tv/TvInputHal.java
index 558ffb5..c12dd63 100644
--- a/services/core/java/com/android/server/tv/TvInputHal.java
+++ b/services/core/java/com/android/server/tv/TvInputHal.java
@@ -55,7 +55,7 @@
 
     private native long nativeOpen();
 
-    private static native int nativeAddStream(long ptr, int deviceId, int streamId,
+    private static native int nativeAddOrUpdateStream(long ptr, int deviceId, int streamId,
             Surface surface);
     private static native int nativeRemoveStream(long ptr, int deviceId, int streamId);
     private static native TvStreamConfig[] nativeGetStreamConfigs(long ptr, int deviceId,
@@ -80,7 +80,7 @@
         }
     }
 
-    public int addStream(int deviceId, Surface surface, TvStreamConfig streamConfig) {
+    public int addOrUpdateStream(int deviceId, Surface surface, TvStreamConfig streamConfig) {
         synchronized (mLock) {
             if (mPtr == 0) {
                 return ERROR_NO_INIT;
@@ -89,7 +89,7 @@
             if (generation != streamConfig.getGeneration()) {
                 return ERROR_STALE_CONFIG;
             }
-            if (nativeAddStream(mPtr, deviceId, streamConfig.getStreamId(), surface) == 0) {
+            if (nativeAddOrUpdateStream(mPtr, deviceId, streamConfig.getStreamId(), surface) == 0) {
                 return SUCCESS;
             } else {
                 return ERROR_UNKNOWN;
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 44e4ad1..7d031ea 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -668,14 +668,14 @@
                     result = mHal.removeStream(mInfo.getDeviceId(), mActiveConfig);
                     mActiveConfig = null;
                 } else {
-                    if (config != mActiveConfig && mActiveConfig != null) {
+                    if (!config.equals(mActiveConfig)) {
                         result = mHal.removeStream(mInfo.getDeviceId(), mActiveConfig);
                         if (result != TvInputHal.SUCCESS) {
                             mActiveConfig = null;
                             return false;
                         }
                     }
-                    result = mHal.addStream(mInfo.getDeviceId(), surface, config);
+                    result = mHal.addOrUpdateStream(mInfo.getDeviceId(), surface, config);
                     if (result == TvInputHal.SUCCESS) {
                         mActiveConfig = config;
                     }
@@ -801,7 +801,7 @@
                     return false;
                 }
 
-                int result = mHal.addStream(mInfo.getDeviceId(), surface, config);
+                int result = mHal.addOrUpdateStream(mInfo.getDeviceId(), surface, config);
                 return result == TvInputHal.SUCCESS;
             }
         }
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index fde703d..f947b6a 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -992,8 +992,7 @@
 
                     final int flags = windowState.mAttrs.flags;
 
-                    // If the window is not touchable, do not report it but take into account
-                    // the space it takes since the content behind it cannot be touched.
+                    // If the window is not touchable - ignore.
                     if ((flags & WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE) != 0) {
                         continue;
                     }
@@ -1014,9 +1013,14 @@
                         }
                     }
 
-                    // Account for the space this window takes.
-                    unaccountedSpace.op(boundsInScreen, unaccountedSpace,
-                            Region.Op.REVERSE_DIFFERENCE);
+                    // Account for the space this window takes if the window
+                    // is not an accessibility overlay which does not change
+                    // the reported windows.
+                    if (windowState.mAttrs.type == WindowManager.LayoutParams
+                            .TYPE_ACCESSIBILITY_OVERLAY) {
+                        unaccountedSpace.op(boundsInScreen, unaccountedSpace,
+                                Region.Op.REVERSE_DIFFERENCE);
+                    }
 
                     // We figured out what is touchable for the entire screen - done.
                     if (unaccountedSpace.isEmpty()) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 30589b1..b0feca8 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -376,10 +376,9 @@
             stack.dump(prefix + "  ", pw);
         }
         pw.println();
-        pw.println("  Application tokens in bottom up Z order:");
+        pw.println("  Application tokens in top down Z order:");
         int ndx = 0;
-        final int numStacks = mStacks.size();
-        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
+        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
             ArrayList<Task> tasks = mStacks.get(stackNdx).getTasks();
             for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
                 AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 9ceac41..a60be3b 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -60,6 +60,12 @@
         return removed;
     }
 
+    void setSendingToBottom(boolean toBottom) {
+        for (int appTokenNdx = 0; appTokenNdx < mAppTokens.size(); appTokenNdx++) {
+            mAppTokens.get(appTokenNdx).sendingToBottom = toBottom;
+        }
+    }
+
     @Override
     public String toString() {
         return "{taskId=" + taskId + " appTokens=" + mAppTokens + "}";
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0a0e8a1..3fee608 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -619,6 +619,9 @@
 
     boolean mTurnOnScreen;
 
+    // Whether or not a layout can cause a wake up when theater mode is enabled.
+    boolean mAllowTheaterModeWakeFromLayout;
+
     DragState mDragState = null;
 
     // For frozen screen animations.
@@ -881,6 +884,9 @@
 
         mAnimator = new WindowAnimator(this);
 
+        mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
+                com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
+
         LocalServices.addService(WindowManagerInternal.class, new LocalService());
         initPolicy();
 
@@ -2331,6 +2337,11 @@
                           + attrs.token + ".  Aborting.");
                     return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
+                if (type == TYPE_ACCESSIBILITY_OVERLAY) {
+                    Slog.w(TAG, "Attempted to add Accessibility overlay window with unknown token "
+                            + attrs.token + ".  Aborting.");
+                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
+                }
                 token = new WindowToken(this, attrs.token, -1, false);
                 addToken = true;
             } else if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
@@ -2374,6 +2385,12 @@
                             + attrs.token + ".  Aborting.");
                       return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
                 }
+            } else if (type == TYPE_ACCESSIBILITY_OVERLAY) {
+                if (token.windowType != TYPE_ACCESSIBILITY_OVERLAY) {
+                    Slog.w(TAG, "Attempted to add Accessibility overlay window with bad token "
+                            + attrs.token + ".  Aborting.");
+                    return WindowManagerGlobal.ADD_BAD_APP_TOKEN;
+                }
             } else if (token.appWindowToken != null) {
                 Slog.w(TAG, "Non-null appWindowToken for system window of type=" + type);
                 // It is not valid to use an app token with other system types; we will
@@ -5052,6 +5069,10 @@
                     }
                 }
                 stack.moveTaskToTop(task);
+                if (mAppTransition.isTransitionSet()) {
+                    task.setSendingToBottom(false);
+                }
+                moveStackWindowsLocked(displayContent);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -5070,6 +5091,9 @@
                 }
                 final TaskStack stack = task.mStack;
                 stack.moveTaskToBottom(task);
+                if (mAppTransition.isTransitionSet()) {
+                    task.setSendingToBottom(true);
+                }
                 moveStackWindowsLocked(stack.getDisplayContent());
             }
         } finally {
@@ -9953,8 +9977,12 @@
         }
 
         if (mTurnOnScreen) {
-            if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
-            mPowerManager.wakeUp(SystemClock.uptimeMillis());
+            if (mAllowTheaterModeWakeFromLayout
+                    || Settings.Global.getInt(mContext.getContentResolver(),
+                        Settings.Global.THEATER_MODE_ON, 0) == 0) {
+                if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
+                mPowerManager.wakeUp(SystemClock.uptimeMillis());
+            }
             mTurnOnScreen = false;
         }
 
@@ -11610,5 +11638,23 @@
                 checkDrawnWindowsLocked();
             }
         }
+
+        @Override
+        public void addWindowToken(IBinder token, int type) {
+            WindowManagerService.this.addWindowToken(token, type);
+        }
+
+        @Override
+        public void removeWindowToken(IBinder token, boolean removeWindows) {
+            synchronized(mWindowMap) {
+                if (removeWindows) {
+                    WindowToken wtoken = mTokenMap.remove(token);
+                    if (wtoken != null) {
+                        wtoken.removeAllWindows();
+                    }
+                }
+                WindowManagerService.this.removeWindowToken(token);
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index b4a7f04..806f7c5 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -704,9 +704,8 @@
         WindowState ws = this;
         WindowList windows = getWindowList();
         while (true) {
-            if ((ws.mAttrs.privateFlags
-                    & WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY) != 0) {
-                return (ws.mAttrs.flags & WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0;
+            if (ws.mAttrs.needsMenuKey != WindowManager.LayoutParams.NEEDS_MENU_UNSET) {
+                return ws.mAttrs.needsMenuKey == WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE;
             }
             // If we reached the bottom of the range of windows we are considering,
             // assume no menu is needed.
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 2267123..1a672e68 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -17,6 +17,7 @@
 package com.android.server.wm;
 
 import android.os.IBinder;
+import android.util.Slog;
 
 import java.io.PrintWriter;
 
@@ -29,7 +30,7 @@
 class WindowToken {
     // The window manager!
     final WindowManagerService service;
-    
+
     // The actual token.
     final IBinder token;
 
@@ -77,6 +78,15 @@
         explicit = _explicit;
     }
 
+    void removeAllWindows() {
+        for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
+            WindowState win = windows.get(winNdx);
+            if (WindowManagerService.DEBUG_WINDOW_MOVEMENT) Slog.w(WindowManagerService.TAG,
+                    "removeAllWindows: removing win=" + win);
+            win.mService.removeWindowLocked(win.mSession, win);
+        }
+    }
+
     void dump(PrintWriter pw, String prefix) {
         pw.print(prefix); pw.print("windows="); pw.println(windows);
         pw.print(prefix); pw.print("windowType="); pw.print(windowType);
diff --git a/services/core/jni/com_android_server_tv_TvInputHal.cpp b/services/core/jni/com_android_server_tv_TvInputHal.cpp
index d5abe0c..5cb0543 100644
--- a/services/core/jni/com_android_server_tv_TvInputHal.cpp
+++ b/services/core/jni/com_android_server_tv_TvInputHal.cpp
@@ -235,7 +235,7 @@
 
     static JTvInputHal* createInstance(JNIEnv* env, jobject thiz);
 
-    int addStream(int deviceId, int streamId, const sp<Surface>& surface);
+    int addOrUpdateStream(int deviceId, int streamId, const sp<Surface>& surface);
     int removeStream(int deviceId, int streamId);
     const tv_stream_config_t* getStreamConfigs(int deviceId, int* numConfigs);
 
@@ -312,7 +312,7 @@
     return new JTvInputHal(env, thiz, device);
 }
 
-int JTvInputHal::addStream(int deviceId, int streamId, const sp<Surface>& surface) {
+int JTvInputHal::addOrUpdateStream(int deviceId, int streamId, const sp<Surface>& surface) {
     KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId);
     if (connections.indexOfKey(streamId) < 0) {
         connections.add(streamId, Connection());
@@ -555,14 +555,14 @@
     return (jlong)JTvInputHal::createInstance(env, thiz);
 }
 
-static int nativeAddStream(JNIEnv* env, jclass clazz,
+static int nativeAddOrUpdateStream(JNIEnv* env, jclass clazz,
         jlong ptr, jint deviceId, jint streamId, jobject jsurface) {
     JTvInputHal* tvInputHal = (JTvInputHal*)ptr;
     if (!jsurface) {
         return BAD_VALUE;
     }
     sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
-    return tvInputHal->addStream(deviceId, streamId, surface);
+    return tvInputHal->addOrUpdateStream(deviceId, streamId, surface);
 }
 
 static int nativeRemoveStream(JNIEnv* env, jclass clazz,
@@ -612,8 +612,8 @@
     /* name, signature, funcPtr */
     { "nativeOpen", "()J",
             (void*) nativeOpen },
-    { "nativeAddStream", "(JIILandroid/view/Surface;)I",
-            (void*) nativeAddStream },
+    { "nativeAddOrUpdateStream", "(JIILandroid/view/Surface;)I",
+            (void*) nativeAddOrUpdateStream },
     { "nativeRemoveStream", "(JII)I",
             (void*) nativeRemoveStream },
     { "nativeGetStreamConfigs", "(JII)[Landroid/media/tv/TvStreamConfig;",
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index f934963..354fa2e 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -484,10 +484,10 @@
 
     /**
      * Notifies this {@code Call} that an account has been selected and to proceed with placing
-     * an outgoing call.
+     * an outgoing call. Optionally sets this account as the default account.
      */
-    public void phoneAccountSelected(PhoneAccountHandle accountHandle) {
-        mInCallAdapter.phoneAccountSelected(mTelecomCallId, accountHandle);
+    public void phoneAccountSelected(PhoneAccountHandle accountHandle, boolean setDefault) {
+        mInCallAdapter.phoneAccountSelected(mTelecomCallId, accountHandle, setDefault);
 
     }
 
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 795053d..2932721 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -898,6 +898,13 @@
     }
 
     /**
+     * @hide
+     */
+    public final ConnectionService getConnectionService() {
+        return mConnectionService;
+    }
+
+    /**
      * Sets the conference that this connection is a part of. This will fail if the connection is
      * already part of a conference call. {@link #resetConference} to un-set the conference first.
      *
diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java
index fd3cf2e..62b8dea 100644
--- a/telecomm/java/android/telecom/InCallAdapter.java
+++ b/telecomm/java/android/telecom/InCallAdapter.java
@@ -189,14 +189,16 @@
     }
 
     /**
-     * Instructs Telecom to add a PhoneAccountHandle to the specified call
+     * Instructs Telecom to add a PhoneAccountHandle to the specified call.
      *
-     * @param callId The identifier of the call
-     * @param accountHandle The PhoneAccountHandle through which to place the call
+     * @param callId The identifier of the call.
+     * @param accountHandle The PhoneAccountHandle through which to place the call.
+     * @param setDefault {@code True} if this account should be set as the default for calls.
      */
-    public void phoneAccountSelected(String callId, PhoneAccountHandle accountHandle) {
+    public void phoneAccountSelected(String callId, PhoneAccountHandle accountHandle,
+            boolean setDefault) {
         try {
-            mAdapter.phoneAccountSelected(callId, accountHandle);
+            mAdapter.phoneAccountSelected(callId, accountHandle, setDefault);
         } catch (RemoteException e) {
         }
     }
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 66b52ae..402df30 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -105,11 +105,17 @@
      */
     public static final String SCHEME_SIP = "sip";
 
+    /**
+     * Indicating no color is set.
+     */
+    public static final int NO_COLOR = -1;
+
     private final PhoneAccountHandle mAccountHandle;
     private final Uri mAddress;
     private final Uri mSubscriptionAddress;
     private final int mCapabilities;
     private final int mIconResId;
+    private final int mColor;
     private final CharSequence mLabel;
     private final CharSequence mShortDescription;
     private final List<String> mSupportedUriSchemes;
@@ -120,6 +126,7 @@
         private Uri mSubscriptionAddress;
         private int mCapabilities;
         private int mIconResId;
+        private int mColor = NO_COLOR;
         private CharSequence mLabel;
         private CharSequence mShortDescription;
         private List<String> mSupportedUriSchemes = new ArrayList<String>();
@@ -141,6 +148,7 @@
             mSubscriptionAddress = phoneAccount.getSubscriptionAddress();
             mCapabilities = phoneAccount.getCapabilities();
             mIconResId = phoneAccount.getIconResId();
+            mColor = phoneAccount.getColor();
             mLabel = phoneAccount.getLabel();
             mShortDescription = phoneAccount.getShortDescription();
             mSupportedUriSchemes.addAll(phoneAccount.getSupportedUriSchemes());
@@ -166,6 +174,11 @@
             return this;
         }
 
+        public Builder setColor(int value) {
+            this.mColor = value;
+            return this;
+        }
+
         public Builder setShortDescription(CharSequence value) {
             this.mShortDescription = value;
             return this;
@@ -219,6 +232,7 @@
                     mSubscriptionAddress,
                     mCapabilities,
                     mIconResId,
+                    mColor,
                     mLabel,
                     mShortDescription,
                     mSupportedUriSchemes);
@@ -231,6 +245,7 @@
             Uri subscriptionAddress,
             int capabilities,
             int iconResId,
+            int color,
             CharSequence label,
             CharSequence shortDescription,
             List<String> supportedUriSchemes) {
@@ -239,6 +254,7 @@
         mSubscriptionAddress = subscriptionAddress;
         mCapabilities = capabilities;
         mIconResId = iconResId;
+        mColor = color;
         mLabel = label;
         mShortDescription = shortDescription;
         mSupportedUriSchemes = Collections.unmodifiableList(supportedUriSchemes);
@@ -371,6 +387,15 @@
     }
 
     /**
+     * A highlight color to use in displaying information about this {@code PhoneAccount}.
+     *
+     * @return A hexadecimal color value.
+     */
+    public int getColor() {
+        return mColor;
+    }
+
+    /**
      * An icon to represent this {@code PhoneAccount} in a user interface.
      *
      * @return An icon for this {@code PhoneAccount}.
@@ -418,6 +443,7 @@
         out.writeParcelable(mSubscriptionAddress, 0);
         out.writeInt(mCapabilities);
         out.writeInt(mIconResId);
+        out.writeInt(mColor);
         out.writeCharSequence(mLabel);
         out.writeCharSequence(mShortDescription);
         out.writeList(mSupportedUriSchemes);
@@ -444,6 +470,7 @@
         mSubscriptionAddress = in.readParcelable(getClass().getClassLoader());
         mCapabilities = in.readInt();
         mIconResId = in.readInt();
+        mColor = in.readInt();
         mLabel = in.readCharSequence();
         mShortDescription = in.readCharSequence();
 
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index ed221d2..2652b45 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -31,7 +31,6 @@
 
 /**
  * Provides access to Telecom-related functionality.
- * TODO: Move this all into PhoneManager.
  */
 public class TelecomManager {
 
@@ -587,7 +586,6 @@
      *
      * @param account The complete {@link PhoneAccount}.
      */
-    @SystemApi
     public void registerPhoneAccount(PhoneAccount account) {
         try {
             if (isServiceConnected()) {
@@ -603,7 +601,6 @@
      *
      * @param accountHandle A {@link PhoneAccountHandle} for the {@link PhoneAccount} to unregister.
      */
-    @SystemApi
     public void unregisterPhoneAccount(PhoneAccountHandle accountHandle) {
         try {
             if (isServiceConnected()) {
@@ -617,7 +614,6 @@
     /**
      * Remove all Accounts that belong to the calling package from the system.
      */
-    @SystemApi
     public void clearAccounts() {
         try {
             if (isServiceConnected()) {
@@ -671,7 +667,6 @@
      * Requires permission: {@link android.Manifest.permission#READ_PHONE_STATE}
      * </p>
      */
-    @SystemApi
     public boolean isInCall() {
         try {
             if (isServiceConnected()) {
@@ -823,7 +818,6 @@
      * @param extras A bundle that will be passed through to
      *            {@link ConnectionService#onCreateIncomingConnection}.
      */
-    @SystemApi
     public void addNewIncomingCall(PhoneAccountHandle phoneAccount, Bundle extras) {
         try {
             if (isServiceConnected()) {
diff --git a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
index 138a877..863fff2 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
@@ -46,7 +46,8 @@
 
     void postDialContinue(String callId, boolean proceed);
 
-    void phoneAccountSelected(String callId, in PhoneAccountHandle accountHandle);
+    void phoneAccountSelected(String callId, in PhoneAccountHandle accountHandle,
+            boolean setDefault);
 
     void conference(String callId, String otherCallId);
 
diff --git a/telephony/java/android/telephony/SubInfoRecord.java b/telephony/java/android/telephony/SubInfoRecord.java
index b9de871..f2df079 100644
--- a/telephony/java/android/telephony/SubInfoRecord.java
+++ b/telephony/java/android/telephony/SubInfoRecord.java
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.graphics.drawable.BitmapDrawable;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -107,6 +108,31 @@
         this.mnc = mnc;
     }
 
+    /**
+     * Returns the string displayed to the user that identifies this subscription
+     */
+    public String getLabel() {
+        return this.displayName;
+    }
+
+    /**
+     * Return the icon used to identify this SIM.
+     * TODO: return the correct drawable.
+     */
+    public BitmapDrawable getIconDrawable() {
+        return new BitmapDrawable();
+    }
+
+    /**
+     * Return the color to be used for when displaying to the user. This is the value of the color.
+     * ex: 0x00ff00
+     */
+    public int getColor() {
+        // Note: This color is currently an index into a list of drawables, but this is soon to
+        // change.
+        return this.color;
+    }
+
     public static final Parcelable.Creator<SubInfoRecord> CREATOR = new Parcelable.Creator<SubInfoRecord>() {
         @Override
         public SubInfoRecord createFromParcel(Parcel source) {
diff --git a/telephony/java/com/android/ims/internal/IImsCallSession.aidl b/telephony/java/com/android/ims/internal/IImsCallSession.aidl
index 98b2d8a9..2cf7208 100644
--- a/telephony/java/com/android/ims/internal/IImsCallSession.aidl
+++ b/telephony/java/com/android/ims/internal/IImsCallSession.aidl
@@ -225,4 +225,10 @@
      * intermediates between the propriety implementation and Telecomm/InCall.
      */
     IImsVideoCallProvider getVideoCallProvider();
+
+    /**
+     * Determines if the current session is multiparty.
+     * @return {@code True} if the session is multiparty.
+     */
+    boolean isMultiparty();
 }
diff --git a/telephony/java/com/android/internal/telephony/DcParamObject.java b/telephony/java/com/android/internal/telephony/DcParamObject.java
index 2736e6f..c92988f 100644
--- a/telephony/java/com/android/internal/telephony/DcParamObject.java
+++ b/telephony/java/com/android/internal/telephony/DcParamObject.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 MediaTek Inc.
+ * 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.
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index defb43b..a4e9486 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -99,6 +99,7 @@
     public static final int EVENT_PROVISIONING_APN_ALARM = BASE + 39;
     public static final int CMD_NET_STAT_POLL = BASE + 40;
     public static final int EVENT_DATA_RAT_CHANGED = BASE + 41;
+    public static final int CMD_CLEAR_PROVISIONING_SPINNER = BASE + 42;
 
     /***** Constants *****/
 
diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp
index 117fc24..b7f64f6 100644
--- a/tools/aapt/AaptAssets.cpp
+++ b/tools/aapt/AaptAssets.cpp
@@ -1141,9 +1141,10 @@
 ssize_t AaptAssets::slurpFullTree(Bundle* bundle, const String8& srcDir,
                                     const AaptGroupEntry& kind,
                                     const String8& resType,
-                                    sp<FilePathStore>& fullResPaths)
+                                    sp<FilePathStore>& fullResPaths,
+                                    const bool overwrite)
 {
-    ssize_t res = AaptDir::slurpFullTree(bundle, srcDir, kind, resType, fullResPaths);
+    ssize_t res = AaptDir::slurpFullTree(bundle, srcDir, kind, resType, fullResPaths, overwrite);
     if (res > 0) {
         mGroupEntries.add(kind);
     }
diff --git a/tools/aapt/AaptAssets.h b/tools/aapt/AaptAssets.h
index d809c5b..7ae5368 100644
--- a/tools/aapt/AaptAssets.h
+++ b/tools/aapt/AaptAssets.h
@@ -591,7 +591,8 @@
                                   const String8& srcDir,
                                   const AaptGroupEntry& kind,
                                   const String8& resType,
-                                  sp<FilePathStore>& fullResPaths);
+                                  sp<FilePathStore>& fullResPaths,
+                                  const bool overwrite=false);
 
     ssize_t slurpResourceTree(Bundle* bundle, const String8& srcDir);
     ssize_t slurpResourceZip(Bundle* bundle, const char* filename);
diff --git a/tools/aapt/ConfigDescription.h b/tools/aapt/ConfigDescription.h
index 779c423..4f999a2 100644
--- a/tools/aapt/ConfigDescription.h
+++ b/tools/aapt/ConfigDescription.h
@@ -28,10 +28,12 @@
         memset(this, 0, sizeof(*this));
         size = sizeof(android::ResTable_config);
     }
+
     ConfigDescription(const android::ResTable_config&o) {
         *static_cast<android::ResTable_config*>(this) = o;
         size = sizeof(android::ResTable_config);
     }
+
     ConfigDescription(const ConfigDescription&o) {
         *static_cast<android::ResTable_config*>(this) = o;
     }
@@ -41,6 +43,7 @@
         size = sizeof(android::ResTable_config);
         return *this;
     }
+
     ConfigDescription& operator=(const ConfigDescription& o) {
         *static_cast<android::ResTable_config*>(this) = o;
         return *this;
diff --git a/tools/aapt/ResourceIdCache.cpp b/tools/aapt/ResourceIdCache.cpp
index d60a07fc..8835fb0 100644
--- a/tools/aapt/ResourceIdCache.cpp
+++ b/tools/aapt/ResourceIdCache.cpp
@@ -9,8 +9,6 @@
 #include <utils/Log.h>
 #include "ResourceIdCache.h"
 #include <map>
-using namespace std;
-
 
 static size_t mHits = 0;
 static size_t mMisses = 0;
@@ -29,7 +27,7 @@
     CacheEntry(const android::String16& name, uint32_t resId) : hashedName(name), id(resId) { }
 };
 
-static map< uint32_t, CacheEntry > mIdMap;
+static std::map< uint32_t, CacheEntry > mIdMap;
 
 
 // djb2; reasonable choice for strings when collisions aren't particularly important
@@ -63,7 +61,7 @@
         bool onlyPublic) {
     const String16 hashedName = makeHashableName(package, type, name, onlyPublic);
     const uint32_t hashcode = hash(hashedName);
-    map<uint32_t, CacheEntry>::iterator item = mIdMap.find(hashcode);
+    std::map<uint32_t, CacheEntry>::iterator item = mIdMap.find(hashcode);
     if (item == mIdMap.end()) {
         // cache miss
         mMisses++;
diff --git a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
index bef5181..4993262 100644
--- a/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/FontFamily_Delegate.java
@@ -213,6 +213,10 @@
         return null;
     }
 
+    @Nullable
+    /*package*/ static String getFontLocation() {
+        return sFontLocation;
+    }
 
     // ---- native methods ----
 
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java
deleted file mode 100644
index adad2ac..0000000
--- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Accessor.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2011 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.graphics;
-
-/**
- * Class allowing access to package-protected methods/fields.
- */
-public class Typeface_Accessor {
-
-    public static void resetDefaults() {
-        Typeface.sDefaults = null;
-    }
-}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
index 276e134..b9460b4 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Typeface_Delegate.java
@@ -27,6 +27,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import static android.graphics.FontFamily_Delegate.getFontLocation;
+
 /**
  * Delegate implementing the native methods of android.graphics.Typeface
  *
@@ -48,8 +50,6 @@
     private static final DelegateManager<Typeface_Delegate> sManager =
             new DelegateManager<Typeface_Delegate>(Typeface_Delegate.class);
 
-    // ---- delegate helper data ----
-    private static String sFontLocation;
 
     // ---- delegate data ----
 
@@ -61,11 +61,8 @@
 
     private static long sDefaultTypeface;
 
+
     // ---- Public Helper methods ----
-    public static synchronized void setFontLocation(String fontLocation) {
-        sFontLocation = fontLocation;
-        FontFamily_Delegate.setFontLocation(fontLocation);
-    }
 
     public static Typeface_Delegate getDelegate(long nativeTypeface) {
         return sManager.getDelegate(nativeTypeface);
@@ -131,6 +128,18 @@
         return fonts;
     }
 
+    /**
+     * Clear the default typefaces when disposing bridge.
+     */
+    public static void resetDefaults() {
+        // Sometimes this is called before the Bridge is initialized. In that case, we don't want to
+        // initialize Typeface because the SDK fonts location hasn't been set.
+        if (FontFamily_Delegate.getFontLocation() != null) {
+            Typeface.sDefaults = null;
+        }
+    }
+
+
     // ---- native methods ----
 
     @LayoutlibDelegate
@@ -193,7 +202,7 @@
 
     @LayoutlibDelegate
     /*package*/ static File getSystemFontConfigLocation() {
-        return new File(sFontLocation);
+        return new File(getFontLocation());
     }
 
     // ---- Private delegate/helper methods ----
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 3d0e1e8..825731b 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -38,7 +38,7 @@
 
 import android.content.res.BridgeAssetManager;
 import android.graphics.Bitmap;
-import android.graphics.Typeface_Accessor;
+import android.graphics.FontFamily_Delegate;
 import android.graphics.Typeface_Delegate;
 import android.os.Looper;
 import android.os.Looper_Accessor;
@@ -250,7 +250,7 @@
         }
 
         // load the fonts.
-        Typeface_Delegate.setFontLocation(fontLocation.getAbsolutePath());
+        FontFamily_Delegate.setFontLocation(fontLocation.getAbsolutePath());
 
         // now parse com.android.internal.R (and only this one as android.R is a subset of
         // the internal version), and put the content in the maps.
@@ -303,7 +303,7 @@
         BridgeAssetManager.clearSystem();
 
         // dispose of the default typeface.
-        Typeface_Accessor.resetDefaults();
+        Typeface_Delegate.resetDefaults();
 
         return true;
     }
diff --git a/tools/split-select/Abi.cpp b/tools/split-select/Abi.cpp
new file mode 100644
index 0000000..20654b6
--- /dev/null
+++ b/tools/split-select/Abi.cpp
@@ -0,0 +1,83 @@
+/*
+ * 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 "Abi.h"
+
+namespace split {
+namespace abi {
+
+static const std::vector<Variant> sNoneVariants = {};
+static const std::vector<Variant> sArmVariants =
+        {Variant::armeabi, Variant::armeabi_v7a, Variant::arm64_v8a};
+static const std::vector<Variant> sIntelVariants = {Variant::x86, Variant::x86_64};
+static const std::vector<Variant> sMipsVariants = {Variant::mips, Variant::mips64};
+
+Family getFamily(Variant variant) {
+    switch (variant) {
+        case Variant::none:
+            return Family::none;
+        case Variant::armeabi:
+        case Variant::armeabi_v7a:
+        case Variant::arm64_v8a:
+            return Family::arm;
+        case Variant::x86:
+        case Variant::x86_64:
+            return Family::intel;
+        case Variant::mips:
+        case Variant::mips64:
+            return Family::mips;
+    }
+    return Family::none;
+}
+
+const std::vector<Variant>& getVariants(Family family) {
+    switch (family) {
+        case Family::none:
+            return sNoneVariants;
+        case Family::arm:
+            return sArmVariants;
+        case Family::intel:
+            return sIntelVariants;
+        case Family::mips:
+            return sMipsVariants;
+    }
+    return sNoneVariants;
+}
+
+const char* toString(Variant variant) {
+    switch (variant) {
+        case Variant::none:
+            return "";
+        case Variant::armeabi:
+            return "armeabi";
+        case Variant::armeabi_v7a:
+            return "armeabi-v7a";
+        case Variant::arm64_v8a:
+            return "arm64-v8a";
+        case Variant::x86:
+            return "x86";
+        case Variant::x86_64:
+            return "x86_64";
+        case Variant::mips:
+            return "mips";
+        case Variant::mips64:
+            return "mips64";
+    }
+    return "";
+}
+
+} // namespace abi
+} // namespace split
diff --git a/tools/split-select/Abi.h b/tools/split-select/Abi.h
new file mode 100644
index 0000000..3e00eba
--- /dev/null
+++ b/tools/split-select/Abi.h
@@ -0,0 +1,50 @@
+/*
+ * 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 H_ANDROID_SPLIT_ABI
+#define H_ANDROID_SPLIT_ABI
+
+#include <vector>
+
+namespace split {
+namespace abi {
+
+enum class Variant {
+    none = 0,
+    armeabi,
+    armeabi_v7a,
+    arm64_v8a,
+    x86,
+    x86_64,
+    mips,
+    mips64,
+};
+
+enum class Family {
+    none,
+    arm,
+    intel,
+    mips,
+};
+
+Family getFamily(Variant variant);
+const std::vector<Variant>& getVariants(Family family);
+const char* toString(Variant variant);
+
+} // namespace abi
+} // namespace split
+
+#endif // H_ANDROID_SPLIT_ABI
diff --git a/tools/split-select/Android.mk b/tools/split-select/Android.mk
new file mode 100644
index 0000000..d0b7287
--- /dev/null
+++ b/tools/split-select/Android.mk
@@ -0,0 +1,119 @@
+#
+# 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.
+#
+
+# This tool is prebuilt if we're doing an app-only build.
+ifeq ($(TARGET_BUILD_APPS)$(filter true,$(TARGET_BUILD_PDK)),)
+
+# TODO(adamlesinski): Enable OS X builds when I figure out how
+# to build with clang and libc++
+ifneq ($(HOST_OS),darwin)
+
+# ==========================================================
+# Setup some common variables for the different build
+# targets here.
+# ==========================================================
+LOCAL_PATH:= $(call my-dir)
+
+main := Main.cpp
+sources := \
+    Abi.cpp \
+    Grouper.cpp \
+    Rule.cpp \
+    RuleGenerator.cpp \
+    SplitDescription.cpp
+
+testSources := \
+    Grouper_test.cpp \
+    Rule_test.cpp \
+    RuleGenerator_test.cpp
+
+cIncludes := \
+    external/zlib \
+    frameworks/base/tools
+
+hostLdLibs :=
+hostStaticLibs := \
+    libaapt \
+    libandroidfw \
+    libpng \
+    liblog \
+    libutils \
+    libcutils \
+    libexpat \
+    libziparchive-host
+
+cFlags := -std=c++11 -Wall -Werror
+
+ifeq ($(HOST_OS),linux)
+    hostLdLibs += -lrt -ldl -lpthread
+endif
+
+# Statically link libz for MinGW (Win SDK under Linux),
+# and dynamically link for all others.
+ifneq ($(strip $(USE_MINGW)),)
+    hostStaticLibs += libz
+else
+    hostLdLibs += -lz
+endif
+
+
+# ==========================================================
+# Build the host static library: libsplit-select
+# ==========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := libsplit-select
+
+LOCAL_SRC_FILES := $(sources)
+
+LOCAL_C_INCLUDES += $(cIncludes)
+LOCAL_CFLAGS += $(cFlags) -D_DARWIN_UNLIMITED_STREAMS
+
+include $(BUILD_HOST_STATIC_LIBRARY)
+
+
+# ==========================================================
+# Build the host tests: libsplit-select_tests
+# ==========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := libsplit-select_tests
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(testSources)
+
+LOCAL_C_INCLUDES += $(cIncludes)
+LOCAL_STATIC_LIBRARIES += libsplit-select $(hostStaticLibs)
+LOCAL_LDLIBS += $(hostLdLibs)
+LOCAL_CFLAGS += $(cFlags)
+
+include $(BUILD_HOST_NATIVE_TEST)
+
+# ==========================================================
+# Build the host executable: split-select
+# ==========================================================
+include $(CLEAR_VARS)
+LOCAL_MODULE := split-select
+
+LOCAL_SRC_FILES := $(main)
+
+LOCAL_C_INCLUDES += $(cIncludes)
+LOCAL_STATIC_LIBRARIES += libsplit-select $(hostStaticLibs)
+LOCAL_LDLIBS += $(hostLdLibs)
+LOCAL_CFLAGS += $(cFlags)
+
+include $(BUILD_HOST_EXECUTABLE)
+
+endif # Not OS X
+endif # No TARGET_BUILD_APPS or TARGET_BUILD_PDK
diff --git a/tools/split-select/Grouper.cpp b/tools/split-select/Grouper.cpp
new file mode 100644
index 0000000..15edf89
--- /dev/null
+++ b/tools/split-select/Grouper.cpp
@@ -0,0 +1,83 @@
+/*
+ * 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 "Grouper.h"
+
+#include "SplitDescription.h"
+
+#include <utils/KeyedVector.h>
+#include <utils/Vector.h>
+
+using namespace android;
+
+namespace split {
+
+template <typename Key, typename Value>
+static void addToVector(KeyedVector<Key, SortedVector<Value> >& group,
+        const Key& key, const Value& value) {
+    ssize_t idx = group.indexOfKey(key);
+    if (idx < 0) {
+        idx = group.add(key, SortedVector<Value>());
+    }
+    group.editValueAt(idx).add(value);
+}
+
+Vector<SortedVector<SplitDescription> >
+groupByMutualExclusivity(const Vector<SplitDescription>& splits) {
+    Vector<SortedVector<SplitDescription> > groups;
+
+    // Find mutually exclusive splits and group them.
+    KeyedVector<SplitDescription, SortedVector<SplitDescription> > densityGroups;
+    KeyedVector<SplitDescription, SortedVector<SplitDescription> > abiGroups;
+    KeyedVector<SplitDescription, SortedVector<SplitDescription> > localeGroups;
+    for (const SplitDescription& split : splits) {
+        if (split.config.density != 0) {
+            SplitDescription key(split);
+            key.config.density = 0;
+            key.config.sdkVersion = 0; // Ignore density so we can support anydpi.
+            addToVector(densityGroups, key, split);
+        } else if (split.abi != abi::Variant::none) {
+            SplitDescription key(split);
+            key.abi = abi::Variant::none;
+            addToVector(abiGroups, key, split);
+        } else if (split.config.locale != 0) {
+            SplitDescription key(split);
+            key.config.clearLocale();
+            addToVector(localeGroups, key, split);
+        } else {
+            groups.add();
+            groups.editTop().add(split);
+        }
+    }
+
+    const size_t densityCount = densityGroups.size();
+    for (size_t i = 0; i < densityCount; i++) {
+        groups.add(densityGroups[i]);
+    }
+
+    const size_t abiCount = abiGroups.size();
+    for (size_t i = 0; i < abiCount; i++) {
+        groups.add(abiGroups[i]);
+    }
+
+    const size_t localeCount = localeGroups.size();
+    for (size_t i = 0; i < localeCount; i++) {
+        groups.add(localeGroups[i]);
+    }
+    return groups;
+}
+
+} // namespace split
diff --git a/tools/split-select/Grouper.h b/tools/split-select/Grouper.h
new file mode 100644
index 0000000..5cb0b5b
--- /dev/null
+++ b/tools/split-select/Grouper.h
@@ -0,0 +1,32 @@
+/*
+ * 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 H_ANDROID_SPLIT_GROUPER
+#define H_ANDROID_SPLIT_GROUPER
+
+#include "SplitDescription.h"
+
+#include <utils/SortedVector.h>
+#include <utils/Vector.h>
+
+namespace split {
+
+android::Vector<android::SortedVector<SplitDescription> >
+groupByMutualExclusivity(const android::Vector<SplitDescription>& splits);
+
+} // namespace split
+
+#endif // H_ANDROID_SPLIT_GROUPER
diff --git a/tools/split-select/Grouper_test.cpp b/tools/split-select/Grouper_test.cpp
new file mode 100644
index 0000000..4d146cd
--- /dev/null
+++ b/tools/split-select/Grouper_test.cpp
@@ -0,0 +1,151 @@
+/*
+ * 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 "Grouper.h"
+
+#include "SplitDescription.h"
+
+#include <gtest/gtest.h>
+#include <initializer_list>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+using namespace android;
+
+namespace split {
+
+class GrouperTest : public ::testing::Test {
+protected:
+    virtual void SetUp() {
+        Vector<SplitDescription> splits;
+        addSplit(splits, "en-rUS-sw600dp-hdpi");
+        addSplit(splits, "fr-rFR-sw600dp-hdpi");
+        addSplit(splits, "fr-rFR-sw600dp-xhdpi");
+        addSplit(splits, ":armeabi");
+        addSplit(splits, "en-rUS-sw300dp-xhdpi");
+        addSplit(splits, "large");
+        addSplit(splits, "pl-rPL");
+        addSplit(splits, "xlarge");
+        addSplit(splits, "en-rUS-sw600dp-xhdpi");
+        addSplit(splits, "en-rUS-sw300dp-hdpi");
+        addSplit(splits, "xxhdpi");
+        addSplit(splits, "hdpi");
+        addSplit(splits, "de-rDE");
+        addSplit(splits, "xhdpi");
+        addSplit(splits, ":x86");
+        addSplit(splits, "anydpi");
+        addSplit(splits, "v7");
+        addSplit(splits, "v8");
+        addSplit(splits, "sw600dp");
+        addSplit(splits, "sw300dp");
+        mGroups = groupByMutualExclusivity(splits);
+    }
+
+    void addSplit(Vector<SplitDescription>& splits, const char* str);
+    void expectHasGroupWithSplits(std::initializer_list<const char*> l);
+
+    Vector<SortedVector<SplitDescription> > mGroups;
+};
+
+TEST_F(GrouperTest, shouldHaveCorrectNumberOfGroups) {
+    EXPECT_EQ(12u, mGroups.size());
+}
+
+TEST_F(GrouperTest, shouldGroupDensities) {
+    expectHasGroupWithSplits({"en-rUS-sw300dp-hdpi", "en-rUS-sw300dp-xhdpi"});
+    expectHasGroupWithSplits({"en-rUS-sw600dp-hdpi", "en-rUS-sw600dp-xhdpi"});
+    expectHasGroupWithSplits({"fr-rFR-sw600dp-hdpi", "fr-rFR-sw600dp-xhdpi"});
+    expectHasGroupWithSplits({"hdpi", "xhdpi", "xxhdpi", "anydpi"});
+}
+
+TEST_F(GrouperTest, shouldGroupAbi) {
+    expectHasGroupWithSplits({":armeabi", ":x86"});
+}
+
+TEST_F(GrouperTest, shouldGroupLocale) {
+    expectHasGroupWithSplits({"pl-rPL", "de-rDE"});
+}
+
+TEST_F(GrouperTest, shouldGroupEachSplitIntoItsOwnGroup) {
+    expectHasGroupWithSplits({"large"});
+    expectHasGroupWithSplits({"xlarge"});
+    expectHasGroupWithSplits({"v7"});
+    expectHasGroupWithSplits({"v8"});
+    expectHasGroupWithSplits({"sw600dp"});
+    expectHasGroupWithSplits({"sw300dp"});
+}
+
+//
+// Helper methods
+//
+
+void GrouperTest::expectHasGroupWithSplits(std::initializer_list<const char*> l) {
+    Vector<SplitDescription> splits;
+    for (const char* str : l) {
+        splits.add();
+        if (!SplitDescription::parse(String8(str), &splits.editTop())) {
+            ADD_FAILURE() << "Failed to parse SplitDescription " << str;
+            return;
+        }
+    }
+    const size_t splitCount = splits.size();
+
+    const size_t groupCount = mGroups.size();
+    for (size_t i = 0; i < groupCount; i++) {
+        const SortedVector<SplitDescription>& group = mGroups[i];
+        if (group.size() != splitCount) {
+            continue;
+        }
+
+        size_t found = 0;
+        for (size_t j = 0; j < splitCount; j++) {
+            if (group.indexOf(splits[j]) >= 0) {
+                found++;
+            }
+        }
+
+        if (found == splitCount) {
+            return;
+        }
+    }
+
+    String8 errorMessage("Failed to find expected group [");
+    for (size_t i = 0; i < splitCount; i++) {
+        if (i != 0) {
+            errorMessage.append(", ");
+        }
+        errorMessage.append(splits[i].toString());
+    }
+    errorMessage.append("].\nActual:\n");
+
+    for (size_t i = 0; i < groupCount; i++) {
+        errorMessage.appendFormat("Group %d:\n", int(i + 1));
+        const SortedVector<SplitDescription>& group = mGroups[i];
+        for (size_t j = 0; j < group.size(); j++) {
+            errorMessage.append("  ");
+            errorMessage.append(group[j].toString());
+            errorMessage.append("\n");
+        }
+    }
+    ADD_FAILURE() << errorMessage.string();
+}
+
+void GrouperTest::addSplit(Vector<SplitDescription>& splits, const char* str) {
+    splits.add();
+    EXPECT_TRUE(SplitDescription::parse(String8(str), &splits.editTop()));
+}
+
+} // namespace split
diff --git a/tools/split-select/Main.cpp b/tools/split-select/Main.cpp
new file mode 100644
index 0000000..d6251c3
--- /dev/null
+++ b/tools/split-select/Main.cpp
@@ -0,0 +1,314 @@
+/*
+ * 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 <algorithm>
+#include <cstdio>
+
+#include "aapt/AaptUtil.h"
+
+#include "Grouper.h"
+#include "Rule.h"
+#include "RuleGenerator.h"
+#include "SplitDescription.h"
+
+#include <androidfw/AssetManager.h>
+#include <androidfw/ResourceTypes.h>
+#include <utils/KeyedVector.h>
+#include <utils/Vector.h>
+
+using namespace android;
+
+namespace split {
+
+static void usage() {
+    fprintf(stderr,
+            "split-select --help\n"
+            "split-select --target <config> --split <path/to/apk> [--split <path/to/apk> [...]]\n"
+            "split-select --generate --split <path/to/apk> [--split <path/to/apk> [...]]\n"
+            "\n"
+            "  --help                   Displays more information about this program.\n"
+            "  --target <config>        Performs the Split APK selection on the given configuration.\n"
+            "  --generate               Generates the logic for selecting the Split APK, in JSON format.\n"
+            "  --split <path/to/apk>    Includes a Split APK in the selection process.\n"
+            "\n"
+            "  Where <config> is an extended AAPT resource qualifier of the form\n"
+            "  'resource-qualifiers:extended-qualifiers', where 'resource-qualifiers' is an AAPT resource\n"
+            "  qualifier (ex: en-rUS-sw600dp-xhdpi), and 'extended-qualifiers' is an ordered list of one\n"
+            "  qualifier (or none) from each category:\n"
+            "    Architecture: armeabi, armeabi-v7a, arm64-v8a, x86, x86_64, mips\n");
+}
+
+static void help() {
+    usage();
+    fprintf(stderr, "\n"
+            "  Generates the logic for selecting a Split APK given some target Android device configuration.\n"
+            "  Using the flag --generate will emit a JSON encoded tree of rules that must be satisfied in order\n"
+            "  to install the given Split APK. Using the flag --target along with the device configuration\n"
+            "  will emit the set of Split APKs to install, following the same logic that would have been emitted\n"
+            "  via JSON.\n");
+}
+
+class SplitSelector {
+public:
+    SplitSelector() = default;
+    SplitSelector(const Vector<SplitDescription>& splits);
+
+    Vector<SplitDescription> getBestSplits(const SplitDescription& target) const;
+
+    template <typename RuleGenerator>
+    KeyedVector<SplitDescription, sp<Rule> > getRules() const;
+
+private:
+    Vector<SortedVector<SplitDescription> > mGroups;
+};
+
+SplitSelector::SplitSelector(const Vector<SplitDescription>& splits)
+    : mGroups(groupByMutualExclusivity(splits)) {
+}
+
+static void selectBestFromGroup(const SortedVector<SplitDescription>& splits,
+        const SplitDescription& target, Vector<SplitDescription>& splitsOut) {
+    SplitDescription bestSplit;
+    bool isSet = false;
+    const size_t splitCount = splits.size();
+    for (size_t j = 0; j < splitCount; j++) {
+        const SplitDescription& thisSplit = splits[j];
+        if (!thisSplit.match(target)) {
+            continue;
+        }
+
+        if (!isSet || thisSplit.isBetterThan(bestSplit, target)) {
+            isSet = true;
+            bestSplit = thisSplit;
+        }
+    }
+
+    if (isSet) {
+        splitsOut.add(bestSplit);
+    }
+}
+
+Vector<SplitDescription> SplitSelector::getBestSplits(const SplitDescription& target) const {
+    Vector<SplitDescription> bestSplits;
+    const size_t groupCount = mGroups.size();
+    for (size_t i = 0; i < groupCount; i++) {
+        selectBestFromGroup(mGroups[i], target, bestSplits);
+    }
+    return bestSplits;
+}
+
+template <typename RuleGenerator>
+KeyedVector<SplitDescription, sp<Rule> > SplitSelector::getRules() const {
+    KeyedVector<SplitDescription, sp<Rule> > rules;
+
+    const size_t groupCount = mGroups.size();
+    for (size_t i = 0; i < groupCount; i++) {
+        const SortedVector<SplitDescription>& splits = mGroups[i];
+        const size_t splitCount = splits.size();
+        for (size_t j = 0; j < splitCount; j++) {
+            sp<Rule> rule = Rule::simplify(RuleGenerator::generate(splits, j));
+            if (rule != NULL) {
+                rules.add(splits[j], rule);
+            }
+        }
+    }
+    return rules;
+}
+
+Vector<SplitDescription> select(const SplitDescription& target, const Vector<SplitDescription>& splits) {
+    const SplitSelector selector(splits);
+    return selector.getBestSplits(target);
+}
+
+void generate(const KeyedVector<String8, Vector<SplitDescription> >& splits) {
+    Vector<SplitDescription> allSplits;
+    const size_t apkSplitCount = splits.size();
+    for (size_t i = 0; i < apkSplitCount; i++) {
+        allSplits.appendVector(splits[i]);
+    }
+    const SplitSelector selector(allSplits);
+    KeyedVector<SplitDescription, sp<Rule> > rules(selector.getRules<RuleGenerator>());
+
+    fprintf(stdout, "[\n");
+    for (size_t i = 0; i < apkSplitCount; i++) {
+        sp<Rule> masterRule = new Rule();
+        masterRule->op = Rule::OR_SUBRULES;
+        const Vector<SplitDescription>& splitDescriptions = splits[i];
+        const size_t splitDescriptionCount = splitDescriptions.size();
+        for (size_t j = 0; j < splitDescriptionCount; j++) {
+            masterRule->subrules.add(rules.valueFor(splitDescriptions[j]));
+        }
+        masterRule = Rule::simplify(masterRule);
+        fprintf(stdout, "  {\n    \"path\": \"%s\",\n    \"rules\": %s\n  }%s\n",
+                splits.keyAt(i).string(),
+                masterRule->toJson(2).string(),
+                i < apkSplitCount - 1 ? "," : "");
+    }
+    fprintf(stdout, "]\n");
+}
+
+static void removeRuntimeQualifiers(ConfigDescription* outConfig) {
+    outConfig->imsi = 0;
+    outConfig->orientation = ResTable_config::ORIENTATION_ANY;
+    outConfig->screenWidth = ResTable_config::SCREENWIDTH_ANY;
+    outConfig->screenHeight = ResTable_config::SCREENHEIGHT_ANY;
+    outConfig->uiMode &= ResTable_config::UI_MODE_NIGHT_ANY;
+}
+
+static Vector<SplitDescription> extractSplitDescriptionsFromApk(const String8& path) {
+    AssetManager assetManager;
+    Vector<SplitDescription> splits;
+    int32_t cookie = 0;
+    if (!assetManager.addAssetPath(path, &cookie)) {
+        return splits;
+    }
+
+    const ResTable& res = assetManager.getResources(false);
+    if (res.getError() == NO_ERROR) {
+        Vector<ResTable_config> configs;
+        res.getConfigurations(&configs);
+        const size_t configCount = configs.size();
+        for (size_t i = 0; i < configCount; i++) {
+            splits.add();
+            splits.editTop().config = configs[i];
+        }
+    }
+
+    AssetDir* dir = assetManager.openNonAssetDir(cookie, "lib");
+    if (dir != NULL) {
+        const size_t fileCount = dir->getFileCount();
+        for (size_t i = 0; i < fileCount; i++) {
+            splits.add();
+            Vector<String8> parts = AaptUtil::splitAndLowerCase(dir->getFileName(i), '-');
+            if (parseAbi(parts, 0, &splits.editTop()) < 0) {
+                fprintf(stderr, "Malformed library %s\n", dir->getFileName(i).string());
+                splits.pop();
+            }
+        }
+        delete dir;
+    }
+    return splits;
+}
+
+static int main(int argc, char** argv) {
+    // Skip over the first argument.
+    argc--;
+    argv++;
+
+    bool generateFlag = false;
+    String8 targetConfigStr;
+    Vector<String8> splitApkPaths;
+    while (argc > 0) {
+        const String8 arg(*argv);
+        if (arg == "--target") {
+            argc--;
+            argv++;
+            if (argc < 1) {
+                fprintf(stderr, "Missing parameter for --split.\n");
+                usage();
+                return 1;
+            }
+            targetConfigStr.setTo(*argv);
+        } else if (arg == "--split") {
+            argc--;
+            argv++;
+            if (argc < 1) {
+                fprintf(stderr, "Missing parameter for --split.\n");
+                usage();
+                return 1;
+            }
+            splitApkPaths.add(String8(*argv));
+        } else if (arg == "--generate") {
+            generateFlag = true;
+        } else if (arg == "--help") {
+            help();
+            return 0;
+        } else {
+            fprintf(stderr, "Unknown argument '%s'\n", arg.string());
+            usage();
+            return 1;
+        }
+        argc--;
+        argv++;
+    }
+
+    if (!generateFlag && targetConfigStr == "") {
+        usage();
+        return 1;
+    }
+
+    if (splitApkPaths.size() == 0) {
+        usage();
+        return 1;
+    }
+
+    SplitDescription targetSplit;
+    if (!generateFlag) {
+        if (!SplitDescription::parse(targetConfigStr, &targetSplit)) {
+            fprintf(stderr, "Invalid --target config: '%s'\n",
+                    targetConfigStr.string());
+            usage();
+            return 1;
+        }
+
+        // We don't want to match on things that will change at run-time
+        // (orientation, w/h, etc.).
+        removeRuntimeQualifiers(&targetSplit.config);
+    }
+
+    KeyedVector<String8, Vector<SplitDescription> > apkPathSplitMap;
+    KeyedVector<SplitDescription, String8> splitApkPathMap;
+    Vector<SplitDescription> splitConfigs;
+    const size_t splitCount = splitApkPaths.size();
+    for (size_t i = 0; i < splitCount; i++) {
+        Vector<SplitDescription> splits = extractSplitDescriptionsFromApk(splitApkPaths[i]);
+        if (splits.isEmpty()) {
+            fprintf(stderr, "Invalid --split path: '%s'. No splits found.\n",
+                    splitApkPaths[i].string());
+            usage();
+            return 1;
+        }
+        apkPathSplitMap.replaceValueFor(splitApkPaths[i], splits);
+        const size_t apkSplitDescriptionCount = splits.size();
+        for (size_t j = 0; j < apkSplitDescriptionCount; j++) {
+            splitApkPathMap.replaceValueFor(splits[j], splitApkPaths[i]);
+        }
+        splitConfigs.appendVector(splits);
+    }
+
+    if (!generateFlag) {
+        Vector<SplitDescription> matchingConfigs = select(targetSplit, splitConfigs);
+        const size_t matchingConfigCount = matchingConfigs.size();
+        SortedVector<String8> matchingSplitPaths;
+        for (size_t i = 0; i < matchingConfigCount; i++) {
+            matchingSplitPaths.add(splitApkPathMap.valueFor(matchingConfigs[i]));
+        }
+
+        const size_t matchingSplitApkPathCount = matchingSplitPaths.size();
+        for (size_t i = 0; i < matchingSplitApkPathCount; i++) {
+            fprintf(stderr, "%s\n", matchingSplitPaths[i].string());
+        }
+    } else {
+        generate(apkPathSplitMap);
+    }
+    return 0;
+}
+
+} // namespace split
+
+int main(int argc, char** argv) {
+    return split::main(argc, argv);
+}
diff --git a/tools/split-select/Rule.cpp b/tools/split-select/Rule.cpp
new file mode 100644
index 0000000..9559fe2
--- /dev/null
+++ b/tools/split-select/Rule.cpp
@@ -0,0 +1,196 @@
+/*
+ * 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 "Rule.h"
+
+#include <utils/String8.h>
+
+using namespace android;
+
+namespace split {
+
+inline static void indentStr(String8& str, int indent) {
+    while (indent > 0) {
+        str.append("  ");
+        indent--;
+    }
+}
+
+String8 Rule::toJson(int indent) const {
+    String8 str;
+    indentStr(str, indent);
+    str.append("{\n");
+    indent++;
+    indentStr(str, indent);
+    str.append("\"op\": \"");
+    switch (op) {
+        case ALWAYS_TRUE:
+            str.append("ALWAYS_TRUE");
+            break;
+        case GREATER_THAN:
+            str.append("GREATER_THAN");
+            break;
+        case LESS_THAN:
+            str.append("LESS_THAN");
+            break;
+        case EQUALS:
+            str.append("EQUALS");
+            break;
+        case AND_SUBRULES:
+            str.append("AND_SUBRULES");
+            break;
+        case OR_SUBRULES:
+            str.append("OR_SUBRULES");
+            break;
+        case CONTAINS_ANY:
+            str.append("CONTAINS_ANY");
+            break;
+        default:
+            str.appendFormat("%d", op);
+            break;
+    }
+    str.append("\"");
+
+    if (negate) {
+        str.append(",\n");
+        indentStr(str, indent);
+        str.append("\"negate\": true");
+    }
+
+    bool includeKey = true;
+    switch (op) {
+        case AND_SUBRULES:
+        case OR_SUBRULES:
+            includeKey = false;
+            break;
+        default:
+            break;
+    }
+
+    if (includeKey) {
+        str.append(",\n");
+        indentStr(str, indent);
+        str.append("\"property\": \"");
+        switch (key) {
+            case NONE:
+                str.append("NONE");
+                break;
+            case SDK_VERSION:
+                str.append("SDK_VERSION");
+                break;
+            case SCREEN_DENSITY:
+                str.append("SCREEN_DENSITY");
+                break;
+            case NATIVE_PLATFORM:
+                str.append("NATIVE_PLATFORM");
+                break;
+            case LANGUAGE:
+                str.append("LANGUAGE");
+                break;
+            default:
+                str.appendFormat("%d", key);
+                break;
+        }
+        str.append("\"");
+    }
+
+    if (op == AND_SUBRULES || op == OR_SUBRULES) {
+        str.append(",\n");
+        indentStr(str, indent);
+        str.append("\"subrules\": [\n");
+        const size_t subruleCount = subrules.size();
+        for (size_t i = 0; i < subruleCount; i++) {
+            str.append(subrules[i]->toJson(indent + 1));
+            if (i != subruleCount - 1) {
+                str.append(",");
+            }
+            str.append("\n");
+        }
+        indentStr(str, indent);
+        str.append("]");
+    } else {
+        switch (key) {
+            case SDK_VERSION:
+            case SCREEN_DENSITY: {
+                str.append(",\n");
+                indentStr(str, indent);
+                str.append("\"args\": [");
+                const size_t argCount = longArgs.size();
+                for (size_t i = 0; i < argCount; i++) {
+                    if (i != 0) {
+                        str.append(", ");
+                    }
+                    str.appendFormat("%d", longArgs[i]);
+                }
+                str.append("]");
+                break;
+            }
+            case LANGUAGE:
+            case NATIVE_PLATFORM: {
+                str.append(",\n");
+                indentStr(str, indent);
+                str.append("\"args\": [");
+                const size_t argCount = stringArgs.size();
+                for (size_t i = 0; i < argCount; i++) {
+                    if (i != 0) {
+                        str.append(", ");
+                    }
+                    str.append(stringArgs[i]);
+                }
+                str.append("]");
+                break;
+            }
+            default:
+                break;
+        }
+    }
+    str.append("\n");
+    indent--;
+    indentStr(str, indent);
+    str.append("}");
+    return str;
+}
+
+sp<Rule> Rule::simplify(sp<Rule> rule) {
+    if (rule->op != AND_SUBRULES && rule->op != OR_SUBRULES) {
+        return rule;
+    }
+
+    Vector<sp<Rule> > newSubrules;
+    newSubrules.setCapacity(rule->subrules.size());
+    const size_t subruleCount = rule->subrules.size();
+    for (size_t i = 0; i < subruleCount; i++) {
+        sp<Rule> simplifiedRule = simplify(rule->subrules.editItemAt(i));
+        if (simplifiedRule != NULL) {
+            if (simplifiedRule->op == rule->op) {
+                newSubrules.appendVector(simplifiedRule->subrules);
+            } else {
+                newSubrules.add(simplifiedRule);
+            }
+        }
+    }
+
+    const size_t newSubruleCount = newSubrules.size();
+    if (newSubruleCount == 0) {
+        return NULL;
+    } else if (subruleCount == 1) {
+        return newSubrules.editTop();
+    }
+    rule->subrules = newSubrules;
+    return rule;
+}
+
+} // namespace split
diff --git a/tools/split-select/Rule.h b/tools/split-select/Rule.h
new file mode 100644
index 0000000..8029931
--- /dev/null
+++ b/tools/split-select/Rule.h
@@ -0,0 +1,78 @@
+/*
+ * 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 H_ANDROID_SPLIT_RULE
+#define H_ANDROID_SPLIT_RULE
+
+#include "SplitDescription.h"
+
+#include <utils/RefBase.h>
+#include <utils/StrongPointer.h>
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+namespace split {
+
+struct Rule : public virtual android::RefBase {
+    inline Rule();
+
+    enum Operator {
+        LESS_THAN = 1,
+        GREATER_THAN,
+        EQUALS,
+        CONTAINS_ANY,
+        CONTAINS_ALL,
+        IS_TRUE,
+        IS_FALSE,
+        AND_SUBRULES,
+        OR_SUBRULES,
+        ALWAYS_TRUE,
+    };
+
+    Operator op;
+
+    enum Key {
+        NONE = 0,
+        SDK_VERSION,
+        SCREEN_DENSITY,
+        LANGUAGE,
+        NATIVE_PLATFORM,
+        TOUCH_SCREEN,
+        SCREEN_SIZE,
+        SCREEN_LAYOUT,
+    };
+
+    Key key;
+    bool negate;
+
+    android::Vector<android::String8> stringArgs;
+    android::Vector<int> longArgs;
+    android::Vector<double> doubleArgs;
+    android::Vector<android::sp<Rule> > subrules;
+
+    android::String8 toJson(int indent=0) const;
+
+    static android::sp<Rule> simplify(android::sp<Rule> rule);
+};
+
+Rule::Rule()
+: op(ALWAYS_TRUE)
+, key(NONE)
+, negate(false) {}
+
+} // namespace split
+
+#endif // H_ANDROID_SPLIT_RULE
diff --git a/tools/split-select/RuleGenerator.cpp b/tools/split-select/RuleGenerator.cpp
new file mode 100644
index 0000000..669ae78
--- /dev/null
+++ b/tools/split-select/RuleGenerator.cpp
@@ -0,0 +1,153 @@
+/*
+ * 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 "RuleGenerator.h"
+
+#include <algorithm>
+#include <cmath>
+#include <vector>
+#include <androidfw/ResourceTypes.h>
+
+using namespace android;
+
+namespace split {
+
+// Calculate the point at which the density selection changes between l and h.
+static inline int findMid(int l, int h) {
+    double root = sqrt((h*h) + (8*l*h));
+    return (double(-h) + root) / 2.0;
+}
+
+sp<Rule> RuleGenerator::generateDensity(const Vector<int>& allDensities, size_t index) {
+    sp<Rule> densityRule = new Rule();
+    densityRule->op = Rule::AND_SUBRULES;
+
+    const bool anyDensity = allDensities[index] == ResTable_config::DENSITY_ANY;
+    sp<Rule> any = new Rule();
+    any->op = Rule::EQUALS;
+    any->key = Rule::SCREEN_DENSITY;
+    any->longArgs.add((int)ResTable_config::DENSITY_ANY);
+    any->negate = !anyDensity;
+    densityRule->subrules.add(any);
+
+    if (!anyDensity) {
+        if (index > 0) {
+            sp<Rule> gt = new Rule();
+            gt->op = Rule::GREATER_THAN;
+            gt->key = Rule::SCREEN_DENSITY;
+            gt->longArgs.add(findMid(allDensities[index - 1], allDensities[index]) - 1);
+            densityRule->subrules.add(gt);
+        }
+
+        if (index + 1 < allDensities.size() && allDensities[index + 1] != ResTable_config::DENSITY_ANY) {
+            sp<Rule> lt = new Rule();
+            lt->op = Rule::LESS_THAN;
+            lt->key = Rule::SCREEN_DENSITY;
+            lt->longArgs.add(findMid(allDensities[index], allDensities[index + 1]));
+            densityRule->subrules.add(lt);
+        }
+    }
+    return densityRule;
+}
+
+sp<Rule> RuleGenerator::generateAbi(const Vector<abi::Variant>& splitAbis, size_t index) {
+    const abi::Variant thisAbi = splitAbis[index];
+    const std::vector<abi::Variant>& familyVariants = abi::getVariants(abi::getFamily(thisAbi));
+
+    std::vector<abi::Variant>::const_iterator start =
+            std::find(familyVariants.begin(), familyVariants.end(), thisAbi);
+
+    std::vector<abi::Variant>::const_iterator end = familyVariants.end();
+    if (index + 1 < splitAbis.size()) {
+        end = std::find(start, familyVariants.end(), splitAbis[index + 1]);
+    }
+
+    sp<Rule> abiRule = new Rule();
+    abiRule->op = Rule::CONTAINS_ANY;
+    abiRule->key = Rule::NATIVE_PLATFORM;
+    while (start != end) {
+        abiRule->stringArgs.add(String8(abi::toString(*start)));
+        ++start;
+    }
+    return abiRule;
+}
+
+sp<Rule> RuleGenerator::generate(const SortedVector<SplitDescription>& group, size_t index) {
+    sp<Rule> rootRule = new Rule();
+    rootRule->op = Rule::AND_SUBRULES;
+
+    if (group[index].config.locale != 0) {
+        sp<Rule> locale = new Rule();
+        locale->op = Rule::EQUALS;
+        locale->key = Rule::LANGUAGE;
+        char str[RESTABLE_MAX_LOCALE_LEN];
+        group[index].config.getBcp47Locale(str);
+        locale->stringArgs.add(String8(str));
+        rootRule->subrules.add(locale);
+    }
+
+    if (group[index].config.sdkVersion != 0) {
+        sp<Rule> sdk = new Rule();
+        sdk->op = Rule::GREATER_THAN;
+        sdk->key = Rule::SDK_VERSION;
+        sdk->longArgs.add(group[index].config.sdkVersion - 1);
+        rootRule->subrules.add(sdk);
+    }
+
+    if (group[index].config.density != 0) {
+        size_t densityIndex = 0;
+        Vector<int> allDensities;
+        allDensities.add(group[index].config.density);
+
+        const size_t groupSize = group.size();
+        for (size_t i = 0; i < groupSize; i++) {
+            if (group[i].config.density != group[index].config.density) {
+                // This group differs by density.
+                allDensities.clear();
+                for (size_t j = 0; j < groupSize; j++) {
+                    allDensities.add(group[j].config.density);
+                }
+                densityIndex = index;
+                break;
+            }
+        }
+        rootRule->subrules.add(generateDensity(allDensities, densityIndex));
+    }
+
+    if (group[index].abi != abi::Variant::none) {
+        size_t abiIndex = 0;
+        Vector<abi::Variant> allVariants;
+        allVariants.add(group[index].abi);
+
+        const size_t groupSize = group.size();
+        for (size_t i = 0; i < groupSize; i++) {
+            if (group[i].abi != group[index].abi) {
+                // This group differs by ABI.
+                allVariants.clear();
+                for (size_t j = 0; j < groupSize; j++) {
+                    allVariants.add(group[j].abi);
+                }
+                abiIndex = index;
+                break;
+            }
+        }
+        rootRule->subrules.add(generateAbi(allVariants, abiIndex));
+    }
+
+    return rootRule;
+}
+
+} // namespace split
diff --git a/tools/split-select/RuleGenerator.h b/tools/split-select/RuleGenerator.h
new file mode 100644
index 0000000..619acd9
--- /dev/null
+++ b/tools/split-select/RuleGenerator.h
@@ -0,0 +1,39 @@
+/*
+ * 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 H_ANDROID_SPLIT_RULE_GENERATOR
+#define H_ANDROID_SPLIT_RULE_GENERATOR
+
+#include "Abi.h"
+#include "Rule.h"
+#include "SplitDescription.h"
+
+#include <utils/SortedVector.h>
+#include <utils/Vector.h>
+
+namespace split {
+
+struct RuleGenerator {
+    // Generate rules for a Split given the group of mutually exclusive splits it belongs to
+    static android::sp<Rule> generate(const android::SortedVector<SplitDescription>& group, size_t index);
+
+    static android::sp<Rule> generateAbi(const android::Vector<abi::Variant>& allVariants, size_t index);
+    static android::sp<Rule> generateDensity(const android::Vector<int>& allDensities, size_t index);
+};
+
+} // namespace split
+
+#endif // H_ANDROID_SPLIT_RULE_GENERATOR
diff --git a/tools/split-select/RuleGenerator_test.cpp b/tools/split-select/RuleGenerator_test.cpp
new file mode 100644
index 0000000..60baabe
--- /dev/null
+++ b/tools/split-select/RuleGenerator_test.cpp
@@ -0,0 +1,155 @@
+/*
+ * 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 "RuleGenerator.h"
+
+#include <algorithm>
+#include <gtest/gtest.h>
+#include <utils/String8.h>
+
+using namespace android;
+
+namespace split {
+
+static void expectDensityRule(const Vector<int>& densities, int density, int greaterThan, int lessThan);
+static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant,
+        std::initializer_list<const char*> matches);
+
+TEST(RuleGeneratorTest, testAbiRules) {
+    Vector<abi::Variant> abis;
+    abis.add(abi::Variant::armeabi);
+    abis.add(abi::Variant::armeabi_v7a);
+    abis.add(abi::Variant::x86);
+    std::sort(abis.begin(), abis.end());
+
+    expectAbiRule(abis, abi::Variant::armeabi, {"armeabi"});
+    expectAbiRule(abis, abi::Variant::armeabi_v7a, {"armeabi-v7a", "arm64-v8a"});
+    expectAbiRule(abis, abi::Variant::x86, {"x86", "x86_64"});
+}
+
+TEST(RuleGeneratorTest, testDensityRules) {
+    Vector<int> densities;
+    densities.add(ConfigDescription::DENSITY_HIGH);
+    densities.add(ConfigDescription::DENSITY_XHIGH);
+    densities.add(ConfigDescription::DENSITY_XXHIGH);
+    densities.add(ConfigDescription::DENSITY_ANY);
+
+    ASSERT_LT(263, ConfigDescription::DENSITY_XHIGH);
+    ASSERT_GT(262, ConfigDescription::DENSITY_HIGH);
+    ASSERT_LT(363, ConfigDescription::DENSITY_XXHIGH);
+    ASSERT_GT(362, ConfigDescription::DENSITY_XHIGH);
+
+    expectDensityRule(densities, ConfigDescription::DENSITY_HIGH, 0, 263);
+    expectDensityRule(densities, ConfigDescription::DENSITY_XHIGH, 262, 363);
+    expectDensityRule(densities, ConfigDescription::DENSITY_XXHIGH, 362, 0);
+    expectDensityRule(densities, ConfigDescription::DENSITY_ANY, 0, 0);
+}
+
+//
+// Helper methods.
+//
+
+static void expectDensityRule(const Vector<int>& densities, int density, int greaterThan, int lessThan) {
+    const int* iter = std::find(densities.begin(), densities.end(), density);
+    if (densities.end() == iter) {
+        ADD_FAILURE() << density << "dpi was not in the density list.";
+        return;
+    }
+
+    sp<Rule> rule = RuleGenerator::generateDensity(densities, iter - densities.begin());
+    if (rule->op != Rule::AND_SUBRULES) {
+        ADD_FAILURE() << "Op in rule for " << density << "dpi is not Rule::AND_SUBRULES.";
+        return;
+    }
+
+    size_t index = 0;
+
+    bool isAnyDpi = density == ConfigDescription::DENSITY_ANY;
+
+    sp<Rule> anyDpiRule = rule->subrules[index++];
+    EXPECT_EQ(Rule::EQUALS, anyDpiRule->op)
+            << "for " << density << "dpi ANY DPI rule";
+    EXPECT_EQ(Rule::SCREEN_DENSITY, anyDpiRule->key)
+            << "for " << density << "dpi ANY DPI rule";
+    EXPECT_EQ(isAnyDpi == false, anyDpiRule->negate)
+            << "for " << density << "dpi ANY DPI rule";
+    if (anyDpiRule->longArgs.size() == 1) {
+        EXPECT_EQ(ConfigDescription::DENSITY_ANY, anyDpiRule->longArgs[0])
+            << "for " << density << "dpi ANY DPI rule";
+    } else {
+        EXPECT_EQ(1u, anyDpiRule->longArgs.size())
+            << "for " << density << "dpi ANY DPI rule";
+    }
+
+
+    if (greaterThan != 0) {
+        sp<Rule> greaterThanRule = rule->subrules[index++];
+        EXPECT_EQ(Rule::GREATER_THAN, greaterThanRule->op)
+                << "for " << density << "dpi GREATER_THAN rule";
+        EXPECT_EQ(Rule::SCREEN_DENSITY, greaterThanRule->key)
+                << "for " << density << "dpi GREATER_THAN rule";
+        if (greaterThanRule->longArgs.size() == 1) {
+            EXPECT_EQ(greaterThan, greaterThanRule->longArgs[0])
+                << "for " << density << "dpi GREATER_THAN rule";
+        } else {
+            EXPECT_EQ(1u, greaterThanRule->longArgs.size())
+                << "for " << density << "dpi GREATER_THAN rule";
+        }
+    }
+
+    if (lessThan != 0) {
+        sp<Rule> lessThanRule = rule->subrules[index++];
+        EXPECT_EQ(Rule::LESS_THAN, lessThanRule->op)
+                << "for " << density << "dpi LESS_THAN rule";
+        EXPECT_EQ(Rule::SCREEN_DENSITY, lessThanRule->key)
+                << "for " << density << "dpi LESS_THAN rule";
+        if (lessThanRule->longArgs.size() == 1) {
+            EXPECT_EQ(lessThan, lessThanRule->longArgs[0])
+                << "for " << density << "dpi LESS_THAN rule";
+        } else {
+            EXPECT_EQ(1u, lessThanRule->longArgs.size())
+                << "for " << density << "dpi LESS_THAN rule";
+        }
+    }
+}
+
+static void expectAbiRule(const Vector<abi::Variant>& abis, abi::Variant variant,
+        std::initializer_list<const char*> matches) {
+    const abi::Variant* iter = std::find(abis.begin(), abis.end(), variant);
+    if (abis.end() == iter) {
+        ADD_FAILURE() << abi::toString(variant) << " was not in the abi list.";
+        return;
+    }
+
+    sp<Rule> rule = RuleGenerator::generateAbi(abis, iter - abis.begin());
+
+    EXPECT_EQ(Rule::CONTAINS_ANY, rule->op)
+            << "for " << abi::toString(variant) << " rule";
+    EXPECT_EQ(Rule::NATIVE_PLATFORM, rule->key)
+            << " for " << abi::toString(variant) << " rule";
+    EXPECT_EQ(matches.size(), rule->stringArgs.size())
+            << " for " << abi::toString(variant) << " rule";
+
+    for (const char* match : matches) {
+        if (rule->stringArgs.end() ==
+                std::find(rule->stringArgs.begin(), rule->stringArgs.end(), String8(match))) {
+            ADD_FAILURE() << "Rule for abi " << abi::toString(variant)
+                    << " does not contain match for expected abi " << match;
+        }
+    }
+}
+
+} // namespace split
diff --git a/tools/split-select/Rule_test.cpp b/tools/split-select/Rule_test.cpp
new file mode 100644
index 0000000..aca7433
--- /dev/null
+++ b/tools/split-select/Rule_test.cpp
@@ -0,0 +1,147 @@
+/*
+ * 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 "Rule.h"
+
+#include "SplitDescription.h"
+
+#include <algorithm>
+#include <string>
+#include <gtest/gtest.h>
+#include <utils/String8.h>
+
+using namespace android;
+
+namespace split {
+
+TEST(RuleTest, generatesValidJson) {
+    sp<Rule> rule = new Rule();
+    rule->op = Rule::AND_SUBRULES;
+
+    sp<Rule> subrule = new Rule();
+    subrule->op = Rule::EQUALS;
+    subrule->key = Rule::SDK_VERSION;
+    subrule->longArgs.add(7);
+    rule->subrules.add(subrule);
+
+    subrule = new Rule();
+    subrule->op = Rule::OR_SUBRULES;
+    rule->subrules.add(subrule);
+
+    sp<Rule> subsubrule = new Rule();
+    subsubrule->op = Rule::GREATER_THAN;
+    subsubrule->key = Rule::SCREEN_DENSITY;
+    subsubrule->longArgs.add(10);
+    subrule->subrules.add(subsubrule);
+
+    subsubrule = new Rule();
+    subsubrule->op = Rule::LESS_THAN;
+    subsubrule->key = Rule::SCREEN_DENSITY;
+    subsubrule->longArgs.add(5);
+    subrule->subrules.add(subsubrule);
+
+    std::string expected(
+            "{"
+            "  \"op\": \"AND_SUBRULES\","
+            "  \"subrules\": ["
+            "    {"
+            "      \"op\": \"EQUALS\","
+            "      \"property\": \"SDK_VERSION\","
+            "      \"args\": [7]"
+            "    },"
+            "    {"
+            "      \"op\": \"OR_SUBRULES\","
+            "      \"subrules\": ["
+            "        {"
+            "          \"op\": \"GREATER_THAN\","
+            "          \"property\": \"SCREEN_DENSITY\","
+            "          \"args\": [10]"
+            "        },"
+            "        {"
+            "          \"op\": \"LESS_THAN\","
+            "          \"property\": \"SCREEN_DENSITY\","
+            "          \"args\": [5]"
+            "        }"
+            "      ]"
+            "     }"
+            "  ]"
+            "}");
+    // Trim
+    expected.erase(std::remove_if(expected.begin(), expected.end(), ::isspace), expected.end());
+
+    std::string result(rule->toJson().string());
+
+    // Trim
+    result.erase(std::remove_if(result.begin(), result.end(), ::isspace), result.end());
+
+    ASSERT_EQ(expected, result);
+}
+
+TEST(RuleTest, simplifiesSingleSubruleRules) {
+    sp<Rule> rule = new Rule();
+    rule->op = Rule::AND_SUBRULES;
+
+    sp<Rule> subrule = new Rule();
+    subrule->op = Rule::EQUALS;
+    subrule->key = Rule::SDK_VERSION;
+    subrule->longArgs.add(7);
+    rule->subrules.add(subrule);
+
+    sp<Rule> simplified = Rule::simplify(rule);
+    EXPECT_EQ(Rule::EQUALS, simplified->op);
+    EXPECT_EQ(Rule::SDK_VERSION, simplified->key);
+    ASSERT_EQ(1u, simplified->longArgs.size());
+    EXPECT_EQ(7, simplified->longArgs[0]);
+}
+
+TEST(RuleTest, simplifiesNestedSameOpSubrules) {
+    sp<Rule> rule = new Rule();
+    rule->op = Rule::AND_SUBRULES;
+
+    sp<Rule> subrule = new Rule();
+    subrule->op = Rule::AND_SUBRULES;
+    rule->subrules.add(subrule);
+
+    sp<Rule> subsubrule = new Rule();
+    subsubrule->op = Rule::EQUALS;
+    subsubrule->key = Rule::SDK_VERSION;
+    subsubrule->longArgs.add(7);
+    subrule->subrules.add(subsubrule);
+
+    subrule = new Rule();
+    subrule->op = Rule::EQUALS;
+    subrule->key = Rule::SDK_VERSION;
+    subrule->longArgs.add(8);
+    rule->subrules.add(subrule);
+
+    sp<Rule> simplified = Rule::simplify(rule);
+    EXPECT_EQ(Rule::AND_SUBRULES, simplified->op);
+    ASSERT_EQ(2u, simplified->subrules.size());
+
+    sp<Rule> simplifiedSubrule = simplified->subrules[0];
+    EXPECT_EQ(Rule::EQUALS, simplifiedSubrule->op);
+    EXPECT_EQ(Rule::SDK_VERSION, simplifiedSubrule->key);
+    ASSERT_EQ(1u, simplifiedSubrule->longArgs.size());
+    EXPECT_EQ(7, simplifiedSubrule->longArgs[0]);
+
+    simplifiedSubrule = simplified->subrules[1];
+    EXPECT_EQ(Rule::EQUALS, simplifiedSubrule->op);
+    EXPECT_EQ(Rule::SDK_VERSION, simplifiedSubrule->key);
+    ASSERT_EQ(1u, simplifiedSubrule->longArgs.size());
+    EXPECT_EQ(8, simplifiedSubrule->longArgs[0]);
+}
+
+} // namespace split
diff --git a/tools/split-select/SplitDescription.cpp b/tools/split-select/SplitDescription.cpp
new file mode 100644
index 0000000..8037ef0
--- /dev/null
+++ b/tools/split-select/SplitDescription.cpp
@@ -0,0 +1,175 @@
+/*
+ * 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 "SplitDescription.h"
+
+#include "aapt/AaptConfig.h"
+#include "aapt/AaptUtil.h"
+
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+using namespace android;
+
+namespace split {
+
+SplitDescription::SplitDescription()
+: abi(abi::Variant::none) {
+}
+
+int SplitDescription::compare(const SplitDescription& rhs) const {
+    int cmp;
+    cmp = (int)abi - (int)rhs.abi;
+    if (cmp != 0) return cmp;
+    return config.compareLogical(rhs.config);
+}
+
+bool SplitDescription::isBetterThan(const SplitDescription& o, const SplitDescription& target) const {
+    if (abi != abi::Variant::none || o.abi != abi::Variant::none) {
+        abi::Family family = abi::getFamily(abi);
+        abi::Family oFamily = abi::getFamily(o.abi);
+        if (family != oFamily) {
+            return family != abi::Family::none;
+        }
+
+        if (int(target.abi) - int(abi) < int(target.abi) - int(o.abi)) {
+            return true;
+        }
+    }
+    return config.isBetterThan(o.config, &target.config);
+}
+
+bool SplitDescription::match(const SplitDescription& o) const {
+    if (abi != abi::Variant::none) {
+        abi::Family family = abi::getFamily(abi);
+        abi::Family oFamily = abi::getFamily(o.abi);
+        if (family != oFamily) {
+            return false;
+        }
+
+        if (int(abi) > int(o.abi)) {
+            return false;
+        }
+    }
+    return config.match(o.config);
+}
+
+String8 SplitDescription::toString() const {
+    String8 extension;
+    if (abi != abi::Variant::none) {
+        if (extension.isEmpty()) {
+            extension.append(":");
+        } else {
+            extension.append("-");
+        }
+        extension.append(abi::toString(abi));
+    }
+    String8 str(config.toString());
+    str.append(extension);
+    return str;
+}
+
+ssize_t parseAbi(const Vector<String8>& parts, const ssize_t index,
+        SplitDescription* outSplit) {
+    const ssize_t N = parts.size();
+    abi::Variant abi = abi::Variant::none;
+    ssize_t endIndex = index;
+    if (parts[endIndex] == "arm64") {
+        endIndex++;
+        if (endIndex < N) {
+            if (parts[endIndex] == "v8a") {
+                endIndex++;
+                abi = abi::Variant::arm64_v8a;
+            }
+        }
+    } else if (parts[endIndex] == "armeabi") {
+        endIndex++;
+        abi = abi::Variant::armeabi;
+        if (endIndex < N) {
+            if (parts[endIndex] == "v7a") {
+                endIndex++;
+                abi = abi::Variant::armeabi_v7a;
+            }
+        }
+    } else if (parts[endIndex] == "x86") {
+        endIndex++;
+        abi = abi::Variant::x86;
+    } else if (parts[endIndex] == "x86_64") {
+        endIndex++;
+        abi = abi::Variant::x86_64;
+    } else if (parts[endIndex] == "mips") {
+        endIndex++;
+        abi = abi::Variant::mips;
+    } else if (parts[endIndex] == "mips64") {
+        endIndex++;
+        abi = abi::Variant::mips64;
+    }
+
+    if (abi == abi::Variant::none && endIndex != index) {
+        return -1;
+    }
+
+    if (outSplit != NULL) {
+        outSplit->abi = abi;
+    }
+    return endIndex;
+}
+
+bool SplitDescription::parse(const String8& str, SplitDescription* outSplit) {
+    ssize_t index = str.find(":");
+
+    String8 configStr;
+    String8 extensionStr;
+    if (index >= 0) {
+        configStr.setTo(str.string(), index);
+        extensionStr.setTo(str.string() + index + 1);
+    } else {
+        configStr.setTo(str);
+    }
+
+    SplitDescription split;
+    if (!AaptConfig::parse(configStr, &split.config)) {
+        return false;
+    }
+
+    Vector<String8> parts = AaptUtil::splitAndLowerCase(extensionStr, '-');
+    const ssize_t N = parts.size();
+    index = 0;
+
+    if (extensionStr.length() == 0) {
+        goto success;
+    }
+
+    index = parseAbi(parts, index, &split);
+    if (index < 0) {
+        return false;
+    } else {
+        if (index == N) {
+            goto success;
+        }
+    }
+
+    // Unrecognized
+    return false;
+
+success:
+    if (outSplit != NULL) {
+        *outSplit = split;
+    }
+    return true;
+}
+
+} // namespace split
diff --git a/tools/split-select/SplitDescription.h b/tools/split-select/SplitDescription.h
new file mode 100644
index 0000000..5fcafc8
--- /dev/null
+++ b/tools/split-select/SplitDescription.h
@@ -0,0 +1,65 @@
+/*
+ * 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 H_ANDROID_SPLIT_SPLIT_DESCRIPTION
+#define H_ANDROID_SPLIT_SPLIT_DESCRIPTION
+
+#include "aapt/ConfigDescription.h"
+#include "Abi.h"
+
+#include <utils/String8.h>
+#include <utils/Vector.h>
+
+namespace split {
+
+struct SplitDescription {
+    SplitDescription();
+    SplitDescription(const SplitDescription&) = default;
+
+    ConfigDescription config;
+    abi::Variant abi;
+
+    int compare(const SplitDescription& rhs) const;
+    inline bool operator<(const SplitDescription& rhs) const;
+    inline bool operator==(const SplitDescription& rhs) const;
+    inline bool operator!=(const SplitDescription& rhs) const;
+
+    bool match(const SplitDescription& o) const;
+    bool isBetterThan(const SplitDescription& o, const SplitDescription& target) const;
+
+    android::String8 toString() const;
+
+    static bool parse(const android::String8& str, SplitDescription* outSplit);
+};
+
+ssize_t parseAbi(const android::Vector<android::String8>& parts, const ssize_t index,
+        SplitDescription* outSplit);
+
+bool SplitDescription::operator<(const SplitDescription& rhs) const {
+    return compare(rhs) < 0;
+}
+
+bool SplitDescription::operator==(const SplitDescription& rhs) const {
+    return compare(rhs) == 0;
+}
+
+bool SplitDescription::operator!=(const SplitDescription& rhs) const {
+    return compare(rhs) != 0;
+}
+
+} // namespace split
+
+#endif // H_ANDROID_SPLIT_SPLIT_DESCRIPTION